思路:
1.打印菜单,其中有进入游戏和退出游戏。
2.进入游戏。
游戏内的基本逻辑为:
1.初始化棋盘。
2..打印棋盘。
3..玩家落子。
4..判断输赢
5.电脑落子。
6.判断输赢。
游戏结束。
1.打印开始页面:使用printf语句打印
printf("**************\n");
printf("****1.paly****\n");
printf("****0.exit****\n");
printf("**************\n");
printf("请选择:");
2.选择是否开始游戏,此处的逻辑为:输入1开始游戏,输入0结束游戏,输入其他数字则提示重新输入,因此这块我们可以选择使用switch选择分支语句。我们要使游戏具有重复可玩性,因此还需要一个循环语句,而第一次进入菜单无需任何条件,所以我们使用do while语句。
代码如下:
do
{
printf("**************\n");
printf("****1.paly****\n");
printf("****0.exit****\n");
printf("**************\n");
printf("请选择:");
scanf("%d", & num);//0 1 其他数字
switch (num)
{
case 0:
printf("退出游戏\n");
break;
case 1:
game();
break;
default:
printf("请重新选择:\n");
break;
}
} while (num);
进入游戏后:
1.打印棋盘:我们可以使用二维数组来表示棋盘。
void initboard(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++)
{
board[i][j] = ' ';
}
}
}
2.初始化棋盘后,需要打印棋盘,但是不能只打印数组,因为还需要打印分割线。
void print(char board[Row][Col], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)//打印第i行
{
//打印数据
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
//打印分割线
for (int j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
3.玩家落子:玩家输入坐标有两种结果:1.坐标合理,2.坐标不可用,因此使用while循环,坐标合理则跳出循环,否则玩家继续输入坐标。因为数组的下标是从0开始的,所以我们在输入坐标时需要将玩家输入的坐标减一。
void play(char board[Row][Col], int row, int col)
{
printf("玩家落子:");
int a = 0;
int b = 0;
while (1)
{
scanf_s("%d %d", &a, &b);//判断坐标是否合理
if (a >= 1 && a <= row && b >= 1 && b <= col)
{
if (board[a - 1][b - 1] == ' ')
{
board[a - 1][b - 1] = '*';
break;
}
else
{
printf("请重新输入:");
}
}
}
}
4.判断输赢:每次玩家或者电脑下棋后,都需要判断一次是否游戏结束,每次判断都有四种可能:1.玩家赢。2.电脑赢。3.平局。4.还没结束,继续游戏。
我们使用char定义一个变量:result 用来接收返回结果,如果结果为“*”,则玩家赢,结果为“#”,电脑赢,结果为“c”,则为平局,除此之外,游戏继续。
result = win(board, Row, Col);//判断输赢
if (result == '*')//player赢
{
print(board, Row, Col);
printf("玩家赢\n");
break;
}
else if (result == '#')
{
print(board, Row, Col);
printf("电脑赢\n");
break;
}
else if(result=='c')
{
print(board, Row, Col);
printf("平局\n");
break;
}
win函数用来判断输赢:因此此次举例为三子棋,所以只需要使得某一行相同或某一列相同,两条对角线相同即可获胜。如果是平局,那么可以通过遍历整个棋盘,如果棋盘上每个空格都被覆盖,则返回平局。如果游戏还没结束,则不返回值,此时游戏继续。
char win(char board[Row][Col], int row, int col)//玩家赢,电脑赢,平局
{
int i = 0;
int j = 0;
int n = 1;
for (int a = 0; a < row; a++)//行
{
if (board[a][0] == board[a][1] && board[a][1] == board[a][2])
return board[a][0];
}
for (int a = 0; a < col; a++)//列
{
if (board[0][a] == board[1][a] && board[1][a] == board[2][a])
return board[0][a];
}
if (board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] != ' ')//正对角线
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] != ' ')//反对角线
{
return board[1][1];
}
for (i = 0; i < row; i++)//行
{
for (j = 1; j < col + 1; j++)//列
{
if (board[i][j] == ' ')//保证棋盘是满的
{
n = 0;
}
}
}
if (n == 1)
{
return 'c';
}
5.电脑落子:我们使用随机数函数来模拟电脑随机落子。在这里我们可以使用while循环,如果落子的坐标有值,则重新随机一个坐标,成功落子后,便跳出循环。
void cplay(char board[Row][Col], int row, int col)
{
while (1)
{
int ret = rand() % row;//0 1 2
int num = rand() % col;//0 1 2
if (board[ret][num] == ' ')
{
board[ret][num] = '#';
break;
}
}
}
6.再次判断输赢,使用while循环重复1-5的操作,直到游戏结束,跳出循环。
下面是游戏主体的所有代码:
void game()
{
char result = 0;
char board[Row][Col] = { 0 };
initboard(board, Row, Col);//初始化棋盘
do{
print(board, Row, Col);//打印棋盘
play(board, Row, Col);//玩家下棋
result = win(board, Row, Col);//判断输赢
if (result == '*')//player赢
{
print(board, Row, Col);
printf("玩家赢\n");
break;
}
else if (result == '#')
{
print(board, Row, Col);
printf("电脑赢\n");
break;
}
else if(result=='c')
{
print(board, Row, Col);
printf("平局\n");
break;
}
cplay(board, Row, Col);//电脑下棋
result = win(board, Row, Col);//判断输赢
if (result == '*')
{
print(board, Row, Col);
printf("玩家赢\n");
break;
}
else if (result == '#')
{
print(board, Row, Col);
printf("电脑赢\n");
break;
}
else if(result=='c')
{
print(board, Row, Col);
printf("平局\n");
break;
}
} while (1);
Tips:
1.我们可以将所有需要用到的函数库,函数声明以及宏放在一个头文件里,这样在.c文件中就不用多次重复调用,只需要调用一次这个头文件。这也就是常说的模块式代码。