引言:想必大家都玩过这个简单的游戏——三子棋,今天我们就来实现一下关于三子棋该如何实现
我们可以看到图中的红色标记,我来介绍一下这下文件分别要实现的功能。 头文件game.h:来包含我们代码中所用到的所有头文件,以及函数的声明。 源文件game.c:各个函数的功能的实现。 源文件text.c:主程序的进行,包括如何调用函数进行游戏的实现。
我们可以看到当我们在game.h里包含头文件时,我们只需要在源文件include"game.h"就可以在源文件里面使用我们在game.h里的所有东西。(包括宏定义)
int main()
{
//srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input) {
case 1:
game();
break;
case 0:
printf("退出游戏");
break;
default:
printf("选择错误请重新选择");
break;
}
} while (input);
return 0;
}
void menu() {
printf("*****************\n");
printf("**** 1.play *****\n");
printf("**** 0.exit *****\n");
printf("*****************\n");
}
我们先编写主函数的代码,用一个do-while循环来实现游戏的循环,并且调用了一个menu(菜单)函数,来增加玩家的可选择性。当我们调用menu函数后,打印菜单,玩家可选择1玩游戏,input被赋值1,来到switch分支,case(1)进入我们的游戏函数,玩家可选择0退出,input被赋值0,case(0)退出游戏,当玩家数入别的数字,来到default,提醒玩家重新输入,while(input)当input是0时,条件为假循环结束,游戏退出,当input非零时,条件为真,循环继续。
首先我们在game.h这个文件里对这两个函数进行声明。
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] = ' ';
}
}
}
先来实现初始化棋盘,我们用两个for循环来遍历3*3的井字格,row代表行,col代表列,将这个井字格进行初始化成空格。
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 < col - 1)
printf("|");
}
printf("\n");
if(i
再来实现打印棋盘的函数,我们依旧用for循环来打印分割行和刚刚初始化的二维数组。
void game()
{
char ret = 0;
char board[ROW][COL];
//开始时里面全是空格
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
我们在game函数中调用这两个函数,我们来看一下运行结果:
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋\n");
while(1)
{
printf("请输入坐标>");
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");
}
}
}
同样我们先给函数传入参数(不要忘了先在game.h文件里声明),我们用while循环让玩家输入坐标,注意,要先确定好坐标的范围,不要让玩家输入的坐标无效,另外在传入二维坐标的时候,x,y要记得减一,因为二维数组是从下标为零开始的,但是玩家不知道啊,或者也是为了输入坐标方便。
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑下棋\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
接下来是让我们的电脑下棋,我在这只是先实现了一个笨一点的电脑,我用了随机时间戳,然后再%上row和col这样就可以得到一个随机的坐标,这就是电脑落子的位置了,但是我们还要用if来判断这个坐标是否是空坐标,如果是不是空坐标就循环让带电脑在随机生成一个坐标。我们看一下运行效果。
我们可以看到玩家和电脑都可以正常下棋了,接下来我们只需要最后一个判断输赢的函数了。
static 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;
}
这个函数就是判断如果棋盘满了但是依然没有分出胜负,就说平局了,我们依旧是运用双重循环进行 遍历,如果没有空格就说明棋盘已经满了。
char IsWin(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][0];
}
}
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i]&&board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
}
}
if (board[0][0] == board[1][1]&&board[1][1] == board[2][2] && board[0][0] != ' ')
{
return board[0][0];
}
if (board[0][2] == board[1][1]&&board[1][1] == board[2][0] && board[0][2] != ' ')
{
return board[0][2];
}
if (IsFull(board, row, col))
{
return 'Q';
}
return 'C';
}
这里我只是将所有情况给列出来了,其实还有更好的判断方法,但这里我为了更好的让大家理解,我就只写了3*3棋盘的情况,我们用for循环进行一行一行的遍历,列出获胜的条件,如果谁连成了三个,那就返回棋盘上的字符。
void game()
{
char ret = 0;
char board[ROW][COL];
//开始时里面全是空格
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//下棋
while (1)
{
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断输赢
ret = IsWin(board,ROW,COL);
if (ret != 'C')
{
break;
}
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("玩家赢\n");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else
{
printf("平局\n");
}
}
最后我们完善我们的game函数,我们用ret来接受我们刚刚判断谁赢的字符,然后用if语句来打印谁赢,或是平局,当每次落子时都有可能结束游戏,那么我们每次落子后都判断一下,如果是‘C’那就继续游戏,如果不是就跳出游戏循环,进行判断输赢。
最终:
最后,感谢大家的观看!!!