C++写算24点(续)

本文介绍了如何用C++实现24点游戏的广度优先搜索算法,详细阐述了广度优先算法的思想及其实现过程,并提供了算法的实现示例。

C++算24点

大家应该认识我吧?就是那个写24点的。(不认识点此
今天我将再次讲C++算24点。
我说在前面:你必须会C++的基本知识(如for、while、函数、printf等)如果不会,我敢肯定你看不懂,只是把大妈(代码)给复制、粘贴而已,所以如果你不会,就关上这个网页,看别的去吧!
有两种方法。
第一种方法:(是以游戏的形式)
第二种方法(不是游戏的形式)
说了那么多,开始讲了!
先讲第二个。(为什么不先讲第一个?因为我喜欢从后开始)
来一个小插曲:

广度优先算法

广度优先算法(Breadth-First Search),同广度优先搜索,又称作宽度优先搜索,或横向优先搜索,简称BFS,是一种图形搜索演算法。简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点,如果发现目标,则演算终止。广度优先搜索的实现一般采用open-closed表。

广度优先算法——思想

BFS是一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。BFS并不使用经验法则算法。
从算法的观点,所有因为展开节点而得到的子节点都会被加进一个先进先出的伫列中。一般的实作里,其邻居节点尚未被检验过的节点会被放置在一个被称为open的容器中(例如伫列或是链表),而被检验过的节点则被放置在被称为closed的容器中。(open-closed表)

广度优先算法——实现

所谓广度,就是一层一层的,向下遍历,层层堵截,还是这幅图,我们如果要是广度优先遍历的话,我们的结果是V1 V2 V3 V4 V5 V6 V7 V8。
无
1、访问顶点vi ;
2、访问vi 的所有未被访问的邻接点w1 ,w2 , …wk ;
3、依次从这些邻接点(在步骤②中访问的顶点)出发,访问它们的所有未被访问的邻接点; 依此类推,直到图中所有访问过的顶点的邻接点都被访问;
好了,插曲到此结束。

24点的广度优先算法

无
很抱歉,手画的。
就像这个,先从根节点的四个数开始,搜到第一个左子树+,变成3个数有搜到第一个+的左子树+又搜到左子树+发现成立后打印,之后退到第二个+重新搜索。

大概就是这样子了···
再见!
附代码:
第一种:(游戏)

#include<iostream>
#include<cmath>/*fabs()*/
#include<cstdlib>/*exit(),srand(),rand()*/
#include<vector>/*vector*/
#include<string>/*string*/
#include<ctime>/*time()*/
using namespace std;
const double Precision=1e-10;/*比较的精度*/
const double M=24;/*凑数结果*/
const int N1=13,N2=4;/*4个从1到13的数*/
const int C1=5,C2=10,C3=15,C4=20;/*盘数*/
class Gamer;/*玩家的信息*/
class Four;/*把满足条件的四个数及其符号储存起来*/
ostream& operator<<(ostream& out,const Four &obj);/*输出Four类的对象*/
double count(double a1,int b,double a2,bool& abnormal);/*计算在运算符b(b==1时,代表+;...)的作用下,数字a1与a2的运算结果*/
bool judge(double a1,int b1,double a2,int b2,double a3,int b3,double a4,int& code);/*判断是否能凑成M*/
bool judge1(double a1,int b1,double a2,int b2,double a3,int b3,double a4);/*((a1@a2)@a3)@a4*/
bool judge2(double a1,int b1,double a2,int b2,double a3,int b3,double a4);/*(a1@(a2@a3))@a4*/
bool judge3(double a1,int b1,double a2,int b2,double a3,int b3,double a4);/*(a1@a2)@(a3@a4)*/
bool judge4(double a1,int b1,double a2,int b2,double a3,int b3,double a4);/*a1@((a2@a3)@a4)*/
bool judge5(double a1,int b1,double a2,int b2,double a3,int b3,double a4);/*a1@(a2@(a3@a4))*/
void print(ostream& out,int b);//打印算符
void GameOn();
class Gamer
{
   
   
private:
int score;/*得分*/
int bout;/*盘数*/
string name;/*姓名*/
public:
Gamer(string n,int b=C1);/*设置玩家姓名,初始化分数*/
int getScore() const;
void setScore(char c);/*对玩家分数进行加减操作*/
void print() const;/*打印玩家信息*/
};
Gamer::Gamer(string n,int b)
{
   
   
name=n;
bout=b;
score=bout;/*初始分数等于盘数*/
}
int Gamer::getScore() const
{
   
   
return score;
}
void Gamer::setScore(char c)
{
   
   
switch(c)/*c='+'或'-'*/
{
   
   
case '+':score++;break;/*回答正确,加分*/
case '-':score--;break;/*回答错误,减分*/
default:cout<<"参数错误!!!"<<endl;
}
}
void Gamer::print() const
{
   
   
cout<<"玩家"<<name<<"的得分情况:"<<endl;
cout<<"盘数:"<<bout<<"\t"<<"初始分:"<<bout<<"\t"<<"最后得分:"<<score<<endl;
}
class Four
{
   
   
private:
int Sign[3];/*储存运算符*/
int Q[N2];/*储存原始顺序,即未排序前的顺序,是输出函数的依据*/
int method;/*方法的代号,记下由这四个数字得到24的一种方法(有可能有多种得到24的方法,但只选最先找到的那种方法)*/
public:
Four(int a=0,int b=0,int c=0,int d=0,int m=0,int s1=0,int s2=0,int s3=0);/*构造函数,初始化成员数据*/
void reSet(int a,int b,int c,int d,int m,int s1,int s2,int s3);
friend ostream& operator<<(ostream& out,const Four &obj);/*友元函数*/
};
Four::Four(int a,int b,int c,int d,int m,int s1,int s2,int s3)
{
   
   
Q[0]=a;
Q[1]=b;
Q[2]=c;
Q[3]=d;
method=m;
Sign[0]=s1;
Sign[1]=s2;
Sign[2]=s3;
}
void Four::reSet(int a,int b,int c,int d,int m,int s1,int s2,int s3)
{
   
   
Q[0]=a;
Q[1]=b;
Q[2]=c;
Q[3]=d;
method=m;
Sign[0]=s1;
Sign[1]=s2;
Sign[2]=s3;
}
ostream& operator<<(ostream& out,const Four &obj)
{
   
   
switch(obj.method)
{
   
   
case 1:/*((a1@a2)@a3)@a4*/
{
   
   
out<<"(("<<obj.Q[0];
print(out,obj.Sign[0]);
out<<obj.Q[1]<<")";
print(out,obj.Sign[1]);
out<<obj.Q[2]<<")";
print(out,obj.Sign[2]);
out<<obj.Q[3
实现一个基于 C++11 的简单文件传输程序,我们可以采用 **TCP 协议**通过套接字(socket)在本地网络中进行文件传输。该程序包含两个部分: - **服务器端(Server)**:监听连接并接收文件。 - **客户端(Client)**:连接服务器并发送文件。 我们将使用标准 C++11 特性(如 `std::thread`、`std::vector`、`std::unique_ptr` 等),并调用操作系统提供的 socket API(在 Linux/macOS 上为 POSIX sockets,在 Windows 上为 Winsock)。以下代码以 **Linux/Unix 风格 socket 编程**为主,若你在 Windows 上运行,请使用支持 POSIX 的环境(如 WSL 或 MinGW),或稍作适配。 --- ### ✅ 功能说明 - 客户端向服务器发送一个文件(二进制安全)。 - 使用固定缓冲区逐块传输。 - 服务器将接收到的文件保存到指定路径。 - 支持任意类型文件(文本、图片、压缩包等)。 --- ### 📁 server.cpp(服务器:接收文件) ```cpp // server.cpp - 文件接收端 (C++11) #include <iostream> #include <fstream> #include <sstream> #include <cstring> #include <thread> #include <vector> #ifdef _WIN32 #include <winsock2.h> #pragma comment(lib, "ws2_32.lib") #else #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #endif constexpr int PORT = 8080; constexpr size_t BUFFER_SIZE = 4096; void handle_client(int client_sock) { char buffer[BUFFER_SIZE]; ssize_t bytes_read; // 读取文件名长度 uint32_t filename_len; bytes_read = recv(client_sock, reinterpret_cast<char*>(&filename_len), sizeof(filename_len), 0); if (bytes_read <= 0) { std::cerr << "Failed to receive filename length.\n"; close(client_sock); return; } // 读取文件名 std::string filename; filename.resize(ntohl(filename_len)); bytes_read = recv(client_sock, &filename[0], filename.size(), 0); if (bytes_read <= 0) { std::cerr << "Failed to receive filename.\n"; close(client_sock); return; } // 打开输出文件 std::ofstream file(filename, std::ios::binary); if (!file) { std::cerr << "Cannot create file: " << filename << std::endl; close(client_sock); return; } // 读取文件大小 uint64_t file_size; bytes_read = recv(client_sock, reinterpret_cast<char*>(&file_size), sizeof(file_size), 0); file_size = be64toh(file_size); // 大端转主机 if (bytes_read <= 0) { std::cerr << "Failed to receive file size.\n"; return; } std::cout << "Receiving file: " << filename << " (size: " << file_size << " bytes)\n"; // 接收文件数据 size_t total_received = 0; while (total_received < file_size) { bytes_read = recv(client_sock, buffer, std::min(BUFFER_SIZE, file_size - total_received), 0); if (bytes_read <= 0) break; file.write(buffer, bytes_read); total_received += bytes_read; } file.close(); std::cout << "File received successfully: " << filename << "\n"; close(client_sock); } int main() { #ifdef _WIN32 WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { std::cerr << "WSAStartup failed.\n"; return -1; } #endif int server_sock = socket(AF_INET, SOCK_STREAM, 0); if (server_sock == -1) { perror("Socket creation failed"); return -1; } int opt = 1; setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&opt), sizeof(opt)); sockaddr_in server_addr{}; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(PORT); if (bind(server_sock, reinterpret_cast<sockaddr*>(&server_addr), sizeof(server_addr)) < 0) { perror("Bind failed"); close(server_sock); return -1; } if (listen(server_sock, 5) < 0) { perror("Listen failed"); close(server_sock); return -1; } std::cout << "Server listening on port " << PORT << "...\n"; while (true) { sockaddr_in client_addr{}; socklen_t client_len = sizeof(client_addr); int client_sock = accept(server_sock, reinterpret_cast<sockaddr*>(&client_addr), &client_len); if (client_sock < 0) { perror("Accept failed"); continue; } std::cout << "Client connected: " << inet_ntoa(client_addr.sin_addr) << std::endl; std::thread t(handle_client, client_sock); t.detach(); // 分离线程处理客户端 } #ifdef _WIN32 closesocket(server_sock); WSACleanup(); #else close(server_sock); #endif return 0; } ``` --- ### 📂 client.cpp(客户端:发送文件) ```cpp // client.cpp - 文件发送端 (C++11) #include <iostream> #include <fstream> #include <sstream> #include <cstring> #include <vector> #ifdef _WIN32 #include <winsock2.h> #pragma comment(lib, "ws2_32.lib") #else #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #endif constexpr const char* SERVER_IP = "127.0.0.1"; // 修改为目标 IP constexpr int PORT = 8080; constexpr size_t BUFFER_SIZE = 4096; // 辅助函数:主机序转大端64位 uint64_t htobe64(uint64_t value) { #ifdef __APPLE__ return OSSwapHostToBigInt64(value); #elif defined(__linux__) || defined(__unix__) return htobe64(value); #else // 手动转换(小端机器) return ((value & 0xFFULL) << 56) | (((value >> 8) & 0xFF) << 48) | (((value >> 16) & 0xFF) << 40) | (((value >> 24) & 0xFF) << 32) | (((value >> 32) & 0xFF) << 24) | (((value >> 40) & 0xFF) << 16) | (((value >> 48) & 0xFF) << 8) | ((value >> 56) & 0xFF); #endif } int main(int argc, char* argv[]) { if (argc != 2 && argc != 3) { std::cerr << "Usage: " << argv[0] << " <filename> [server_ip]\n"; return -1; } std::string filename = argv[1]; std::string ip = (argc == 3) ? argv[2] : SERVER_IP; #ifdef _WIN32 WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { std::cerr << "WSAStartup failed.\n"; return -1; } #endif int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { perror("Socket creation failed"); return -1; } sockaddr_in server_addr{}; server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); if (inet_pton(AF_INET, ip.c_str(), &server_addr.sin_addr) <= 0) { std::cerr << "Invalid address: " << ip << std::endl; close(sock); return -1; } if (connect(sock, reinterpret_cast<sockaddr*>(&server_addr), sizeof(server_addr)) < 0) { perror("Connection failed"); close(sock); return -1; } std::cout << "Connected to server at " << ip << ":" << PORT << std::endl; // 打开文件 std::ifstream file(filename, std::ios::binary | std::ios::ate); if (!file) { std::cerr << "Cannot open file: " << filename << std::endl; close(sock); return -1; } auto file_size = file.tellg(); file.seekg(0, std::ios::beg); // 提取文件名 std::string base_filename = filename; auto last_slash = filename.find_last_of("/\\"); if (last_slash != std::string::npos) base_filename = filename.substr(last_slash + 1); // 发送文件名长度和文件名 uint32_t filename_len = htonl(static_cast<uint32_t>(base_filename.size())); send(sock, reinterpret_cast<const char*>(&filename_len), sizeof(filename_len), 0); send(sock, base_filename.c_str(), base_filename.size(), 0); // 发送文件大小(大端) uint64_t net_file_size = htobe64(static_cast<uint64_t>(file_size)); send(sock, reinterpret_cast<const char*>(&net_file_size), sizeof(net_file_size), 0); // 发送文件内容 std::vector<char> buffer(BUFFER_SIZE); size_t total_sent = 0; while (total_sent < static_cast<size_t>(file_size)) { file.read(buffer.data(), BUFFER_SIZE); size_t sent_now = file.gcount(); if (sent_now <= 0) break; const char* buf_ptr = buffer.data(); while (sent_now > 0) { ssize_t s = send(sock, buf_ptr, sent_now, 0); if (s <= 0) { std::cerr << "Send error during transmission.\n"; close(sock); file.close(); return -1; } buf_ptr += s; sent_now -= s; total_sent += s; } } file.close(); std::cout << "File sent successfully: " << filename << " (" << total_sent << " bytes)\n"; close(sock); #ifdef _WIN32 WSACleanup(); #endif return 0; } ``` --- ### 🔧 编译与运行(Linux/macOS) ```bash # 编译服务器 g++ -std=c++11 -o server server.cpp # 编译客户端 g++ -std=c++11 -o client client.cpp # 终端1:启动服务器 ./server # 终端2:发送文件(例如 test.txt) ./client test.txt ``` > 注意:Windows 用户需链接 `ws2_32.lib`,或使用 MinGW/GCC。 --- ### ⚠️ 注意事项 - 当前为单向传输(客户端 → 服务器)。 - 不含加密、校验、断传等高级功能。 - 可扩展为双向、多文件、进度条、异步 IO 等。 --- ### ✅ 解释 - **C++11 特性使用**: - `std::thread` 实现并发处理多个客户端。 - `std::vector`, `std::string` 安全管理内存。 - `constexpr` 定义常量。 - **Socket 编程流程**: - 服务器:`socket → bind → listen → accept → recv/send` - 客户端:`socket → connect → send/recv` - **跨平台注意**: - Windows 需要初始化 Winsock。 - 字节序转换使用 `htonl`, `htobe64` 确保一致性。 - **文件传输协议设计**: - 先传元信息(文件名、大小),再传内容。 - 二进制安全,支持所有文件类型。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值