目录
前言
一,游戏规则
二,游戏步骤
三,游戏实现
3.1游戏构思和框架
3.2 棋盘的初始化和打印
3.3 玩家和电脑下棋的实现
3.4 判断输赢
3.5 游戏平局
3.6 游戏头文件game.h
四,电脑下棋优化
五,游戏总代码
继上一次的猜数字小游戏以后,我们再来个更加锻炼一个逻辑的游戏,这个游戏比上个代码多,但很能考验我们的逻辑能力。逻辑能力上来了,以后做项目,编写程序的时候就不会太吃力。话不多说,先来一张美图,直接开始。
跟小时候在作业本上画个“井”子格一样,谁先连成一条线谁赢。如果棋盘满了还没有分出胜负,则平局。只不过这次在电脑上和人机下棋,在电脑上显示“井”子格。这次玩家棋子用“ # ”表示,电脑用“ * ”表示。
游戏的步骤如下:
第一步,玩家下棋
第二步,电脑下棋
第三步,如果没分出胜负重复1,2步骤,一旦有一方胜利就终止游戏。
另外还要注意的是:
1,在游戏步骤执行之前,我们想一下,在开始之前应该有一个菜单,来满足我们是否要选择玩游戏。而游戏结束之后应该跳到菜单界面,由玩家选择是否还要玩游戏。
2,在执行游戏步骤的时候,玩家和电脑下棋之后到要进行判断输赢。
3,三子棋总共有九格,那三子棋的实现就应该是用3*3二维数组来实现,每一个格子放一个数。更何况我们不能直接在屏幕上来下,我们可以用坐标来代替,而二维数组正好可以满足要求。
这次我们把这个游戏分别放在不同的文件中,游戏框架放在test.c源文件中,游戏实现放在game.c源文件中,函数声明放在game.h头文件中。
我们现在头文件里添加个库函数
//game.h
#include
#defile ROW 3
#defile COL 3
然后我们将头文件test.h作为test.c的库函数(这样就相当于直接调用test.h里的内容了)和游戏框架如下所示:
//test.c
#include"game.h"
void mune()
{
printf("******************************\n");
printf("******** 1.开始游戏 **********\n");
printf("******** 0.退出游戏 **********\n");
printf("******************************\n");
}
int main()
{
int input = 0;
srand((unsigned)time(NULL)); //随机数的起点,后面会提到
do
{
mune();//打印游戏菜单
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
break;
default:
printf("选择错误,重新选择。\n");
break;
}
} while (input);
return 0;
}
用do...while()语句来实现整个框架,先把菜单打印出来,然后看着菜单进行选择,将选项赋值在变量input中,然后再用switch语句来执行不同的选项,将游戏实现的过程放在game() 函数中。
然后接下来我们开始编写game() 函数。
根据构思我们可以想出以下步骤:
1,屏幕出现棋盘。
2,玩家输入坐标下棋,判断输赢,没赢继续执行下一步。
3,电脑下棋,判断输赢,没赢执行第1步。
既然出现棋盘,那我们就先创建一个3*3棋盘,并对棋盘进行初始化(让棋盘里的内容都变成空格)。然后打印棋盘:
//test.c
void game()
{
char chessboard[ROW][COL];//创建一个3*3的棋盘
init_chessboard(chessboard, ROW, COL);//初始化棋盘
print_chessboard(chessboard, ROW, COL);//打印棋盘
}
我们将棋盘的初始化和打印棋盘的实现放在game.c文件中,game.c中也一样将game.h作为库函数调用。
//game.c
#include "game.h"
void init_chessboard(char chessboard[ROW][COL],int row,int col)//初始化棋盘
{
int i,j;
for(i = 0;i < row; i++)
{
for(j = 0; j < col; j++)
{
chessboard[i][j] = ' '; //先将棋盘中的数打印成空格
}
}
}
void print_chessboard(char chessboard[ROW][COL],int row,int col)//打印棋盘
{
int i,j;
for(i = 0; i < row; i++) //运行三次后,打印棋盘
{
for(j = 0; j < col; j++) //运行三次后: %c | %c | %c
{
if(j == col - 1)
printf(" %c ", chessboard[i][j]);
else
printf(" %c |", chessboard[i][j]);
}
printf("\n");
for(j = 0; j < col; j++) //运行三次后: ---|---|---
{
if(i < 2)
{
if(j == col - 1)
printf("---");
else
printf("---|");
}
}
printf("\n");
}
}
当屏幕上打印棋盘后,玩家该输入坐标下棋。玩家下棋用‘#’表示,电脑下棋用‘*’表示
//test.c
void game()
{
char chessboard[3][3]; //创建一个3*3的棋盘
init_chessboard(chessboard, ROW, COL); //初始化棋盘
print_chessboard(chessboard, ROW, COL); //打印棋盘
player_playchess(chessboard, ROW, COL); //玩家下棋
judge(chessboard, ROW, COL); //判断输赢
computer_playchess(chessboard, ROW, COL); //电脑下棋
}
在game.c中实现玩家和电脑下棋的操作。其中玩家下棋是输入坐标下棋,电脑是靠rand()来生成随机数来下棋。然后在test.c中加一个随机起点(srand((unsigned)time(NULL)))(具体rand()生成随机数可以看这篇的生成随机值)
如下:
//game.c
void player_playchess(char chessboard[ROW][COL],int row,int col)
{
int input = 1;
while(input)
{
printf("请输入下棋的坐标\n");
int a = 0; //创建a,b两个变量来储存坐标
int b = 0;
scanf("%d %d",&a,&b);
if(a > 0 && a < row + 1 && b > 0 && b < col + 1) //坐标必须在0到row(col)+1之间
{
if(chessboard[a - 1][b - 1] == ' ') //判断输入坐标的地方是否为空格
{
chessboard[a - 1][b - 1] = '#';
input = 0;
}
else
printf("该坐标已被占用,请从新输入");
}
else
{
printf("坐标非法,请重新输入");
}
}
print_chessboard(chessboard,row,col); //打印下棋后的棋盘
}
//电脑下棋
void computer_playchess(int chessboard[ROW][COL], int row, int col)
{
int input = 1;
while(input)
{
int a = rand() % row; //用a,b装 0到2 的随机数
int b = rand() % col;
if(chessboard[a - 1][b - 1] == ' ') //判断输入坐标的地方是否为空格
{
chessboard[a - 1][b - 1] = '*';
input = 0;
}
}
print_chessboard(chessboard,row,col); //打印下棋后的棋盘
}
在电脑和玩家下棋后要判断输赢,如果平局,返回‘Q’,如果都没有赢,就返回 'P',游戏继续。
//game.c
char judge(int chessboard[ROW][COL],int row,int col)
{
int i = 0;
for(i = 0; i < row; i++)
{
if(chessboard[i][0] == chessboard[i][1] && chessboard[i][1] == chessboard[i][2]
&& chessboard[i][0] != ' ')
{
return chessboard[i][0]; //判断一行是否相同
}
if(chessboard[0][i] == chessboard[1][i] && chessboard[1][i] == chessboard[2][i] && chessboard[0][i] != ' ')
{
return chessboard[0][i]; //判断一列是否相同
}
}
if(chessboard[0][0] == chessboard[1][1] && chessboard[1][1] == chessboard[2][2] && chessboard[0][0] != ' ')
{
return chessboard[0][0]; //判断右斜线是否相同
}
if(chessboard[0][2] == chessboard[1][1] && chessboard[1][1] == chessboard[2][0] && chessboard[1][1] != ' ')
{
return chessboard[0][2]; //判断左斜线是否相同
}
if(if_full(chessboard,row,col)) //判断是否平局,平局返回‘Q’
{
return 'Q';
}
return 'P';
}
与电脑下棋一来一回后,棋盘还未满,加一个while循环。如下
//test.c
void game()
{
int char = 0; //装判断函数的返回值
char chessboard[3][3]; //创建一个3*3的棋盘
init_chessboard(chessboard, ROW, COL); //初始化棋盘
print_chessboard(chessboard, ROW, COL); //打印棋盘
while(1)
{
player_playchess(chessboard, ROW, COL); //玩家下棋
ret = judge(chessboard, ROW, COL); //判断输赢
if( ret != 'P') //judge函数返回'P',游戏继续
{
break;
}
computer_playchess(chessboard, ROW, COL); //电脑下棋
ret = judge(chessboard, ROW, COL); //判断输赢
if( ret != 'P')
{
break;
}
}
如果三子棋棋盘都满了,并且还没分出胜负,游戏就平局。if_full判断棋盘是否满了,如全满返回1,然后在前面judge函数中返回'Q',来表示平局。
//game.c
int if_full(int chessboard[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(chessboard[i][j] == ' ')
return 0; //遍历一遍是否有空格,有返回0
}
}
return '1'; //如果棋盘都没有空格,返回‘1’
}
接着如果将judge返回值放在ret中,如果ret == '#',玩家胜利。如果ret == ' * ',电脑胜利。如果ret == 'Q',游戏平局。代码如下:
//test.c
void game()
{
char ret = 0; //装判断输赢函数的返回值
char chessboard[3][3]; //创建一个3*3的棋盘
init_chessboard(chessboard, ROW, COL); //初始化棋盘
print_chessboard(chessboard, ROW, COL); //打印棋盘
while(1)
{
player_playchess(chessboard, ROW, COL); //玩家下棋
ret = judge(chessboard, ROW, COL); //判断输赢
if( ret != 'P') //judge函数返回'P',游戏继续
{
break;
}
computer_playchess(chessboard, ROW, COL); //电脑下棋
ret = judge(chessboard, ROW, COL); //判断输赢
if( ret != 'P')
{
break;
}
}
if(ret == '#')
{
printf("玩家胜利!");
}
if(ret == '*')
{
printf("电脑胜利!");
}
if(ret == 'Q')
{
printf("游戏平局");
}
print_chessboard(chessboard, ROW, COL); //游戏结束再打印一下打印棋盘
}
将game.c源文件中代码的实现通过game.h头文件与test.c源文件进行联系。
#include
#include
#include
#define ROW 3
#define COL 3
void init_chessboard(chessboard[ROW][COL], int ROW, int COL);
void print_chessboard(chessboard[ROW][COL], int ROW, int COL);
void player_playchess(chessboard[ROW][COL], int ROW, int COL);
void computer_playchess(chessboard[ROW][COL], int ROW, int COL);
void judge(chessboard[ROW][COL], int ROW, int COL);
前面的电脑下棋太菜了,这次我们用代码提高电脑下棋水平。从而让“人工智障”变为“人工智能”。
我们需要电脑来“拦截”我们的棋子,当我们有两个棋子相连的时候三子棋,就要进行拦截了。否则,电脑随机下棋。实现代码如下:
int intell_computer(char chessboard[ROW][COL], int row, int col)
{
int i = 0;
//行判断
for (i = 0; i < row; i++)
{
if (chessboard[i][0] == chessboard[i][1] && chessboard[i][2] == ' ')
{
chessboard[i][2] = '*';
return 1;
}
if (chessboard[i][0] == chessboard[i][2] && chessboard[i][1] == ' ')
{
chessboard[i][1] = '*';
return 1;
}
if (chessboard[i][1] == chessboard[i][2] && chessboard[i][0] == ' ')
{
chessboard[i][0] = '*';
return 1;
}
}
//列判断
for (i = 0; i < col; i++)
{
if (chessboard[0][i] == chessboard[1][i] && chessboard[2][i] == ' ')
{
chessboard[2][i] = '*';
return 1;
}
if (chessboard[0][i] == chessboard[2][i] && chessboard[1][i] == ' ')
{
chessboard[1][i] = '*';
return 1;
}
if (chessboard[1][i] == chessboard[2][i] && chessboard[0][i] == ' ')
{
chessboard[0][i] = '*';
return 1;
}
}
//对角线判断
if (chessboard[1][1] == chessboard[0][0] && chessboard[2][2] == ' ')
{
chessboard[2][2] = '*';
return 1;
}
if (chessboard[0][0] == chessboard[2][2] && chessboard[1][1] == ' ')
{
chessboard[1][1] = '*';
return 1;
}
if (chessboard[1][1] == chessboard[2][2] && chessboard[0][0] == ' ')
{
chessboard[0][0] = '*';
return 1;
}
//斜对角线判断
if (chessboard[1][2] == chessboard[2][1] && chessboard[3][0] == ' ')
{
chessboard[3][i] = '*';
return 1;
}
if (chessboard[1][2] == chessboard[3][0] && chessboard[2][1] == ' ')
{
chessboard[2][1] = '*';
return 1;
}
if (chessboard[2][1] == chessboard[3][0] && chessboard[1][2] == ' ')
{
chessboard[1][2] = '*';
return 1;
}
return 0;
}
我们把这代码插入computer_playchess的实现里,代码如下:
//电脑下棋
void computer_playchess(char chessboard[ROW][COL], int row, int col)
{
printf("电脑下棋\n");
if (intell_computer(chessboard, row, col)) //判断是否复合拦截条件,复合进行拦截。
{
;
}
else
{
while (1)
{
int a = rand() % row; //用a,b装 0到2 的随机数
int b = rand() % col;
if (chessboard[a][b] == ' ') //判断输入坐标的地方是否为空格
{
chessboard[a][b] = '*';
break;
}
}
}
print_chessboard(chessboard,row,col); //打印下棋后的棋盘
}
//game.h
#include
#include
#include
#define ROW 3
#define COL 3
void init_chessboard(chessboard[ROW][COL], int ROW, int COL);
void print_chessboard(chessboard[ROW][COL], int ROW, int COL);
void player_playchess(chessboard[ROW][COL], int ROW, int COL);
void computer_playchess(chessboard[ROW][COL], int ROW, int COL);
void judge(chessboard[ROW][COL], int ROW, int COL);
//test.c
//test.c
#include"game.h"
void mune()
{
printf("******************************\n");
printf("******** 1.开始游戏 **********\n");
printf("******** 0.退出游戏 **********\n");
printf("******************************\n");
}
void game()
{
char ret = 0;
char chessboard[3][3] = { 0 }; //创建一个3*3的棋盘
init_chessboard(chessboard, ROW, COL); //初始化棋盘
system("cls");
print_chessboard(chessboard, ROW, COL); //打印棋盘
while (1)
{
player_playchess(chessboard, ROW, COL); //玩家下棋
print_chessboard(chessboard, ROW, COL); //打印下棋后的棋盘
ret = judge(chessboard, ROW, COL); //判断输赢
if (ret != 'P') //judge函数返回'P',游戏继续
{
break;
}
computer_playchess(chessboard, ROW, COL); //电脑下棋
ret = judge(chessboard, ROW, COL); //判断输赢
if (ret != 'P')
{
break;
}
}
if (ret == '#')
{
printf("玩家胜利!\n");
}
if (ret == '*')
{
printf("电脑胜利!\n");
}
if (ret == 'Q')
{
printf("游戏平局\n");
}
print_chessboard(chessboard, ROW, COL); //游戏结束再打印一下打印棋盘
}
int main()
{
int input = 0;
srand((unsigned)time(NULL)); //随机数的起点,后面会提到
do
{
mune();//打印游戏菜单
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
break;
default:
printf("选择错误,重新选择。\n");
break;
}
} while (input);
return 0;
}
//game.c
#include "game.h"
int intell_computer(char chessboard[ROW][COL], int row, int col)
{
int i = 0;
//行
for (i = 0; i < row; i++)
{
if (chessboard[i][0] == chessboard[i][1] && chessboard[i][2] == ' ')
{
chessboard[i][2] = '*';
return 1;
}
if (chessboard[i][0] == chessboard[i][2] && chessboard[i][1] == ' ')
{
chessboard[i][1] = '*';
return 1;
}
if (chessboard[i][1] == chessboard[i][2] && chessboard[i][0] == ' ')
{
chessboard[i][0] = '*';
return 1;
}
}
//列
for (i = 0; i < col; i++)
{
if (chessboard[0][i] == chessboard[1][i] && chessboard[2][i] == ' ')
{
chessboard[2][i] = '*';
return 1;
}
if (chessboard[0][i] == chessboard[2][i] && chessboard[1][i] == ' ')
{
chessboard[1][i] = '*';
return 1;
}
if (chessboard[1][i] == chessboard[2][i] && chessboard[0][i] == ' ')
{
chessboard[0][i] = '*';
return 1;
}
}
//对角线
if (chessboard[1][1] == chessboard[0][0] && chessboard[2][2] == ' ')
{
chessboard[2][2] = '*';
return 1;
}
if (chessboard[0][0] == chessboard[2][2] && chessboard[1][1] == ' ')
{
chessboard[1][1] = '*';
return 1;
}
if (chessboard[1][1] == chessboard[2][2] && chessboard[0][0] == ' ')
{
chessboard[0][0] = '*';
return 1;
}
//斜对角线
if (chessboard[1][2] == chessboard[2][1] && chessboard[3][0] == ' ')
{
chessboard[3][i] = '*';
return 1;
}
if (chessboard[1][2] == chessboard[3][0] && chessboard[2][1] == ' ')
{
chessboard[2][1] = '*';
return 1;
}
if (chessboard[2][1] == chessboard[3][0] && chessboard[1][2] == ' ')
{
chessboard[1][2] = '*';
return 1;
}
return 0;
}
void init_chessboard(char chessboard[ROW][COL],int row,int col)//初始化棋盘
{
int i, j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
chessboard[i][j] = ' '; //先将棋盘中的数打印成空格
}
}
}
void print_chessboard(char chessboard[ROW][COL], int row, int col)//打印棋盘
{
int i, j;
for (i = 0; i < row; i++) //运行三次后,打印棋盘
{
for (j = 0; j < col; j++) //运行三次后: %c | %c | %c
{
if (j == col - 1)
printf(" %c ", chessboard[i][j]);
else
printf(" %c |", chessboard[i][j]);
}
printf("\n");
for (j = 0; j < col; j++) //运行三次后: ---|---|---
{
if (i < row - 1)
{
if (j == col - 1)
printf("---");
else
printf("---|");
}
}
printf("\n");
}
}
//game.c
void player_playchess(char chessboard[ROW][COL], int row, int col)
{
printf("玩家下棋\n");
int a = 0; //创建a,b两个变量来储存坐标
int b = 0;
while (1)
{
printf("请输入下棋的坐标\n");
scanf("%d %d", &a, &b);
if (a > 0 && a < row + 1 && b > 0 && b < col + 1) //坐标必须在0到row(col)+1之间
{
if (chessboard[a - 1][b - 1] == ' ') //判断输入坐标的地方是否为空格
{
chessboard[a - 1][b - 1] = '#';
break;
}
else
printf("该坐标已被占用,请重新输入坐标\n");
}
else
{
printf("坐标非法,请重新输入\n");
}
}
}
//电脑下棋
void computer_playchess(char chessboard[ROW][COL], int row, int col)
{
printf("电脑下棋\n");
if (intell_computer(chessboard, row, col))
{
;
}
else
{
while (1)
{
int a = rand() % row; //用a,b装 0到2 的随机数
int b = rand() % col;
if (chessboard[a][b] == ' ') //判断输入坐标的地方是否为空格
{
chessboard[a][b] = '*';
break;
}
}
}
print_chessboard(chessboard,row,col); //打印下棋后的棋盘
}
static int if_full(char chessboard[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 (chessboard[i][j] == ' ')
return 0; //遍历一遍是否有空格,有返回0
}
}
return 1; //如果棋盘都没有空格,返回‘1’
}
char judge(char chessboard[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
if (chessboard[i][0] == chessboard[i][1] && chessboard[i][1] == chessboard[i][2] && chessboard[i][0] != ' ')
{
return chessboard[i][0]; //判断一行是否相同
}
}
for (i = 0; i < row; i++)
{
if (chessboard[0][i] == chessboard[1][i] && chessboard[1][i] == chessboard[2][i] && chessboard[0][i] != ' ')
{
return chessboard[0][i]; //判断一列是否相同
}
}
if (chessboard[0][0] == chessboard[1][1] && chessboard[1][1] == chessboard[2][2] && chessboard[0][0] != ' ')
{
return chessboard[0][0]; //判断右斜线是否相同
}
if (chessboard[0][2] == chessboard[1][1] && chessboard[1][1] == chessboard[2][0] && chessboard[1][1] != ' ')
{
return chessboard[0][2]; //判断左斜线是否相同
}
if (if_full(chessboard,row,col)) //判断是否平局,平局返回‘Q’
{
return 'Q';
}
return 'P';
}
好了,今天就到这了。如有瑕疵,请多指教。