那么首先,我们要知道井字棋这个游戏,它的大致内容有那些: 根据代码运行起来的截图可知,井字棋游戏应该分为这几个内容:打印菜单——>玩家选择菜单内容(如果选择1,则开始游戏。如果选择0,则退出游戏)——>如果开始游戏则先打印一下棋盘,再给玩家选择下棋的位置——>玩家下完一步棋,要先判断输赢,如果没有分出胜负。则要打印一下,目前棋盘的样子——>紧接着电脑下棋,同时判断胜负,如果没有分出胜负则要打印目前棋盘的样子。由此循环,直到棋盘的位置被占满或玩家和电脑分出胜负结束这个游戏——>再打印菜单询问是否要玩这个游戏,然后循环以上的流程。
游戏分模块 当我们将这个游戏的大致过程理清楚后,我们可以发现,无论玩家是否要玩这个游戏,我们都要先打印一下菜单。其次,我们可以将我们的游戏代码进行 模块的划分,将 游戏内容有关的代码放在game.c的源文件中,将 主函数和其他的代码放在井字棋.c的源文件中,另外将我们在游戏中所有会用到的 头文件放在game.h的头文件中。当然, 这三个文件是在同一个工程中。具体情况如图所示:
主函数 当我们明白了游戏的大致思路,我们的主函数可以这样来写:
int main()
{
int input = 0;//玩家是否玩游戏的选择
do
{
menu();//菜单打印函数
printf("请输入你的选择:>");
scanf("%d", &input);
printf("n");
switch (input)
{
case 1:
printf("game");//暂时使用这段代码来作为游戏代码
break;
case 0:
printf("退出游戏n");
break;
default:
printf("选择错误n");
break;
}
} while (input);//因为无论是否玩都要打印一遍菜单,所以使用了do...while循环
//同时当input为0时也就是说玩家选择退出游戏时,循环结束。
return 0;
}
经过调试后,我们将游戏代码那行代码经行更改,如下代码所示,这个时候,我们的主函数和菜单打印函数都已经编写完成了,紧接着我们开始编写游戏内容的函数。
int main()
{ srand((unsigned int)time(NULL));//设置随机数的生成起点的,在电脑下棋模块有简述
int input = 0;//玩家是否玩游戏的选择
do
{
menu();//菜单打印函数
printf("请输入你的选择:>");
scanf("%d", &input);
printf("n");
switch (input)
{
case 1:
game();//游戏代码
break;
case 0:
printf("退出游戏n");
break;
default:
printf("选择错误n");
break;
}
} while (input);//因为无论是否玩都要打印一遍菜单,所以使用了do...while循环
//同时当input为0时也就是说玩家选择退出游戏时,循环结束。
return 0;
}
菜单打印函数——>menu()
紧接着,我们开始写菜单打印函数,也就是menu()函数。我们可以直接将其函数定义放在包含主函数的源文件中。由于menu函数不需要返回值也不需要参数,所以将menu函数定义为:
void menu()
{
printf("**************************************************n");
printf("***************** 1.play ******************n");
printf("***************** 0.exit ******************n");
printf("**************************************************n");
}//直接使用printf函数即可
当以上两行代码编写出来后,我们先进行一遍调试以防在哪个没有注意到的地方代码出了问题。
代码结果显示,我们目前编写的代码是没有任何问题的。
游戏内容函数——>game() 首先,我们依旧是先分析,游戏内容函数game不需要返回值,所以将 其函数类型定义为void型,其次,game函数不需要参数。 然后就是game函数的定义了,经过我们之前的分析可以知道,game函数的定义应该是以下代码:
//游戏逻辑
void game()
{
//定义棋盘
char chessboard[ROW][COL]={0};
//初始化棋盘
InitBoard(chessboard, ROW, COL);
//打印棋盘
Printchessboard(chessboard, ROW, COL);
while(1)
{
//玩家下棋
Playersplaychess(chessboard, ROW, COL);
Printchessboard(chessboard, ROW, COL);
//判断输赢
int ret = who_win(chessboard, ROW, COL);
if (ret == 0)
break;
//电脑下棋
Computerchess(chessboard, ROW, COL);
Printchessboard(chessboard, ROW, COL);
//判断输赢
ret = who_win(chessboard, ROW, COL);
if (ret == 0)
break;
}
}
在本段代码中,存在ROW和COL这是两个宏,分别代码这个棋盘的行和列,这样写的目的是为了方便后期的修改和维护,详细的代码在game.h中。
初始化棋盘函数——>InitBoard(chessboard, ROW, COL); 由于我们在定义棋盘的时候将其定义为3*3的数组类型了。 所以,当我们在初始化棋盘的时候也要注意这个范围大小。 初始化棋盘要用到for循环。所以存在代码:
//棋盘初始化
void InitBoard(char chessboard[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)//row是实际的行
{
for (j = 0; j < col; j++)//col是实际的列
{
chessboard[i][j] = ' ';
}
}
}
打印棋盘函数
void Printchessboard(char chessboard[ROW][COL], int row, int col)
在打印棋盘前,我们先观察一下在我们分析时候的游戏运行截图,可以知道,我们的棋盘分为两个部分
所以,在打印棋盘时,我们应将其分为两个部分来打印,一是先打印数组初始化部分,二是打印分割行部分。
同时,打印棋盘的时候,我们并不需要返回值,所以将打印棋盘函数定义为:
void Printchessboard(char chessboard[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 ", chessboard[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("n");
//打印分割线
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("n");
}
}
}
玩家下棋函数
void Playersplaychess(char chessboard[ROW][COL], int row, int col)
玩家下棋函数同样不需要返回值,同时,玩家在下棋时需要注意,玩家输入的下棋位置是否已经被其他的棋子占用了,在没有被占用的条件下,玩家才可以下棋。
void Playersplaychess(char chessboard[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 (chessboard[x-1][y-1] == ' ')
{
chessboard[x-1][y-1] = '*';
break;
}
else
printf("坐标已被占用,请重新输入n");
}
else
printf("你输入的坐标非法,请重新输入n");
}
}
电脑下棋函数
void Computerchess(char chessboard[ROW][COL], int row, int col)
电脑下棋时比较独特,它采用的是随机下棋的方法,同样,电脑在下棋的时候也需要判断,将要下棋的位置是否被占用了,在没有被占用的情况下才能下棋。
/电脑下棋——>电脑下棋下的位置应该是一个随机的值——>使用猜数字游戏里面提到的生成随机起点和时间戳
void Computerchess(char chessboard[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋:>n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (chessboard[x][y] == ' ')
{
chessboard[x][y] = '#';
break;
}
}
}
同时,需要在主函数中添加一行生成随机起点的代码。
判断输赢函数
int who_win(char board[ROW][COL], int row, int col)
在这里我们要返回一个值,所以采用int类型,同时,赢的情况分为行成立,列成立和斜对角成立,另外一种情况是棋盘占满但是没有分出胜负。
//判断输赢
int who_win(char board[ROW][COL], int row, int col)
{
int i, j, count = 0;
for (i = 0; i < row; i++)
{
if (board[i][0] == '*' && board[i][1] == '*' && board[i][2] == '*')
{
printf("玩家赢n");
Sleep(2000);//等待2秒
system("cls");//清理屏幕
return 0;
}
if (board[i][0] == '#' && board[i][1] == '#' && board[i][2] == '#')
{
printf("电脑赢n");
Sleep(2000);
system("cls");
return 0;
}
}
for (i = 0; i < col; i++)
{
if (board[0][i] == '*' && board[1][i] == '*' && board[2][i] == '*')
{
printf("玩家赢n");
Sleep(2000);
system("cls");
return 0;
}
if (board[0][i] == '#' && board[1][i] == '#' && board[2][i] == '#')
{
printf("电脑赢n");
Sleep(2000);
system("cls");
return 0;
}
}
if ((board[0][0] == '*' && board[1][1] == '*' && board[2][2] == '*') || (board[0][2] == '*' && board[1][1] == '*' && board[2][0] == '*'))
{
printf("玩家赢n");
Sleep(2000);
system("cls");
return 0;
}
if ((board[0][0] == '#' && board[1][1] == '#' && board[2][2] == '#') || (board[0][2] == '#' && board[1][1] == '#' && board[2][0] == '#'))
{
printf("电脑赢n");
Sleep(2000);
system("cls");
return 0;
}
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] != ' ')
{
count++;
}
}
}
if (count == row * col)
{
printf("平局了n");
Sleep(2000);
system("cls");
return 0;
}
return 1;
这个过程有更为简单的代码,大家可以自行探讨哟~
game.h
这个部分是我们本次学习内容中所有采用的头文件及函数的声明部分,同时,我们也将
#include#define COL 3 #define ROW 3 #include #include #include //玩家下棋 void Playersplaychess(char chessboard[ROW][COL], int row, int col); //打印棋盘 void Printchessboard(char chessboard[ROW][COL], int row, int col); //棋盘初始化 void InitBoard(char chessboard[ROW][COL], int row, int col); //电脑下棋 void Computerchess(char chessboard[ROW][COL], int row, int col); //判断输赢 int who_win(char chessboard[ROW][COL], int row, int col);
详细代码:井字棋 · 纤云/练习 - 码云 - 开源中国 (gitee.com)
创作不易,请大家多多支持!!!如有不懂的内容,可以私信小刘同学哟~



