三子棋游戏当中蕴含了数组、循环、函数等多种知识,对于初识C语言的小伙伴来讲是很好的锻炼思维逻辑的题目。如下图极为三子棋最终得简易实现图:
在三子棋实现的过程中,需要建立三个新建项:
1、test.c
2、game.h
3、game.c
其中test.c用于存放测试部分的代码,game.h用于存放函数的声明,game.c用于存放各个函数的具体定义。关于三子棋具体得到实现思路是:1、使用printf函数实现对三子棋初始菜单的打印;2、用户通过键盘输入1或0,来表明是否进入游戏;3、用户选择进入游戏后,打印棋盘,并与电脑进行下棋;4、判断下棋的输赢方,输出下棋的结果。在设计程序之前需要考虑代码后面的扩展性要求,因此将棋盘的行数和列数定义成为符号。
一、打印三子棋的菜单
使用printf函数对菜单进行打印,注意对齐的情况,尽量使打印的菜单美观,其中1代表进入三子棋游戏,0代表退出不进入游戏。
void menu()
{
printf("***************************\n");
printf("******** 1. play ********\n");
printf("******** 0. exit ********\n");
printf("***************************\n");
}
二、用户输入,判断是否进入游戏
在上一部打印菜单后,用户会选择是否进入游戏,第一种情况是输入1,进入游戏;第二种是选择0,不进入游戏;还可能出现输入错误的情况。其中game()里面封装游戏的代码,由于可能出现用户想多次玩游戏或者输入错误的情况。因此,讲这段代码放进do...while()循环里。
void test()
{
int input = 0;
srand((unsigned)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
}
三、打印棋盘以及下棋的过程
每次用户在进入游戏后,首先对棋盘进行初始化,再打印棋盘,以便用户输入正确的棋盘位置进行下棋。
(1)对棋盘进行初始化,InitBoard()函数将棋盘所有的位置初始化为空格,主要使用两个for循环来实现,此步主要是为了用户想再次玩游戏时,将上一次游戏所有的信息清空。
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)打印棋盘,DisplayBoard()函数来实现,再打印的的过程中,因为初始情况下字符串内元素都为空格因此需要有额外的符号将其显示出来,因此在循环打印中加入了“|”和“---”等元素,在打印的过程中还是需要注意代码的扩展性,不能将代码写死。
void DisplayBoard(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++)
{
printf(" %c ", board[i][j]);
if (j < row - 1)
printf("|");
}
printf("\n");
//分割行
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < row - 1)
printf("|");
}
}
printf("\n");
}
}
打印棋盘函数所产生的结果为
(3)打印棋盘后,就可以开始下棋游戏。在下棋的过程中是由玩家下棋和电脑下棋所构成的一个循环。
<1> 在玩家下棋的过程中,先要判断玩家输入的坐标的合法性,合法性涉及到该位置是否合法以及该位置之前是否已经下过棋子,如果都没有则将空格改给‘*’表示玩家在此位置下棋。需要注意的是由于玩家理解的位置与代码中数组的位置有偏差,因此可以用-1进行修正。
void play_move(char board[ROW][COL], int row, int col)
{
printf("玩家下棋:>");
int x = 0;
int y = 0;
while (1)
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)//坐标合法性判断
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("该坐标被占用,请重新输入!\n");
}
}
else
{
printf("坐标非法!\n");
}
}
}
<2>在电脑下棋的过程中,需要电脑产生一个0~2之间的随机数来表示电脑下棋的位置,电脑下的位置用‘#’代替空格。
void computer_move(char board[ROW][COL], int row, int col)
{
printf("电脑下棋:>\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % ROW;//rand()%ROW随机数的范围为0~ROW-1
y = rand() % COL;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
至此代码已经可以完成玩家和电脑对弈的过程。当然,电脑下棋部分的代码有待进一步优化,使用更加优秀的算法。整个程序的逻辑已经跑通。但还缺少最好产生结果的步骤。
四、判断输赢的函数
在玩家和电脑下棋之后还需要判断到底是玩家赢还是电脑赢,亦或者平局等情况。我们用is_win函数来判断这一结果。当某一行元素或某一列元素或某一对角线元素都为‘*’表示玩家赢;都为‘#’时表示电脑赢,如果这两种情况都不满足就判断棋盘是否已经满了,如果已满表示平局,如果未满就可以继续下棋。
char is_win(char board[ROW][COL], int row,int col)
{
int i = 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 (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//判断平局
if (1 == is_full(board, row, col))
{
return 'Q';
}
//游戏继续
return 'C';
}
其中is_full函数是用来判断棋盘是否已满的函数。
int is_full(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;
}
以上就是实现三子棋的所有代码!