棋类游戏大全(补订版)
2026-08-18 19:57:26
发布于:四川
又又又又更新了,留个赞再走吧!
公告
为了让大家更新我们的项目更快捷和便利,我们马上要推出新的更新方式(自动更新),我们将代码备份到GitHub上,使用windows_API的请求函数,自动更新代码内容,敬请期待。
注:当然如果您不喜欢这种自动更新的更新方式或是对更新内容有异议,在新版本的设置中可以关闭自动更新功能。
发表预定时间:8/19
最新版本在此,共计2319行,记得点赞哦!
声明一下:bor以后的最新版本无法在ACGO OJ上发表(应为ACGO有文章长度限制,下图是文章总字数和总行数,数据来源-CSDN文章发表),所有的最新版本都统一在CSDN上发表!

更新日志:
- 8/5 [改动]修改了2号模式的AI算法(防守特判) 难度上升
- 8/5 [改动]修改了2号模式的AI算法(攻击特判) 难度上升
- 8/5 [改动]算法:随机落子->特判+随机落子+中间格优势判定
- 8/5 [改动]修改10~20分钟前的版本的旗子打印漏洞
- 8/5 [预告]预计在一周后添加五子棋的AI单人玩法
- 8/6 [通知]AI单人玩法五子棋上线
- 8/6 [改动]修复4号模式中playerM函数和playerMove函数的使用错误导致的致命错误(严重影响游戏运行)
- 8/7 [通知]添加2种局域网联机玩法
- 8/7 [改动]修改所有玩法的输入,使其不再陷入死循环
- 8/7 [改动]添加预加载模块(可能有点慢,可使用开发者模式加速)
- 8/7 [日总结]新增局域网TCP联机五子棋、联机井字棋,数据包哈希校验,jz预加载网络模块
- 8/8 [通知]添加2种象棋类游戏,详见作者主页
- 8/8 [警告|warning]所有象棋部分的代码还在公测阶段,可能存在问题
- 8/9 [改动]美化界面,添加小贴士功能
- 8/16[公告]本项目废除luogu子项目计划,洛谷的所有项目停止改动,但永久保存,用户可将原luogu子项目计划当作项目1.0版本的快照,若不喜欢后期用户交互模块的用户可通过luogu子项目计划的项目节点找回1.0快照版本。
感谢一下
用户@༺ཌༀཉི༒꧁qet꧂༒༃ༀད༻提供的死循环BUG
欢迎更多用户来提出问题!
公告
为了让大家更新我们的项目更快捷和便利,我们马上要推出新的更新方式(自动更新),我们将代码备份到GitHub上,使用windows_API的请求函数,自动更新代码内容,敬请期待。
注:当然如果您不喜欢这种自动更新的更新方式或是对更新内容有异议,在新版本的设置中可以关闭自动更新功能。
代码
//棋类游戏大全
/*
更新日志:
8/5 修改了2号模式的AI算法(防守特判) 难度上升
8/5 修改了2号模式的AI算法(攻击特判) 难度上升
8/5 算法:随机落子->特判+随机落子+中间格优势判定
8/5 修改10~20分钟前的版本的旗子打印漏洞
8/5 预计在一周后添加五子棋的AI单人玩法
8/6 AI单人玩法五子棋上线
8/6 修复4号模式中playerM函数和playerMove函数的使用错误导致的致命错误(严重影响游戏运行)
8/7 新增局域网TCP联机五子棋、联机井字棋,数据包哈希校验,jz预加载网络模块
8/8 新增界面功能
8/8 VIP限免,美化界面
8/8 微调数据
8/8 添加象棋及国际象棋玩法,提示由于c++无法渲染棋盘和棋子,所以此项目由python编写,敬请谅解!
8/16[公告]本项目废除luogu子项目计划,洛谷的所有项目停止改动,但永久保存,用户可将原luogu子项目计划当作项目1.0版本的快照,若不喜欢后期用户交互模块的用户可通过luogu子项目计划的项目节点找回1.0快照版本。
修改需求:普通kfz=0执行原版加载动画,kfz=1执行加载动画但缩短等待时间
*/
//【关键1:头文件顺序强制前置winsock2.h】
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#include <windows.h>
#include <conio.h>
#include <ctime>
#include <shellapi.h>
//【关键2:禁用std命名空间避免std::bind冲突】
#undef bind
#include<bits/stdc++.h>
using namespace std;
const int N = 15;
int nx,ny;
int x_,y_;
string name1,name2;
char oc = '.';
bool color = 1;
char table[N][N];
bool ff,fff;
bool kfz=0;
//1=方向键模式;2=WASD模式
int controlMode = 1;
const int Size = 15;
int jz(int i=2);
//==================== 网络&哈希全局定义(预加载对象) ====================
#define PORT 9999
#define BUF_LEN 256
SOCKET serverSock, clientSock, curSock;
SOCKADDR_IN serverAddr, clientAddr;
WSADATA wsaData;
bool netInitOk = false;
//简易8位哈希函数
unsigned char simpleHash(const char* data, int len)
{
unsigned char res = 0x37;
for(int i=0;i<len;i++)
{
res ^= data[i];
res = (res << 1) | (res >> 7);
}
return res;
}
//打包数据包:长度+数据+哈希
int packData(char* buf, const char* raw, int rawLen)
{
buf[0] = rawLen;
memcpy(buf+1, raw, rawLen);
buf[rawLen+1] = simpleHash(raw, rawLen);
return rawLen+2;
}
//解包校验,成功返回有效长度,失败-1
int unpackData(char* buf, char* out)
{
int len = buf[0];
if(len <=0 || len > BUF_LEN-2) return -1;
unsigned char h = simpleHash(buf+1, len);
if(h != buf[len+1]) return -1;
memcpy(out, buf+1, len);
return len;
}
//网络关闭统一封装
void closeNetSocket()
{
if(curSock != INVALID_SOCKET) closesocket(curSock);
if(serverSock != INVALID_SOCKET) closesocket(serverSock);
if(clientSock != INVALID_SOCKET) closesocket(clientSock);
WSACleanup();
netInitOk = false;
}
//==================== 原有工具函数 ====================
void ask(char com[256])
{
string msg = "正在跳转至";
msg += com;
msg += ",是否打开该网页?";
int ret1 = MessageBoxA(0, msg.c_str(), "确认", MB_YESNO | MB_ICONASTERISK);
if (ret1 == IDYES)
{
ShellExecuteA(0, "open", com, NULL, NULL, SW_SHOW);
}
}
string URL[]={
"",
"https://www.acgo.cn/discuss/rest/88744",
"https://www.luogu.com.cn/article/jguyqy95/",
"https://www.acgo.cn/discuss/rest/89213",
"https://www.acgo.cn/discuss/rest/89211"
};
string ts[]={
"",
"你知道吗?这款娱乐软件源于<bits/stdc++.h>(ACGO OJ) 1~2年前随手编写的游戏代码:棋类游戏大全",
"你知道吗?这款娱乐软件在1~2年前就已经诞生,于 2026/08/06 日重启项目",
"你知道吗?<bits/stdc++.h>和xgy111111的CSDN号分别叫这代码保熟吗和小西瓜学编程",
"你知道吗?VIP的密码是发布文章的网址",
"感谢游玩,祝您游玩愉快!"
};
void get_URL(bool x,int a){
if(x==false){
URL[1]=" ";
URL[2]=" ";
}else if(a==0){
URL[1]="https://www.acgo.cn/discuss/rest/88744";
URL[2]="https://www.luogu.com.cn/article/jguyqy95/";
}
}
//【重点修改jz函数】
//kfz=0普通:原版慢速完整加载
//kfz=1VIP:保留加载动画,Sleep全部缩短,提速
//新增:预加载网络环境、哈希工具、Socket初始化
int jz(int i)
{
get_URL(false,0);
fff=0;
//===============联机模块预加载(动画前完成初始化)===============
closeNetSocket();
//初始化Winsock
if(WSAStartup(MAKEWORD(2,2),&wsaData)==0)
{
netInitOk = true;
serverSock = socket(AF_INET,SOCK_STREAM,0);
clientSock = socket(AF_INET,SOCK_STREAM,0);
curSock = INVALID_SOCKET;
ZeroMemory(&serverAddr,sizeof(serverAddr));
ZeroMemory(&clientAddr,sizeof(clientAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.S_un.S_addr = INADDR_ANY;
}
//全局游戏变量初始化
nx = 6; ny = 6;
x_ = 0; y_ = 0;
oc = '.';
color = 1;
ff = false;
bool nowKfz = kfz;
//双人五子棋棋盘预初始化
for(int p=0;p<N;p++)
{
for(int q=0;q<N;q++)
{
if(p==6 && q==6) table[p][q] = '+';
else if(!p || !q || p==N-1 || q==N-1) table[p][q] = '#';
else table[p][q] = '.';
}
}
//AI五子棋、井字棋内存预开辟
char aiBoardPre[Size][Size];
char tttSinglePre[3][3], tttDoublePre[3][3];
for(int p=0;p<Size;p++)
for(int q=0;q<Size;q++) aiBoardPre[p][q]=' ';
for(int p=0;p<3;p++)
for(int q=0;q<3;q++) tttSinglePre[p][q]=tttDoublePre[p][q]=' ';
static HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
//=============================================================
system("cls");
if(i==1){
int a=rand()%5+1;
for(int k=0;k<3;k++){
cout<<"\n正在返回主界面...\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"<<ts[a]<<"\n\n\n加载中";
Sleep(200);
for(int t=1;t<=3;t++){
Sleep(150);
cout<<'.';
}
system("cls");
}
}else if(i==2&&kfz==1){
int a=rand()%5+1;
for(int k=0;k<3;k++){
cout<<"\n正在预加载资源...\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"<<ts[a]<<"\n\n\n加载中";
Sleep(40);
for(int t=1;t<=3;t++){
Sleep(40);
cout<<'.';
}
system("cls");
}
}else if(i==2){
int a=rand()%5+1;
for(int k=0;k<3;k++){
cout<<"\n正在预加载资源...\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"<<ts[a]<<"\n\n\n加载中";
Sleep(200);
for(int t=1;t<=3;t++){
Sleep(200);
cout<<'.';
}
system("cls");
}
}
// else if(nowKfz == 0)
// {
// for(int k=0;k<3;k++){
// cout<<"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n加载中";
// Sleep(200);
// for(int t=1;t<=3;t++){
// Sleep(200);
// cout<<'.';
// }
// system("cls");
// }
// }
// else
// {
// for(int k=0;k<3;k++){
// cout<<"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n加载中";
// Sleep(40);
// for(int t=1;t<=3;t++){
// Sleep(40);
// cout<<'.';
// }
// system("cls");
// }
// }
fff=1;
get_URL(true,0);
get_URL(true,1);
return 1;
}
void printBoard(char board[Size][Size])
{
cout << " ";
for(int j = 1; j <= Size; j++)
{
cout << setw(2) << j;
}
cout << endl;
cout << " ";
for(int j = 0; j < Size; j++)
{
cout << "# ";
}
cout << endl;
for(int i = 0; i < Size; i++)
{
cout << setw(2) << (i+1) << " ";
cout << "# ";
for(int j = 0; j < Size; j++)
{
if(board[i][j] == ' ')
{
cout << ". ";
}
else
{
cout << board[i][j] << " ";
}
}
cout << "#";
cout << endl;
}
cout << " ";
for(int j = 0; j < Size; j++)
{
cout << "# ";
}
cout << endl;
}
bool checkWin(char board[Size][Size], int x, int y, char player)
{
if(x < 0 || x >= Size || y <0 || y >= Size){
return false;
}
if(board[x][y] != player){
return false;
}
int dx[] = {0, 1, 1, 1};
int dy[] = {1, 0, 1, -1};
for(int dir = 0; dir < 4; dir++)
{
int count = 1;
for(int k = 1; k <=4; k++)
{
int nx = x + dx[dir]*k;
int ny = y + dy[dir]*k;
if(nx>=0&&nx<Size&&ny>=0&&ny<Size && board[nx][ny]==player){
count++;
}else{
break;
}
}
for(int k = 1; k <=4; k++)
{
int nx = x - dx[dir]*k;
int ny = y - dy[dir]*k;
if(nx>=0&&nx<Size&&ny>=0&&ny<Size && board[nx][ny]==player){
count++;
}else{
break;
}
}
if(count >=5){
return true;
}
}
return false;
}
int getScore(char board[Size][Size], int i, int j, char p)
{
if(i<0||i>=Size||j<0||j>=Size){
return 0;
}
if(board[i][j]!=' '){
return 0;
}
int dx[] = {0,1,1,1};
int dy[] = {1,0,1,-1};
int maxcnt = 0;
for(int d=0;d<4;d++)
{
int cnt=1;
for(int k=1;k<=4;k++)
{
int ni = i+dx[d]*k;
int nj = j+dy[d]*k;
if(ni>=0&&ni<Size&&nj>=0&&nj<Size&&board[ni][nj]==p){
cnt++;
}else{
break;
}
}
for(int k=1;k<=4;k++)
{
int ni = i-dx[d]*k;
int nj = j-dx[d]*k;
if(ni>=0&&ni<Size&&nj>=0&&nj<Size&&board[ni][nj]==p){
cnt++;
}else{
break;
}
}
if(cnt>maxcnt){
maxcnt = cnt;
}
}
return maxcnt;
}
void aiPlay(char board[Size][Size], int &aiX, int &aiY)
{
aiX = 7;
aiY =7;
int bestScore = -1;
int dx[] = {0, 1, 1, 1};
int dy[] = {1, 0, 1, -1};
for(int i=0;i<Size;i++)
{
for(int j=0;j<Size;j++)
{
if(board[i][j] != ' '){
continue;
}
int defend = getScore(board,i,j,'X');
int attack = getScore(board,i,j,'O');
int total = 0;
if(defend >=5){total = 9999;}
else if(defend ==4){total = 8000;}
else if(attack ==4){total = 7000;}
else if(defend ==3){total = 5000;}
else if(attack ==3){total = 3000;}
else if(defend ==2){total = 800;}
else if(attack ==2){total = 400;}
if((i==0||i==Size-1)&&(j==0||j==Size-1)) total -= 50;
if(i==0||i==Size-1||j==0||j==Size-1) total -=20;
if((i>=6&&i<=8)&&(j>=6&&j<=8)) total +=100;
if(total <0) total = 10;
int t1 = getScore(board,i,j,'X');
if(t1>=3) total += 600;
if(total>10000) total =10000;
bool isChong3 = false;
for(int dir=0;dir<4;dir++)
{
int cnt_sim = 1;
int left_empty = 0;
int right_empty = 0;
for(int k=1;k<=4;k++)
{
int ni = i + dx[dir]*k;
int nj = j + dy[dir]*k;
if(ni>=0&&ni<Size&&nj>=0&&nj<Size&&board[ni][nj]=='X') cnt_sim++;
else{
if(ni>=0&&ni<Size&&nj>=0&&nj<Size&&board[ni][nj]==' ') right_empty = 1;
break;
}
}
for(int k=1;k<=4;k++)
{
int ni = i - dx[dir]*k;
int nj = j - dy[dir]*k;
if(ni>=0&&ni<Size&&nj>=0&&nj<Size&&board[ni][nj]=='X') cnt_sim++;
else{
if(ni>=0&&ni<Size&&nj>=0&&nj<Size&&board[ni][nj]==' ') left_empty = 1;
break;
}
}
if(cnt_sim == 3 && (left_empty == 1 || right_empty ==1)) isChong3 = true;
}
if(isChong3) total += 1200;
if(total >=8000) total =7900;
if(total > bestScore){
bestScore = total;
aiX = i;
aiY = j;
}
}
}
if(board[aiX][aiY] != ' '){
for(int a=0;a<Size;a++)
for(int b=0;b<Size;b++)
if(board[a][b] == ' '){aiX = a;aiY = b;goto ai_end;}
}
ai_end:
board[aiX][aiY] = 'O';
}
bool isBoardFull(char board[Size][Size])
{
int cnt =0;
for(int i=0;i<Size;i++)
for(int j=0;j<Size;j++)
if(board[i][j] == ' ') cnt++;
return cnt == 0;
}
void wzq()
{
char board[Size][Size];
for(int i=0;i<Size;i++)
for(int j=0;j<Size;j++) board[i][j] = ' ';
string inputx,inputy;
int x,y,aiX, aiY;
int inputX,inputY;
bool gameOver = false;
cout << "=====单人五子棋=====\n";
cout << "输入行 列落子,范围1~15,例如:8 8\n";
cout << "玩家:X AI:O\n\n";
while(!gameOver)
{
printBoard(board);
if(isBoardFull(board)){
cout << "\n棋盘已满!平局!游戏结束\n";
gameOver = true;break;
}
cout << "\n【玩家X】请输入行和 列:";
cin >> inputx >> inputy;
if(inputx.size()==1||inputx.size()==2){
if(inputx.size()==1)inputX=inputx[0]-'0';
else inputX=inputx[0]-'0'*10+inputx[0]-'0';
}else{
cout << "坐标超出范围1~15!重新输入\n";continue;
}
if(inputy.size()==1||inputy.size()==2){
if(inputy.size()==1)inputY=inputy[0]-'0';
else inputY=inputy[0]-'0'*10+inputy[0]-'0';
}else{
cout << "坐标超出范围1~15!重新输入\n";continue;
}
if(inputX<1 || inputX>15||inputY<1 || inputY>15){
cout << "坐标超出范围1~15!重新输入\n";continue;
}
x = inputX - 1; y = inputY - 1;
if(board[x][y] != ' '){
cout << "该位置已经有棋子!重新输入\n";continue;
}
board[x][y] = 'X';
if(checkWin(board,x,y,'X')){
printBoard(board);
cout << "\n恭喜[玩家X]获胜!游戏结束\n";
gameOver = true;break;
}
if(isBoardFull(board)){printBoard(board);cout << "\n平局\n";gameOver=true;break;}
aiPlay(board, aiX, aiY);
cout << "\nAI落子:" << (aiX+1) << " " << (aiY+1) << endl;
if(checkWin(board,aiX,aiY,'O')){
printBoard(board);
cout << "\nAI获胜!游戏结束\n";
gameOver = true;break;
}
if(isBoardFull(board)){printBoard(board);cout << "\n平局\n";gameOver=true;break;}
system("pause");system("CLS");
}
system("pause");system("CLS");jz();
}
char f(int x,int y){
char co = table[x][y];
if(co=='.'){ff = 0;return '.';}
int cnt=0;
for(int i=y;i<=y+4 && i<N;i++) if(table[x][i] == co) cnt++;
if(cnt==5){ ff=1; return co; }
cnt = 0;
for(int i=x;i<=x+4 && i<N;i++) if(table[i][y] == co) cnt++;
if(cnt==5){ ff=1; return co; }
cnt = 0;
for(int i=0;i<=4;i++){int nx=x+i, ny=y+i;if(nx<N && ny<N && table[nx][ny]==co)cnt++;else break;}
if(cnt==5){ ff=1; return co; }
cnt = 0;
for(int i=0;i<=4;i++){int nx=x-i, ny=y+i;if(nx>=0 && ny<N && table[nx][ny]==co)cnt++;else break;}
if(cnt==5){ ff=1; return co; }
ff=0;return co;
}
bool dw(){
for(int i=0;i<N;i++)
for(int j=0;j<N;j++){
char dd= f(i,j);
if(ff){
if(dd=='O') cout << "\nPlayer1:" << name1 <<"赢了\n";
else cout <<"\nPlayer2:" << name2 << "赢了\n";
cout<<"\n按下任意键继续......";_getch();system("cls");return false;
}
}
return true;
}
void cgoto(short x,short y){
COORD gxy = {x,y};
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut, gxy);
}
void init(){
color = 1;nx = ny = 6;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++){
if(i==nx && j==ny)table[i][j] = '+';
else if(!i || !j || i==N-1 || j==N-1)table[i][j] = '#';
else table[i][j] = '.';
}
}
void print(){
cgoto(0,0);
for(int i=0;i<N;i++){
for(int j=0;j<N;j++) cout << table[i][j] << " ";
cout << endl;
}
cout<<"#("<<nx<<","<<ny<<")";
if(controlMode ==1)cout<<" 【模式1:方向键】";
else cout<<" 【模式2:WASD】";
cout<<"\nPlayer1: "<<name1<<",棋子形状为O"<<"\nPlayer2:"<<name2<<",棋子形状为X"<<"\n'+'为落子点,'!'为不可落子点,按Z切换控制模式";
}
void move(int px,int py){
table[nx][ny] = oc;oc = '.';
nx += px;ny+=py;
if(nx<1 || ny<1 || nx>13 || ny>13){nx -=px;ny-=py;}
if(table[nx][ny]!='.'){oc = table[nx][ny];table[nx][ny] = '!';}
else table[nx][ny] = '+';
}
void down(){
if(table[nx][ny]!='+')return;
if(color){oc = 'O';table[nx][ny] = 'O';}
else{table[nx][ny] = 'X';oc = 'X';}
color = !color;
}
void Gobang(){
cout<<"# # # # # # # # # # #\n# #\n# # 五子棋\n# # 小游戏\n# #\n# #\n# #\n# #\n# #\n# #\n# # # # # # # # # # #\n按下任意键继续......";
_getch();system("cls");
string s;int len=0;bool end = 1;
cout << "请输入Player1的名字,他的棋子形状是O"<<endl;cin >> name1;
cout << "请输入Player2的名字,他的棋子形状是X"<<endl;cin >> name2;
system("cls");
while(end){
init();print();oc = '.';
while(dw()){
char fkey;fkey = _getch();
bool isArrowKey = false;
if(fkey == 0 || fkey == (char)0xE0){isArrowKey = true;fkey = _getch();}
if(isArrowKey){
if(controlMode == 1){
if(fkey==75){ move(0,-1);print(); }
else if(fkey==72){ move(-1,0);print(); }
else if(fkey==77){ move(0,1);print(); }
else if(fkey==80){ move(1,0);print(); }
}
}else{
if(fkey == 'z' || fkey == 'Z'){controlMode = (controlMode ==1)?2:1;print();}
else if(controlMode ==2){
if(fkey=='a'){ move(0,-1);print(); }
else if(fkey=='s'){ move(1,0);print(); }
else if(fkey=='d'){ move(0,1);print(); }
else if(fkey=='w'){ move(-1,0);print(); }
}
if(fkey==' '){down();print();}
}
}
while(1){
cout << "按下c键进行下一轮 e键结束\n";
char input = _getch();
if(input=='c'){jz();fff=0;break;}
else if(input=='e'){end = 0;break;}
else MessageBoxA(NULL,"输入错误","提示",MB_OK|MB_ICONHAND);
}
}
}
const int BOARD_SIZE = 3;
char board[BOARD_SIZE][BOARD_SIZE];
void drawBoard() {
cout << " 1 2 3" << endl;
cout << "1 " << board[0][0] << " | " << board[0][1] << " | " << board[0][2] << endl;
cout << " --+---+--" << endl;
cout << "2 " << board[1][0] << " | " << board[1][1] << " | " << board[1][2] << endl;
cout << " --+---+--" << endl;
cout << "3 " << board[2][0] << " | " << board[2][1] << " | " << board[2][2] << endl<<endl;
}
bool checkWin(char player) {
for (int i = 0; i < BOARD_SIZE; i++)
if (board[i][0] == player && board[i][1] == player && board[i][2] == player) return true;
for (int j = 0; j < BOARD_SIZE; j++)
if (board[0][j] == player && board[1][j] == player && board[2][j] == player) return true;
if (board[0][0] == player && board[1][1] == player && board[2][2] == player) return true;
if (board[0][2] == player && board[1][1] == player && board[2][0] == player) return true;
return false;
}
bool checkDraw() {
for (int i = 0; i < BOARD_SIZE; i++)
for (int j = 0; j < BOARD_SIZE; j++)
if (board[i][j] == ' ') return false;
return true;
}
void playerMove() {
int row, col;
while (true) {
cout << "请输入落子位置(行 列):";
string Row,Col;
cin >> Row >> Col;
if(Row.size()==1)row=Row[0]-'0';
else{cout << "坐标超出范围1~3!重新输入\n";continue;}
if(Col.size()==1){col=Col[0]-'0';}
else{cout << "坐标超出范围1~3!重新输入\n";continue;}
row--; col--;
if (row < 0 || row >= BOARD_SIZE || col < 0 || col >= BOARD_SIZE)
cout << "坐标无效\n";
else if (board[row][col] != ' ')
cout << "位置占用\n";
else{board[row][col] = 'X';break;}
}
}
int WJ_IS_WINing(){
if(board[0][0] == 'X'&&board[0][1] == 'X'&&board[0][2] == ' ') return 3;
if(board[0][0] == 'X'&&board[0][1] == ' '&&board[0][2] == 'X') return 2;
if(board[0][0] == ' '&&board[0][1] == 'X'&&board[0][2] == 'X') return 1;
if(board[1][0] == 'X'&&board[1][1] == 'X'&&board[1][2] == ' ') return 6;
if(board[1][0] == 'X'&&board[1][1] == ' '&&board[1][2] == 'X') return 5;
if(board[1][0] == ' '&&board[1][1] == 'X'&&board[1][2] == 'X') return 4;
if(board[2][0] == 'X'&&board[2][1] == 'X'&&board[2][2] == ' ') return 9;
if(board[2][0] == 'X'&&board[2][1] == ' '&&board[2][2] == 'X') return 8;
if(board[2][0] == ' '&&board[2][1] == 'X'&&board[2][2] == 'X') return 7;
if(board[0][0] == 'X'&&board[1][1] == 'X'&&board[2][2] == ' ') return 10;
if(board[0][0] == 'X'&&board[1][1] == ' '&&board[2][2] == 'X') return 11;
if(board[0][0] == ' '&&board[1][1] == 'X'&&board[2][2] == 'X') return 12;
if(board[0][2] == 'X'&&board[1][1] == 'X'&&board[2][0] == ' ') return 13;
if(board[0][2] == 'X'&&board[1][1] == ' '&&board[2][0] == 'X') return 14;
if(board[0][2] == ' '&&board[1][1] == 'X'&&board[2][0] == 'X') return 15;
return 0;
}
int DN_IS_WINing(){
if(board[0][0] == 'O'&&board[0][1] == 'O'&&board[0][2] == ' ') return 3;
if(board[0][0] == 'O'&&board[0][1] == ' '&&board[0][2] == 'O') return 2;
if(board[0][0] == ' '&&board[0][1] == 'O'&&board[0][2] == 'O') return 1;
if(board[1][0] == 'O'&&board[1][1] == 'O'&&board[1][2] == ' ') return 6;
if(board[1][0] == 'O'&&board[1][1] == ' '&&board[1][2] == 'O') return 5;
if(board[1][0] == ' '&&board[1][1] == 'O'&&board[1][2] == 'O') return 4;
if(board[2][0] == 'O'&&board[2][1] == 'O'&&board[2][2] == ' ') return 9;
if(board[2][0] == 'O'&&board[2][1] == ' '&&board[2][2] == 'O') return 8;
if(board[2][0] == ' '&&board[2][1] == 'O'&&board[2][2] == 'O') return 7;
if(board[0][0] == 'O'&&board[1][1] == 'O'&&board[2][2] == ' ') return 10;
if(board[0][0] == 'O'&&board[1][1] == ' '&&board[2][2] == 'O') return 11;
if(board[0][0] == ' '&&board[1][1] == 'O'&&board[2][2] == 'O') return 12;
if(board[0][2] == 'O'&&board[1][1] == 'O'&&board[2][0] == ' ') return 13;
if(board[0][2] == 'O'&&board[1][1] == ' '&&board[2][0] == 'O') return 14;
if(board[0][2] == ' '&&board[1][1] == 'O'&&board[2][0] == 'O') return 15;
return 0;
}
void setPos(int code, char ch)
{
switch(code)
{
case 1: board[2][2]=ch;break;case 2: board[0][1]=ch;break;case 3: board[0][2]=ch;break;
case 4: board[2][0]=ch;break;case 5: board[1][1]=ch;break;case 6: board[1][2]=ch;break;
case 7: board[2][0]=ch;break;case 8: board[2][1]=ch;break;case 9: board[2][2]=ch;break;
case10:board[2][2]=ch;break;case11:board[1][1]=ch;break;case12:board[0][0]=ch;break;
case13: board[2][0]=ch;break;case14: board[1][1]=ch;break;case15: board[0][2]=ch;break;
}
}
void computerMove() {
cout << "电脑落子中..." << endl;srand((unsigned int)time(0));
int bu=WJ_IS_WINing(),bu1=DN_IS_WINing();
while (true){
if(bu1!=0){setPos(bu1,'O');break;}
else if(bu!=0){setPos(bu,'O');break;}
else{
if(board[1][1]==' '){board[1][1]='O';break;}
int row = rand() % BOARD_SIZE;
int col = rand() % BOARD_SIZE;
if (board[row][col] == ' ') {board[row][col] = 'O';break;}
}
}
}
void Tic_Tac_Toe(){
int end = 1;
while (1) {
for(int i=0;i<BOARD_SIZE;i++)
for(int j=0;j<BOARD_SIZE;j++) board[i][j]=' ';
cout << "=== 井字棋单人 ===" << endl;
cout << "玩家:X | 电脑:O" << endl << endl;drawBoard();
while(true){
playerMove();
if (checkWin('X')) {drawBoard();cout << "你赢了\n";end = 2;break;}
if (checkDraw()) {drawBoard();cout << "平局\n";end = 2;break;}
computerMove();
if (checkWin('O')) {drawBoard();cout << "电脑获胜\n";end = 2;break;}
if (checkDraw()) {drawBoard();cout << "平局\n";end = 2;break;}
system("cls");cout << "=== 井字棋单人 ===\n玩家X 电脑O\n\n";drawBoard();
}
if (end == 2) {
Sleep(3000);system("cls");
while (1) {
cout << "c下一轮 e退出\n";char input = _getch();
if (input == 'c') {jz();fff=0;system("cls");break;}
else if (input == 'e') return;
else MessageBoxA(NULL,"输入错误","提示",MB_OK|MB_ICONHAND);
}
}
}
}
char c='X';
const int B = 3;char b[B][B];
void drawB() {
cout << " 1 2 3" << endl;
cout << "1 " << b[0][0] << " | " << b[0][1] << " | " << b[0][2] << endl;
cout << " --+---+--" << endl;
cout << "2 " << b[1][0] << " | " << b[1][1] << " | " << b[1][2] << endl;
cout << " --+---+--" << endl;
cout << "3 " << b[2][0] << " | " << b[2][1] << " | " << b[2][2] << endl<<endl;
}
bool Win(char player) {
for (int i = 0; i < 3; i++)
if (b[i][0] == player && b[i][1] == player && b[i][2] == player) return true;
for (int j = 0; j < 3; j++)
if (b[0][j] == player && b[1][j] == player && b[2][j] == player) return true;
if (b[0][0] == player && b[1][1] == player && b[2][2] == player) return true;
if (b[0][2] == player && b[1][1] == player && b[2][0] == player) return true;
return false;
}
bool cD() {
for (int i = 0; i < B; i++)
for (int j = 0; j < B; j++)
if (b[i][j] == ' ') return false;
return true;
}
void playerM() {
int row, col;
while (true) {
if(c=='X')cout << "玩家1落子(行 列):";
else cout << "玩家2落子(行 列):";
string Row,Col;
cin >> Row >> Col;
if(Row.size()==1)row=Row[0]-'0';
else{cout << "坐标超出范围1~3!重新输入\n";continue;}
if(Col.size()==1){col=Col[0]-'0';}
else{cout << "坐标超出范围1~3!重新输入\n";continue;}
row--; col--;
if (row < 0 || row >= B || col < 0 || col >= B)cout<<"无效\n";
else if (b[row][col] != ' ')cout<<"占用\n";
else{b[row][col] = c;break;}
}
c = (c=='O')?'X':'O';
}
void Tic_Tac_Toe_1(){
int end = 1;
while (1) {
for(int i=0;i<B;i++)for(int j=0;j<B;j++)b[i][j]=' ';
c='X';end=1;
while(true){
system("cls");cout << "双人井字棋 X玩家1 O玩家2\n\n";drawB();
playerM();
if(Win('X')){drawB();cout<<"玩家1胜利\n";end=2;break;}
if(cD()){drawB();cout<<"平局\n";end=2;break;}
system("cls");cout << "双人井字棋 X玩家1 O玩家2\n\n";drawB();
playerM();
if(Win('O')){drawB();cout<<"玩家2胜利\n";end=2;break;}
if(cD()){drawB();cout<<"平局\n";end=2;break;}
}
if (end == 2) {
Sleep(3000);system("cls");
while (1) {
cout << "c下一轮 e退出\n";char input = _getch();
if (input == 'c') {jz();fff=0;system("cls");break;}
else if (input == 'e') return;
else MessageBoxA(NULL,"输入错误","提示",MB_OK|MB_ICONHAND);
}
}
}
}
//==================== 联机五子棋核心 ====================
void NetGobang()
{
if(!netInitOk){cout<<"网络初始化失败!回车返回\n";_getch();jz();return;}
int mode;
char ipBuf[20];
cout<<"==== 局域网五子棋 ====\n1 创建房间(主机)\n2 加入房间(客户端)\n请选择:";cin>>mode;
char board[15][15];
for(int i=0;i<15;i++)for(int j=0;j<15;j++)board[i][j]=' ';
bool isHost = (mode==1);
bool myTurn = isHost;
SOCKET sock = INVALID_SOCKET;
if(isHost)
{
//【修复:强转sockaddr*】
jz();
bind(serverSock,(sockaddr*)&serverAddr,sizeof(serverAddr));
listen(serverSock,1);
cout<<"等待客户端连接(端口"<<PORT<<")...\n";
int len=sizeof(clientAddr);
sock = accept(serverSock,(sockaddr*)&clientAddr,&len);
}
else
{
jz();
cout<<"输入主机IP:";cin>>ipBuf;
clientAddr.sin_family=AF_INET;
clientAddr.sin_port=htons(PORT);
clientAddr.sin_addr.S_un.S_addr = inet_addr(ipBuf);
int ret = connect(clientSock,(sockaddr*)&clientAddr,sizeof(clientAddr));
sock = clientSock;
}
if(sock==INVALID_SOCKET){cout<<"连接失败!回车返回\n";_getch();jz();return;}
curSock = sock;
char sendBuf[BUF_LEN],recvBuf[BUF_LEN],raw[BUF_LEN];
cout<<"连接成功!你是"<<(isHost?"先手X":"后手O")<<endl;
Sleep(1000);system("cls");
bool over = false;
while(!over)
{
printBoard(board);
if(isBoardFull(board)){cout<<"平局\n";over=true;break;}
if(myTurn)
{
int x,y;
cout<<"你的回合,请输入行列:";
string inputx,inputy;
cin >> inputx >> inputy;
if(inputx.size()==1||inputx.size()==2){
if(inputx.size()==1)x=inputx[0]-'0';
else x=inputx[0]-'0'*10+inputx[0]-'0';
}else{
cout << "坐标超出范围1~15!重新输入\n";continue;
}
if(inputy.size()==1||inputy.size()==2){
if(inputy.size()==1)y=inputy[0]-'0';
else y=inputy[0]-'0'*10+inputy[0]-'0';
}else{
cout << "坐标超出范围1~15!重新输入\n";continue;
}
x--;y--;
if(x<0||x>=15||y<0||y>=15||board[x][y]!=' '){cout<<"非法位置\n";continue;}
char ch = isHost?'X':'O';
board[x][y]=ch;
//打包发送坐标
char data[2]={(char)x,(char)y};
int packLen = packData(sendBuf,data,2);
send(sock,sendBuf,packLen,0);
if(checkWin(board,x,y,ch)){printBoard(board);cout<<"你获胜!\n";over=true;break;}
myTurn = false;
}
else
{
cout<<"等待对手落子...\n";
ZeroMemory(recvBuf,BUF_LEN);
int recvLen = recv(sock,recvBuf,BUF_LEN,0);
if(recvLen<=0){cout<<"对手断开连接\n";over=true;break;}
int len = unpackData(recvBuf,raw);
if(len!=2){cout<<"数据包校验失败,丢弃脏数据\n";continue;}
int x = raw[0],y=raw[1];
char ch = isHost?'O':'X';
board[x][y]=ch;
if(checkWin(board,x,y,ch)){printBoard(board);cout<<"对手获胜\n";over=true;break;}
myTurn = true;
}
system("cls");
}
closesocket(sock);
cout<<"对局结束,回车返回\n";_getch();jz();
}
//==================== 联机井字棋核心 ====================
void NetTTT()
{
if(!netInitOk){cout<<"网络初始化失败!回车返回\n";_getch();jz();return;}
int mode;char ipBuf[20];
cout<<"==== 局域网井字棋 ====\n1 创建房间\n2 加入房间\n选择:";cin>>mode;
char ttt[3][3];
for(int i=0;i<3;i++)for(int j=0;j<3;j++)ttt[i][j]=' ';
bool isHost=(mode==1),myTurn=isHost;
SOCKET sock = INVALID_SOCKET;
if(isHost)
{
jz();
bind(serverSock,(sockaddr*)&serverAddr,sizeof(serverAddr));
listen(serverSock,1);
cout<<"等待连接...\n";
int len=sizeof(clientAddr);
sock=accept(serverSock,(sockaddr*)&clientAddr,&len);
}
else
{
jz();
cout<<"主机IP:";cin>>ipBuf;
clientAddr.sin_family=AF_INET;
clientAddr.sin_port=htons(PORT);
clientAddr.sin_addr.S_un.S_addr=inet_addr(ipBuf);
connect(clientSock,(sockaddr*)&clientAddr,sizeof(clientAddr));
sock=clientSock;
}
if(sock==INVALID_SOCKET){cout<<"连接失败\n";_getch();jz();return;}
curSock=sock;
char sendBuf[BUF_LEN],recvBuf[BUF_LEN],raw[BUF_LEN];
cout<<"连接成功,你"<<(isHost?"先手X":"后手O")<<endl;Sleep(1000);system("cls");
bool over=false;
while(!over)
{
drawB();
bool full=true;
for(int i=0;i<3;i++)for(int j=0;j<3;j++)if(ttt[i][j]==' ')full=false;
if(full){cout<<"平局\n";over=true;break;}
if(myTurn)
{
int x,y;
cout<<"你的回合,行列:";
string Row,Col;
cin >> Row >> Col;
if(Row.size()==1)x=Row[0]-'0';
else{cout << "坐标超出范围1~3!重新输入\n";continue;}
if(Col.size()==1){y=Col[0]-'0';}
else{cout << "坐标超出范围1~3!重新输入\n";continue;}
x--;y--;
if(x<0||x>=3||y<0||y>=3||ttt[x][y]!=' '){cout<<"非法位置\n";continue;}
char ch=isHost?'X':'O';
ttt[x][y]=ch;
char data[2]={(char)x,(char)y};
int pl=packData(sendBuf,data,2);
send(sock,sendBuf,pl,0);
bool win=false;
for(int i=0;i<3;i++)
if(ttt[i][0]==ch&&ttt[i][1]==ch&&ttt[i][2]==ch)win=true;
for(int j=0;j<3;j++)
if(ttt[0][j]==ch&&ttt[1][j]==ch&&ttt[2][j]==ch)win=true;
if(ttt[0][0]==ch&&ttt[1][1]==ch&&ttt[2][2]==ch)win=true;
if(ttt[0][2]==ch&&ttt[1][1]==ch&&ttt[2][0]==ch)win=true;
if(win){drawB();cout<<"你赢了\n";over=true;break;}
myTurn=false;
}
else
{
cout<<"等待对手...\n";
ZeroMemory(recvBuf,BUF_LEN);
int rl=recv(sock,recvBuf,BUF_LEN,0);
if(rl<=0){cout<<"连接断开\n";over=true;break;}
int len=unpackData(recvBuf,raw);
if(len!=2){cout<<"校验错误\n";continue;}
int x=raw[0],y=raw[1];
char ch=isHost?'O':'X';
ttt[x][y]=ch;
bool win=false;
for(int i=0;i<3;i++)
if(ttt[i][0]==ch&&ttt[i][1]==ch&&ttt[i][2]==ch)win=true;
for(int j=0;j<3;j++)
if(ttt[0][j]==ch&&ttt[1][j]==ch&&ttt[2][j]==ch)win=true;
if(ttt[0][0]==ch&&ttt[1][1]==ch&&ttt[2][2]==ch)win=true;
if(ttt[0][2]==ch&&ttt[1][1]==ch&&ttt[2][0]==ch)win=true;
if(win){drawB();cout<<"对手胜利\n";over=true;break;}
myTurn=true;
}
system("cls");
}
closesocket(sock);
cout<<"对局结束回车返回\n";_getch();jz();
}
void minx_cjwt(){
system("cls");
cout<<"-----------鸣谢-----------\n";
Sleep(50);
cout<<"·ACGO 用户id:4954991\n注:(由于此用户的用户名中带有中文字符,所以只能写用户id)提出的死循环BUG\n";
Sleep(50);
cout<<"感谢以上用户的支持!\n\n";
Sleep(50);
cout<<"------常见问题及解答------\n";
Sleep(50);
cout<<"·见原码网页\n";
cout<<"感谢游玩,祝您游玩愉快!\n";
Sleep(1000);
cout<<"按下任意键继续...\n";
char a=_getch();
system("cls");
}
int main() {
string in=" ";
while(1){
in=" ";
cout<<"游戏菜单:\n";
cout<<" 0.VIP加速加载(密码)\n";
cout<<" 1.单人AI五子棋\n";
cout<<" 2.双人本地五子棋\n";
cout<<" 3.单人井字棋\n";
cout<<" 4.双人本地井字棋\n";
cout<<" 5.局域网联机五子棋(部分电脑可能弹出防火墙提示,这是正常现象)\n";
cout<<" 6.局域网联机井字棋(部分电脑可能弹出防火墙提示,这是正常现象)\n";
cout<<" 7.原码网页跳转\n";
cout<<" 8.国际象棋/象棋\n";
cout<<" 9.鸣谢及常见问题\n";
cout<<" 10.退出\n\n";
cout<<"请输入编号:";
cin>>in;
system("cls");
if(in=="0"){
cout<<"输入PIN 密码:";string z1,z2;cin>>z1>>z2;
if(z1=="偷密码的是gey"&&z2=="看什么看说的就是你"){kfz=0;jz();}
else if(z1==URL[1]&&z2==URL[2]){kfz=1;jz();}
else{cout<<"密码错误\n";Sleep(200);jz(1);}
}else if(in=="1"){jz();wzq();}
else if(in=="2"){jz();Gobang();}
else if(in=="3"){jz();Tic_Tac_Toe();}
else if(in=="4"){jz();Tic_Tac_Toe_1();}
else if(in=="5"){jz();NetGobang();}
else if(in=="6"){jz();NetTTT();}
else if(in=="7"){
jz();
cout<<"1:ACGO 2:洛谷 3:返回\n输入:";cin>>in;
char c[256]={0};
if(in=="1")strncpy(c,URL[1].c_str(),255),ask(c);
else if(in=="2")strncpy(c,URL[2].c_str(),255),ask(c);
else jz();
}else if(in=="8"){
char c[256]={0};
jz();
cout<<"打开方式:\n1.acgo\n2.洛谷\n";
cin>>in;
if(in=="1"){
cout<<"请输入游戏编号:\n1.中国象棋\n2.国际象棋\n";
cin>>in;
if(in=="1"){
strncpy(c,URL[3].c_str(),255);
ask(c);
}if(in=="2"){
strncpy(c,URL[4].c_str(),255);
ask(c);
}
//cout<<"由于c++无法渲染棋盘和棋子,所以此项目由python编写,敬请谅解!\n";
//MessageBoxA(NULL,"此项目暂未上传到OJ平台,\n制作不易敬请谅解!","提示",MB_OK|MB_ICONEXCLAMATION);
//strncpy(c,URL[3].c_str(),255);
//ask(c);
system("cls");
}else if(in=="2"){
//cout<<"请输入游戏编号:\n1.中国象棋\n2.国际象棋\n";
cout<<"由于c++无法渲染棋盘和棋子,所以此项目由python编写,敬请谅解!\n";
MessageBoxA(NULL,"此项目暂未上传到OJ平台,\n制作不易敬请谅解!","提示",MB_OK|MB_ICONEXCLAMATION);
strncpy(c,URL[4].c_str(),255);
//ask(c);
system("cls");
}
}else if(in=="9"){
minx_cjwt();
}
else if(in=="10"){closeNetSocket();return 0;}
else MessageBoxA(NULL,"输入无效,请重新选择","提示",MB_OK);
}return 0;
}
解释说明
对于局域网联机的提问和回答:
Q:为什么我连接不上其他人的电脑。
A:请排查以下一般现象:
1.未连接到Internet网或未连接到局域网(LAN)或未连接到广域网(WAN),简单来说就是你没有连接WIFI或没有连接热点
2.对方未连接到Internet网或未连接到局域网(LAN)或未连接到广域网(WAN),简单来说就是对方没有连接WIFI或没有连接热点
3.如果你和对方都连接到Internet网或连接到局域网(LAN)或连接到广域网(WAN)或连接到WIFI或连接到热点,那么请检查你们是否连接到同一网络
4.你的或对方的电脑操作系统不支持或不兼容<windows.h>库,或你没有安装c++编译软件
5.你的或对方的电脑硬件不支持联机的基本操作,请换一台电脑再试(最好使用私人电脑)
对于局域网联机时的延迟的提问和回答:
Q:为什么我连接上其他人后没有动静?
A:请排查以下一般现象:
1.请检查一下对方还活着吗(如果有点四了请打120)
2.请检查一下是否断开了连接
3.请等待,有一些延迟是正常现象
Q:为什么我点击国际象棋和象棋弹出弹窗:“由于 c++ 无法渲染棋盘和棋子,所以此项目由python编写,敬请谅解!”和“此项目暂未上传到OJ平台”
A:
1.因为c++的QT5模块太折磨人了,况且作者使用的red panda不支持QT5,所以改用python,还请谅解
2.应为作者更新的慢呀...
全部评论 5
nb
1周前 来自 河北
0。
1周前 来自 广东
0。
1周前 来自 广东
0👍好作者
1周前 来自 广东
0谢谢你
1周前 来自 四川
0
我也做了一个
2026-08-05 来自 江西
0
2026-08-05 来自 四川
0呵呵o( ̄︶ ̄)o
2026-08-05 来自 江西
0



































有帮助,赞一个