- 实验目的
实现人与人或人与电脑进行五子棋对弈
- 实验内容
启动游戏,显示游戏参数设置界面,用户输入参数后进入游戏界面,显示棋盘及双方博弈过程,游戏过程中可选择退出游戏。判定一方获胜后结束本局游戏,可选择继续下一局或者退出游戏。
- 分析与设计
设计棋盘:使用for循环的嵌套并定义一个二维数组存储棋子
void create_board(char board[N][N] , int n)
{
for(int i = 0;i < n;i++)
{
for(int j = 0;j < n;j++)
{
cout << ' ' << board[i][j] << ' ';//" %c "
if(j < n - 1)
cout << '|';
}
cout << endl;
if(i < n - 1)
{
for(int j = 0;j < n;j++)
{
cout << "---";
if(j < n - 1)
cout << '|';
}
}
cout << endl;
}
}
下棋:下棋是有先后顺序,为了保持顺序以及判断是否胜利,定义一个game函数来设置下棋流程。下棋者可以是人也可以是电脑,先对人下棋设置一个函数play_game和play_game_2,来定义双方下棋的位置与不同棋子,
//玩家下棋
bool play_game(char board[N][N] , int n)
{
int x,y;
cout << "请玩家1下棋->" << endl;
while(1)
{
cin >> x >> y;
if(x >= 0 && x < n && y >= 0 && y < n)
{
if(board[x][y] == ' ')
{
board[x][y] = '*';
return check_game(board,n);
break;
}
else
cout << "该点已经下过,请您重新下谢谢" << endl;
}
else
{
cout << "坐标越界,请重新输入" << endl;
}
}
}
bool play_game_2(char board[N][N] , int n)
{
int x,y;
cout << "请玩家2下棋->" << endl;
while(1)
{
cin >> x >> y;
if(x >= 0 && x < n && y >= 0 && y < n)
{
if(board[x][y] == ' ')
{
board[x][y] = '#';
return check_game(board,n);
break;
}
else
cout << "该点已经下过,请您重新下谢谢" << endl;
}
else
{
cout << "坐标越界,请重新输入" << endl;
}
}
}
而电脑下棋就定义一个种子srand使电脑随机性下棋。
//电脑下棋
bool computer_game(char board[N][N],int n)
{
srand((unsigned int)time(NULL)); //设置随机生成的数字
cout << "电脑1下棋->";
int x,y;
while(1)
{
x = rand() % n;
y = rand() % n;
if(board[x][y] == ' ')
{
board[x][y] = '#';
cout << x << ',' << y << endl;
return check_game(board,n);
break;
}
}
}
判断胜利:五子棋胜利条件是五个子横着竖着斜着相连,这个时候就要判断其连通性,判断连通性最好办法就是使用DFS,首先利用两个for循环嵌套遍历当前board数组,随后对四个可能的联通方向通过DFS递归探索,如果五子确实相连,这个时候返回true,不相连则返回false。
//判断是否胜利
int dx[N] = { 1, 1, 0, 1 };
int dy[N] = { 0, 1, 1,-1 };
//判断直线是否能走
bool dfs(int x,int y,char a,int i,int res)
{
if(board[x][y] != a)//五个子不全连
return false;
else if(res == 5) return true; //五个子全连
return dfs(x + dx[i], y + dy[i],a,i,res+1);
}
//遍历四种途径
bool check(char board[N][N],int x,int y)
{
for(int i = 0;i <= 3;i++)//四种胜利的路径判断一遍
{
if(dfs(x,y,board[x][y],i,1) == true)
{
return true;
}
}
return false;
}
bool check_game(char board[N][N],int n)
{
for(int i = 0;i < n;i++)
{
for(int j = 0;j < n;j++)
{
if(board[i][j] != ' ')
if(check(board,i,j) == true)
return true;
}
}
return false;
}
最后主函数利用while循环的嵌套判断玩家选择方式,如果其输入错误的数字,那么就会循环,直到输入正确。
另外这里也需要判断是否棋盘全满:
//判断棋盘是否填满
bool is_full(char board[N][N],int n)
{
for(int i = 0;i < n;i++)
{
for(int j = 0;j < n;j++)
{
if(board[i][j] == ' ')
{
return false;
}
}
}
return true;
}
完整代码如下:
#include <iostream>
#include <time.h>
using namespace std;
const int N = 100;
char board[N][N];
void menu()
{
cout << "*******************************" << endl;
cout << "************menu***************" << endl;
cout << "**(请输入对应的数字进行选择)***" << endl;
cout << "*********1.玩家对弈************" << endl;
cout << "*********2.电脑下棋************" << endl;
cout << "*********3.结束游戏************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
}
void choose()
{
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "******请玩家输入棋盘大小*******" << endl;
cout << "*********(注:6-100)************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
}
void win_1()
{
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "********恭喜玩家1胜利**********" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
}
void win_2()
{
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "********恭喜玩家2胜利**********" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
}
void win_computer()
{
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "***********电脑胜利************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
}
void choose_3()
{
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "*************BYE***************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
}
void end()
{
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "*******是否重新开始游戏********" << endl;
cout << "*********1.continue************" << endl;
cout << "***********2.end***************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
cout << "*******************************" << endl;
}
//初始化棋盘
void error_board(char board[N][N] , int n)
{
for(int i = 0;i < n;i++)
{
for(int j = 0;j < n;j++)
{
board[i][j] = ' ';
}
}
}
//创建棋盘
void create_board(char board[N][N] , int n)
{
for(int i = 0;i < n;i++)
{
for(int j = 0;j < n;j++)
{
cout << ' ' << board[i][j] << ' ';//" %c "
if(j < n - 1)
cout << '|';
}
cout << endl;
if(i < n - 1)
{
for(int j = 0;j < n;j++)
{
cout << "---";
if(j < n - 1)
cout << '|';
}
}
cout << endl;
}
}
//判断是否胜利
int dx[N] = { 1, 1, 0, 1 };
int dy[N] = { 0, 1, 1,-1 };
//判断直线是否能走
bool dfs(int x,int y,char a,int i,int res)
{
if(board[x][y] != a)//五个子不全连
return false;
else if(res == 5) return true; //五个子全连
return dfs(x + dx[i], y + dy[i],a,i,res+1);
}
//遍历四种途径
bool check(char board[N][N],int x,int y)
{
for(int i = 0;i <= 3;i++)//四种胜利的路径判断一遍
{
if(dfs(x,y,board[x][y],i,1) == true)
{
return true;
}
}
return false;
}
bool check_game(char board[N][N],int n)
{
for(int i = 0;i < n;i++)
{
for(int j = 0;j < n;j++)
{
if(board[i][j] != ' ')
if(check(board,i,j) == true)
return true;
}
}
return false;
}
//玩家下棋
bool play_game(char board[N][N] , int n)
{
int x,y;
cout << "请玩家1下棋->" << endl;
while(1)
{
cin >> x >> y;
if(x >= 0 && x < n && y >= 0 && y < n)
{
if(board[x][y] == ' ')
{
board[x][y] = '*';
return check_game(board,n);
break;
}
else
cout << "该点已经下过,请您重新下谢谢" << endl;
}
else
{
cout << "坐标越界,请重新输入" << endl;
}
}
}
bool play_game_2(char board[N][N] , int n)
{
int x,y;
cout << "请玩家2下棋->" << endl;
while(1)
{
cin >> x >> y;
if(x >= 0 && x < n && y >= 0 && y < n)
{
if(board[x][y] == ' ')
{
board[x][y] = '#';
return check_game(board,n);
break;
}
else
cout << "该点已经下过,请您重新下谢谢" << endl;
}
else
{
cout << "坐标越界,请重新输入" << endl;
}
}
}
//电脑下棋
bool computer_game(char board[N][N],int n)
{
srand((unsigned int)time(NULL)); //设置随机生成的数字
cout << "电脑1下棋->";
int x,y;
while(1)
{
x = rand() % n;
y = rand() % n;
if(board[x][y] == ' ')
{
board[x][y] = '#';
cout << x << ',' << y << endl;
return check_game(board,n);
break;
}
}
}
//判断棋盘是否填满
bool is_full(char board[N][N],int n)
{
for(int i = 0;i < n;i++)
{
for(int j = 0;j < n;j++)
{
if(board[i][j] == ' ')
{
return false;
}
}
}
return true;
}
void game_1(char board[N][N] , int n)
{
bool res = false;
//初始化棋盘
error_board(board,n);//初始化
create_board(board,n);//打印棋盘
//下棋
while(1)
{
res = play_game(board,n);//玩家下棋
create_board(board,n);//打印棋盘
if(res == true)
{
create_board(board,n);
win_1();
break;
}
res = play_game_2(board,n);//电脑下棋
create_board(board,n);//打印棋盘
if(res == true)
{
create_board(board,n);
win_2();
break;
}
else if(is_full(board,n))
{
cout << "棋盘已经被填满,本局平局" << endl;
break;
}
}
}
//游戏流程循环
void game_2(char board[N][N] , int n)
{
bool res = false;
//初始化棋盘
error_board(board,n);//初始化
create_board(board,n);//打印棋盘
//下棋
while(1)
{
cout << "请在0-n之间输入数据" << endl;
res = play_game(board,n);//玩家下棋
create_board(board,n);//打印棋盘
if(res == true)
{
create_board(board,n);
win_1();
break;
}
res = computer_game(board,n);//电脑下棋
create_board(board,n);//打印棋盘
if(res == true)
{
create_board(board,n);
win_computer();
break;
}
else if(is_full(board,n))
{
cout << "棋盘已经被填满,本局平局" << endl;
break;
}
}
}
int main()
{
menu();
while(1)
{
int a;int res;
cin >> a;//输入模式
if(a == 1)//玩家对弈
{
while(1)
{
choose();
int n;
cin >> n;
if(n < 6 || n > 100)
{
cout << "请重新输入棋盘大小" << endl;
}
else
{
game_1(board,n);
end();
int res;
cin >> res;
if(res == 2)
break;
}
}
if(res == 2)
{
choose_3();
break;
}
}
else if(a == 2)//电脑对弈
{
while(1)
{
choose();
int n;
cin >> n;
if(n < 6 || n > 100)
{
cout << "请重新输入棋盘大小" << endl;
}
else
{
game_2(board,n);
end();
cin >> res;
if(res == 2)
break;
}
}
if(res == 2)
{
choose_3();
break;
}
}
else if(a == 3)//退出
{
choose_3();
break;
}
else
{
cout << "不满足,请重新输入" << endl;
}
}
return 0;
}
- 运行结果
- 结果分析与结论
这套程序有很多不足的地方
- 棋盘的画法不够美观,可以利用Turbo c的图形库画图
- 电脑下棋不够难度,随机性强,可以通过DFS判断当连通性为3的情况进行补位
- 判断胜利不够高效,时间复杂度很高,n^2的递归暴搜非常慢
可以适当的利用graphics.h以及conio.h头文件画图并加入一些更为高效的算法优化判断