学完如何打印九宫格之后,就要开始玩家与电脑下棋的游戏过程了;
我们知道玩三子棋其实就是玩家先下一步之后,就轮到电脑下,如此往复,直至游戏结束。
但在这一过程中,其实就相当于循环(下棋的次数),玩家和电脑分开执行。
while(1){
}
所以这里,我们先完成玩家下棋的操作,这里我们用PlayerMove()自定义函数来实现玩家下棋的操作。
test.c源文件
PlayerMove(board,ROW,COL);
玩家需要在九宫格棋盘中下,其实就是在二维数组中去存数据,所以这里就要传二维数组;传行和列就是给在棋盘内下。
然后,去game.h头文件中去声明
void PlayerMove(chaer board[ROW][COL],int row,int col);
之后,再去game.c源文件中去定义函数
分析:1、玩家在九宫格中玩三子棋,其实就是往二维数组中输入数据,所以这里需要scanf函数来接受玩家输入的数值,然后进行存储。
int x=0;
int y=0;
scanf("%d%d",&x,&y);
2、在这里我们考虑玩家在九宫格中输入数据的时候,会不会不小心在已经被占用的格子中输入数据,又或者在格子之外中输入数据,因此,这里我们需要判断玩家输入的数据是否在棋盘内。
先限制输入数据的范围:(是否在棋盘内)
if(x>=1&&x<=row&&y>=1&&y<=col){
}
else{
printf("坐标非法,请重新输入!\n");
}
这里我们知道,二维数组的下标是从00开始的,但我们要考虑到在玩家的眼中,第一个格子表示可能是11;因此,我们不能当玩这游戏的玩家都是程序员,所以这里的下标我们从视角上的感官来写11。
就是在屏幕上输入九宫格的格子位置,用视角来看。
但实际下标还是00开始的(不变的)
然后,限制完输入范围之后,就需要判断是否在已被占用的格子中又输入数据:
if(board[x-1][y-1]==' '){
board[x-1][y-1]='*';
break;
}
else{
printf("坐标被占用,请重新输入:");
}
然后,在这里去判断二维数组的时候,就是要从下标开始查询,因此,这里就要回归到我们程序的本身,所以这里要减1。
如果没有的话,就输入玩家所操作的棋子(用“*”来表示)
void PlayerMove(char board[ROW][COL],int row,int col){
int x=0;
int y=0;
printf("请输入:");
while(1){
if(x>=1&&x<=row&&y>=1&&y<col){
if(board[x-1][y-1]==' '){
board[x-1][y-1]='*';
break;
}
else{
printf("坐标被占用,请重新输入:");
}
}
else{
printf("坐标非法,请重新输入!\n");
}
}
}
这里要用循环,是用来判断玩家输入的数值是否有误;对了,就跳出循环,错了,就重新输入。
然后返回到test.c源文件中,这里玩家下棋的过程就写完了,接下来,如果想要看在棋盘输入数字的效果,则在打印——
PlayerMove(board,ROW,COL);
DisplayBoard(board,ROW,COL);
玩家写完之后,就轮到电脑写了,那该如何写呢?
这里我们就用到ComputorMove()自定义函数——
ComputorMove(board,ROW,COL);
DisplayBoard(board,ROW,COL);
这里还是一样,要让电脑输入的数据在九宫格范围内。
在game.h头文件中去进行函数声明——
void ComputorMove(char board[ROW][COL],int row,int col);
在game.c源文件中进行函数定义——
void ComputorMove(char board[ROW][COL],int row,int col){
int x=0;
int y=0;
printf("电脑输入:");
while(1){
x=rand()%row;
y=rand()%col;
if(board[x][y]==' '){
board[x][y]='#';
break;
}
}
}
这里要提一点,电脑下棋,是随机在九宫格中的位置中下的;但这里并不是和玩家一样需要玩家自己输入。
而如何让电脑下呢?
电脑在九宫格中的随机位置下,其实就用到之前所学的生成随机数——rand函数
x=rand()%row;
y=rand()%col;
这里为什么要模上row和col呢?
这是因为rand函数生成的随机数范围是0~32767之间,范围比较大,但这里我们的九宫格是3*3的布局,所以缩小了生成随机坐标的范围。(0~2之间)
因为rand函数生成的随机数只有一次,所以在使用rand函数之前要先使用srand函数,而如何使用srand,之前有讲过
srand((unsigned int)time(NULL));
在这里,就要在game.h引头文件
#include<stdlib.h>
#include<time.h>
而生成的坐标就需要判断是否被占用
【注:生成的坐标已经在我们合法范围内,所以不用减1.】
if(board[x][y]==' '){
board[x][y]='#';
break;
}
这里如果被占用的话,就不要提示了,因为是电脑在下
接下就是将判断放入循环(放入死循环)
while(1){
}
玩家和电脑下棋的过程写完之后,就需要来判断输赢了
这里我们在game函数中使用写两个自定义函数IsWin(),用来判断输赢
假设
玩家赢——返回“*”
电脑赢——返回“#”
平局——返回“Q”
结束——返回“C”
所以我们需要一个变量来接受传回来的值,然后判断是否是结束游戏
int ret=IsWin();
if(ret !='C'){
break;
}
int ret=IsWin();
if(ret !='C'){
break;
}
跳出循环之后,就需要判断谁赢或平局
if(ret=='*'){
printf("玩家赢!\n");
}
else if(ret=='#'){
printf("电脑赢!\n");
}
else{
printf("平局\n");
}
在九宫格中如何判断输赢呢?
无非就是横三竖三两个斜列的棋子是否一样,所以在判断输赢的时候,其实还是在判断棋盘内的内容
所以,这里
InWin(board,ROW,COL);
在game.h头文件声明函数——
char InWin(char board[ROW][COL],int row,int col);
在game.c源文件中定义函数
char InWin(char board[ROW][COL],int row,int col){
int =0;
//横三行
for(i=0;i<row;i++){
if(board[i][0]==board[i][1]&&board[i][1]==board[i][2]&&board[i][0]==' '){
return board[i][1];
}
}
//竖三行
for(i=0;i<row;i++){
if(board[0][i]==board[1][i]&&board[1][i]==board[2][i]&&board[0][i]==' '){
return board[1][i];
}
}
//判断是否平局
if(1==IsFull(board,ROW,COL)){
return 'Q';
}
return 'C';
}
这里为什么判断平局还要再写一个IsFull函数呢?
这里是因为我们需要去查看二维数组中每一行和列是否有数据,如果全都有则是被占用,就返回1,没有,则返回0.
因此,这里要传的参数还是二维数组的行和列
int IsFull(char board[ROW][COL],int row,int col){
int i=0;
int j=0
for(i=0;i<=row;i++){
for(j=0;j<=col;j++){
if(board[i][j]==' ')
return 0;
}
}
return 1;
}
以上就是关于三子棋游戏实现的程序逻辑和步骤。
【注:最终代码,请根据以上内容自行编译。】