前面我们讲解过一个猜数字游戏的实现,想来应该让大家感受到了属于编程的趣味性,并且在实现过程中应该也收获了知识。但猜数字这种简单的游戏肯定满足不了大家对于游戏的高标准、严要求,估计玩不了多久就会没有兴趣了,所以,今天在这里和大家分享一个更好玩,也更有实现难度的小游戏——井字棋!相信大家都不会对这个游戏陌生的(可能有朋友不久前还在学校和小伙伴一起玩呢),那么今天就让我们一起通过编程把这个小游戏实现吧。
1.井字棋游戏的大致流程
首先,由计算机产生一个3*3大小的棋盘,并显示玩家和计算机各自使用的棋子,然后由玩家、计算机轮流在上面落子,哪一方先3颗棋子连成一条线,则显示该方获胜,如果棋局填满,还没有一方三子连线,则判定为和棋。
2.游戏实现的思路
还记得我在猜数字游戏的实现中说过的一句话吗?没错,我们在写编程题或者小游戏代码时,最重要的就是理清实现思路——主体是什么?为了实现目的要创建哪些函数?函数的功能都是什么?只有当我们心中有了一个大体的框架,知道该做些什么时,我们才能更高效地编写代码,完成程序设计。
井字棋游戏的算法如下:
1.提供游戏菜单,由玩家选择是否进行游戏:按“1”开始游戏,按“0”退出游戏,按其他则显示“选择错误,请重新选择”。
2.打印未放置任何棋子的棋盘,并显示玩家和计算机分别分配的棋子类型,并提示玩家先下棋。
2.1PlayerMove(玩家下棋),在棋盘上显示位置,并ret=IsWin(判断是否胜利)。
2.2ComputerMove(电脑下棋)在棋盘上显示位置,并ret=IsWin(判断是否胜利)。
2.3根据ret(定义判断结果的变量)判断最终结果,若玩家胜利,则显示“亲爱的玩家,恭喜你获得游戏胜利!”;若电脑胜利,则显示“亲爱的玩家,请不要因失败而气馁,期待你的下一次开始!”;若平局,则显示“亲爱的玩家,该局游戏平局!”
3.本轮游戏结束,打印游戏菜单并再次询问玩家选择。
二、程序框架
我们将游戏的源文件和头文件分为三个部分,分别是:game.h 、test.c 、game.c
1. game.h
在game.h中为所有需要用到的库函数的头文件的声明,以及要在test.c源文件中使用需要在game.h中定义的自定义函数的声明。
2.test.c
test.c为游戏的整体逻辑部分,并引用头文件"game.h"。
3.game.c
game.c为游戏的实现部分,也要引用头文件"game.h"。
在解决方案资源管理器中找到源文件和头文件的文件夹,分别再头文件文件夹中创建game.h头文件以及在源文件文件夹中创建test.c、game.c两个源文件。
三、游戏实现
1.test.c中编辑游戏的整体逻辑
1-1.创建主函数
int main() //创建主函数
{
srand((unsigned)time(NULL)); //生成随机数随机数(后面用到)
test(); //在test();中实现游戏逻辑,让主函数更简洁
return 0;
}
1-2.定义test()函数
void test() //定义test();函数
{
int input = 0;
do
{
menu(); //打印菜单
//选择游戏进程
printf("请输入:>");
scanf("%d", &input);
switch (input)
{
case 1:
game(); //实现游戏逻辑
break;
case 0:
printf("游戏结束\n");
break;
default:
printf("输入错误!!!(请重新输入1 or 0)\n");
break;
}
} while (input); //每次游戏结束后让玩家选择,当玩家输入1为真游戏继续并开始,输入0为假退出循
// 环,游戏结束。
}
1-3.定义menu()函数
void menu()
{
printf("***********************\n");
printf("**** 1. play ****\n");
printf("**** 0. exit ****\n");
printf("***********************\n");
}
1-4.定义game()函数
void game()
{
//创建棋盘
char board[ROW][COL] = { 0 };
//棋盘初始化
InitBoard(board, ROW, COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
char ret = 0;
while (1)
{
//玩家回合
Player_Move(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断结束或继续
ret = Is_Win(board, ROW, COL);
if (ret != 'C')
break;
//电脑回合
Computer_Move(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = Is_Win(board, ROW, COL);
if (ret != 'C')
break;
}
//判断输赢
if (ret == '*')
printf("玩家赢\n");
else if (ret == '#')
printf("电脑赢\n");
else
printf("平局\n");
}
以下为test.c源文件的整体逻辑
#include "game.h"
//打印菜单
void menu()
{
printf("***********************\n");
printf("**** 1. play ****\n");
printf("**** 0. exit ****\n");
printf("***********************\n");
}
//游戏实现
void game()
{
//创建棋盘
char board[ROW][COL] = { 0 };
//棋盘初始化
InitBoard(board, ROW, COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
char ret = 0;
while (1)
{
//玩家回合
Player_Move(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断结束或继续
ret = Is_Win(board, ROW, COL);
if (ret != 'C')
break;
//电脑回合
Computer_Move(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = Is_Win(board, ROW, COL);
if (ret != 'C')
break;
}
//判断输赢
if (ret == '*')
printf("玩家赢\n");
else if (ret == '#')
printf("电脑赢\n");
else
printf("平局\n");
}
void test()
{
int input = 0;
do
{
//打印菜单
menu();
//选择游戏进程
printf("请输入:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("游戏结束\n");
break;
default:
printf("输入错误!!!(请重新输入1 or 0)\n");
break;
}
} while (input);
}
int main()
{
//随机数
srand((unsigned)time(NULL));
test();
return 0;
}
2.game.h头文件部分的内容
头文件中包含对库函数、自定义函数的声明。
#pragma once
//头文件声明
#include
#include
#include
//定义宏常量
#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 Player_Move(char board[ROW][COL], int row, int col);
void Computer_Move(char board[ROW][COL], int row, int col);
//char返回类型
//若返回"*"则玩家获胜
//若返回"#"则玩家获胜
//若返回"D"(draw)则平局
//若返回"C"(continue)游戏继续
char Is_Win(char board[ROW][COL], int row, int col);
int Is_Full(char board[ROW][COL], int row, int col);
3.game.c 游戏逻辑的实现
game.c是对test.c中game()函数中所使用的函数的定义。
3-1.InitBoard() 自定义的棋盘初始化函数 对九个棋盘格进行初始化为空格
//棋盘初始化
//void 空型函数,char board[ROW][COL]二维数组接收指针,int row、int col接收ROW\COL的形参
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++) //用for循环语句对二维数组进行初始化
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
3-2.打印棋盘
//棋盘打印
//此方式打印出来的棋盘,可以通过对COW和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");
for(j = 0; j < col; j++)
{
if (i < row - 1)
{
printf("---");
if (j < col - 1)
printf("|");
}
}
printf("\n");
}
}
3-3.玩家回合下棋
//玩家回合
void Player_Move(char board[ROW][COL], int row, int col)
{
printf("玩家回合\n");
int x = 0;
int y = 0;
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("输入错误!!!(请重新输入1 ~ 3)\n");
}
}
}
3-4.电脑回合下棋
void Computer_Move(char board[ROW][COL], int row, int col)
{
printf("电脑回合\n");
while (1)
{
int x = rand() % row; //rand()与之前的主函数中srand()共同调用生成随机数
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
3-5.判断游戏的输赢
//判断游戏是否结束
char Is_Win(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 1; j < col; j++)
{
if (board[i][j - 1] == board[i][j] && board[i][j] == board[i][j + 1] && board[i][j] != ' ')
return board[i][j];
}
}
for (j = 0; j < col; j++)
{
for(i = 1; i < row - 1; i++)
if (board[i - 1][j] == board[i][j] && board[i][j] == board[i + 1][j] && board[i][j] != ' ')
return board[i][j];
}
for (i = 1; i < row - 1; i++)
{
for (j = 1; j < col - 1; j++)
{
if (board[i - 1][j - 1] == board[i][j] && board[i][j] == board[i + 1][j + 1] && board[i][j] != ' ')
return board[i][j];
if (board[i - 1][j + 1] == board[i][j] && board[i][j] == board[i + 1][j - 1] && board[i][j] != ' ')
return board[i][j];
}
}
if (1 == Is_Full(board, row, col))
return 'D';
else
return 'C';
}
//判断棋盘是否下满
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;
}
到这里我们就完成对井字棋的实现了,电脑的下棋是随机的,会类似于人工智障的效果。