三子棋就是在3*3的格子中,任何一方的棋子连成一条线那就哪一方获胜了。
接下来我们就一步一步实现C语言玩家与电脑PK的三子棋。(以下的代码都是在VS2022上面实现的)
注意:我们在写很大工程量的代码的时候尽量可以分工程来写。这个代码我们分为三个分别是"game.h" \"game.c"\"text.c",他们分别是函数的声明,函数的定义和函数的实现部分。在写的过程中我们可以加上标记这样不容易出错。
三子棋的实现思路>>>
实现总体路线,我们分析一下这个游戏的过程。首先是开始游戏,棋盘的打印,然后是玩家和电脑分别下棋,电脑和玩家的棋子,最后是判断游戏输赢,最后是结束游戏的提示。接下来我们来实现代码。
游戏开始和结束的提示>>>
游戏的开始界面是选择玩游戏或者不玩(也就是菜单)。这里我们用自定义函数meun()来实现这个功能
void menu()
{
printf("*****************************\n");
printf("******** 1. play *********\n");
printf("******** 0. exit *********\n");
printf("*****************************\n");
}
当玩家选择1后就进入了游戏
int main()
{
int input = 0;
do
{
menu();
printf("请选择>:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误\n");
break;
}
} while (input);
return 0;
}
进入函数这里我们用来do-while重复选择。可以看到这里我们如果选择了1就进入了game()实现游戏(我们要先把整体框架搭建好)
棋盘的打印>>>
我们先建立一个二维数组,我们在这里棋盘的打印其实要两步走,首先是对棋盘的初始化这里我们先把里面的数全部都初始化为空格。(ROW,COL分别为行和列)
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
然后我们第二步就是打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("___");
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
这里我们对打印棋盘重点说一下
为了方便理解我把一个格子分为上下两个部分,首先我们先看上半部分,可以看出来上半部分为
"空格%c空格|"这是一个格子的格式,下半部分为"___|"三个下划线和一个竖杠,ok这样大致的图像我们也了解了,注意我们的图像为了美观我们最右边是没有竖杠的所以代码中用了if语句col-1。写到这里我们可以测试一下代码(建议大型代码每次写完一部分就去测试一下)。
玩家和电脑的下棋>>>
我这里玩家的棋子为’*‘,电脑的是’#‘。
首先我们先来实现玩家的下棋
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");
}
}
}
这里我们要判断输入的位置是否合法,然后我们要考虑下的位置有没有已经有了棋子如果有了我们就要提示换一个位置,所以我们在这里也使用了while循环。
接下来就是电脑的下子
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋:>\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
这里rand就是生成随机数的函数,而这里我们为了保证下棋的位置正确我们用了%。这里我们要去主函数那里加一句话
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("退出游戏\n");
break;
default:
printf("输入错误\n");
break;
}
} while (input);
return 0;
}
这里srand((unsigned int)time(NULL));是为了rang函数的正确实行。
判断输赢>>>
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[1][1] != ' ')
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 (IsFull(board, row, col) == 1)
{
return 'Q';
}
return 'C';
}
我们分别判断赢,平局,和继续。玩家赢我们就返回’*‘,电脑赢我们返回’#‘,平局返回’Q‘,继续返回’C'。
其中赢要判断行,列和对角线。
平局这里我们又使用了另外一个函数
int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
增加代码的可读性。返回1说明没有位置可以在下棋了。
到这里大体我们已经写完了
我们来看一看game()
void game()
{
char ret = 0;
char board[ROW][COL] = { 0 };
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");
}
这里我们要在电脑,玩家下棋后分别打印棋盘,并判断输赢用while循环判断。
最后我们每写一个函数都要在头文件去声明
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL], int row, int col);
void DisplayBoard(char board[ROW][COL], int row, int col);
void PlayerMove(char board[ROW][COL], int row, int col);
void ComputerMove(char board[ROW][COL], int row, int col);
char IsWin(char board[ROW][COL], int row, int col);