大家生活中都玩过三子棋,五子棋吧,除了实体的棋盘,想玩的话在小游戏里也是随处可见,那如果自己想写出一个三子棋棋盘,该怎么做呢?用C语言就可以实现,接下来我将详细地描述用C语言写出三子棋的详细过程。
大家应该非常熟悉游戏的界面,通常进入小游戏会有一个界面来让玩家选择是否进入游戏,或者退出游戏,或者选择菜单等等。我们现在简易地实现这个功能即可,如下图:
当我们在键盘上按下1时即进入游戏,按下0即退出游戏,若输入其他则要重新输出;
接下来讲解一下代码是怎么实现的:
void menu()
{
printf("******************************************n");
printf("************ 1.进入游戏 **************n");
printf("************ 0.退出游戏 **************n");
printf("******************************************n");
}
int main()//1.通过main函数进入
{
srand((unsigned int)time(NULL));//产生随机数函数,下文会提到
int n = 0;
again:
do//2.来到了do while循环,循环作用是当玩家结束一次游戏后来选择继续玩还是退出游戏
{
menu();//3.调用了代码开头自定义的meue函数,目的是在屏幕上输出上图我们看到的界面
scanf("%d", &n);//4.捕获玩家选择的数字
switch (n)
{
case 1://5.电脑会根据该数字选择相应的路线,如选择了数字1,则进入了case 1这条路
game();
break;
case 0:
printf("退出游戏n");
break;
default:
printf("输入错误,请输入1进入游戏,或者输入0退出游戏n");
goto again;
}
} while (n);
return 0;
}
选择了1,便进入了游戏,那么我们看到的界面应该是一个棋盘,所以接下来我们应该输出一个棋盘型,由于我们要玩的是三子棋,所以输出3x3的棋盘:
为了方便,我们把这个功能用自定义函数实现,用不同的函数实现不同的功能,而且函数的功能越单一越好,每当我们需要实现这个功能的时候调用一次这个函数即可,函数如下:
displayboard(char arr[ROW][COL])
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
printf(" %c ", arr[i][j]);//这步是点睛之笔,玩家或者电脑“下棋”实质就是字符的替换,用代表玩家或者电脑的字符利用数组替换了原来的空白字符
if (j < COL-1)
{
printf("|");
}
}
printf("n");
if (i < ROW-1)//从这步开始是为了输出分隔线,即棋盘的形状
{
for (int j = 0; j < COL; j++)
{
printf("---");
if (j < COL - 1)
{
printf("|");
}
}
printf("n");
}
}
}
既然棋盘有了,那么玩家该下棋了吧,假设用 * 表示玩家下的棋,为了下棋简易的实现,可以用输入棋盘位置的坐标来决定要下的位置,同样的,写一个自定义含函数实现。
play(char arr[ROW][COL])
{
int row = 0;
int col = 0;
printf("玩家下棋->n请输入坐标:n");
while (1)
{
scanf("%d%d", &row, &col);
if (row >= 1 && row <= ROW && col >= 1 && col <= COL)//判断数据在规定范围内
{
if (arr[row - 1][col - 1] == ' ')
{
arr[row - 1][col - 1] = '*';//用*替换空白字符表达玩家想下的位置
break;
}
}
else
printf("输入有误,请重新输入n");
}
}
以上代码块实现的效果如下图:
玩家下完后就该电脑下了,但是电脑没有思想,它不会自己输入坐标,那么该怎么办呢?这个时候需要我们给电脑设置两个随机数来表达电脑要下的位置,这两个随机数的产生需要用到库函数里面的rand()函数,我们又想每次产生不同的随机数,于是要用到srand((unsigned int)time(NULL))。
computer_play(char arr[ROW][COL])
{
int row = 0;
int col = 0;
printf("电脑下棋-> n");
while (1)
{
row = rand() % ROW;//产生的余数在棋盘的范围内
col = rand() % COL;
if (arr[row][col] == ' ')
{
arr[row][col] = '#';//用#替换空格字符表达电脑要下的位置
break;
}
}
}
电脑下棋效果如下图:
这样便实现了玩家和电脑你来我往的对弈,当有一方赢了的时候,需要给出判断,结束游戏;当平局时也要给出判断结束游戏。
以下的代码块看上去很庞大,但可以简单的划分三个判断,当一行或者一列或者对角线有三个相同字符且该字符不是空白字符时,即产生了赢家,通过return 该字符来判断是玩家还是电脑获胜。
IsWin(char arr[ROW][COL])
{
int count = 0;
for (int i = 0; i < ROW; i++)//判断行
{
count = 0;
for (int j = 0; j < COL-1; j++)
{
if (arr[i][j] == arr[i][j + 1] && arr[i][j + 1] != ' ')
{
count++;
if (count == COL - 1)
{
return arr[i][j];
}
}
}
}
for (int i = 0; i < COL; i++)//判断列
{
count = 0;
for (int j = 0; j < ROW - 1; j++)
{
if (arr[j][i] == arr[j + 1][i] && arr[j + 1][i] != ' ')
{
count++;
if (count == ROW - 1)
{
return arr[j][i];
}
}
}
}
int j = 0;
count = 0;
for (int i = 0; i < ROW-1; i++)//判断两条对角线
{
if (arr[i][j] == arr[i+1][j+1] && arr[i][j] != ' ')
{
count++;
}
if (count == ROW - 1)
{
return arr[i][j];
}
j++;
}
j = COL-1;
count = 0;
for (int i = 0; i < ROW - 1; i++)
{
if (arr[i][j] == arr[i + 1][j - 1] && arr[i][j] != ' ')
{
count++;
}
if (count == ROW - 1)
{
return arr[i][j];
}
j--;
}
}
有输有赢,那么也有平局,平局判断可以这么想,当棋盘上都被填满了但是上一个函数却没有返回字符,这个时候就是平局。我们可以用一个函数来一个一个“检查”数组中有没有空白字符,如果有,则return 0;没有即return 1;
int IsFull(char arr[ROW][COL])
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
if (arr[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
这些函数就像一个个小插件,分别实现不同的功能,那么是时候该把这些功能集中起来,
开头的case 1中调用了game()函数,我们用自定义的game函数按逻辑集装这些功能。
void game()
{
char arr[ROW][COL];
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
arr[i][j] = ' '; //初始化数组,方便后来的替换
}
}
while (1)
{
displayboard(arr);
play(arr);
char ch = IsWin(arr);
if (ch == '*')//返回的字符为*代表玩家赢了
{
displayboard(arr);
printf("玩家赢了n");
break;
}
if (IsFull(arr))
{
printf("平局n");
break;
}
displayboard(arr);
computer_play(arr);
ch = IsWin(arr);
if (ch == '#')//如果返回的字符为#就代表电脑赢了
{
displayboard(arr);
printf("电脑赢了n");
break;
}
if (IsFull(arr))//返回值为真即执行if花括号的语句
{
printf("平局n");
break;
}
}
}
三种不同的效果如下图:
最后,以上代码用到的头文件和定义放在同一个头文件上
#include
#include
#include
#define ROW 3
#define COL 3
用#define定义行数和列数的好处是,在需要改行数或者列数的时候只需改动那两个数字即可,不需在全局上改动变量。比如,当把3改成5时,就得到了5x5的棋盘,就变成了一个简易的五子棋。
看到这大家应该会有个疑问,这个电脑怎么笨笨的,好像永远赢不了,电脑下的位置是根据随机数,它不会思考,只有人才能让它变聪明,篇幅有限,这里就不展开说让三子棋变聪明了。大家可以思考思考,欢迎在评论区留言讨论。
上述只是简单的梳理了写三子棋代码的逻辑,可能有一些bug哟~



