1. 游戏设计
? ? ?game.h-----函数的声明
? ? ?game.c-----函数的定义
? ? ?test.c--------函数的测试
2. 游戏设计思路
? ? ?创建数组
? ? ?数组初始化
? ? ?打印棋盘
? ? ?布置雷
? ? ?排查雷
? ? ?运行结果
3. 完整代码
扫雷具体解析在代码的注释中,如有错误,请大家指正,谢谢~
创建数组
#define ROW 9 //行 用define定义扫雷的行 方便以后可以修改
#define COL 9 //列 用define定义扫雷的列 方便以后可以修改
#define ROWS ROW+2 //行 +2是为了用于排查雷,方便排查处在周围一圈的坐标
#define COLS COL+2 //列 +2是为了用于排查雷,方便排查处在周围一圈的坐标
char mine[ROWS][COLS] = { 0 }; //mine数组为布置雷的数组(这个数组我们不能让玩家看见,除非玩家已经输了)
char show[ROWS][COLS] = { 0 }; //show数组为布置雷的数组(这个数组是给玩家看的,需要玩家一个一个去排查)
数组初始化
InitBoard(mine, ROWS, COLS, '0'); //初始化 布置雷的棋盘 游戏设置雷为'1',非雷为'0',初始化先将mine数组初始为全'0'。
InitBoard(show, ROWS, COLS, '*'); //初始化 排查雷的棋盘 设置未排查的坐标为'*',初始化先将show数组初始化为全'*'。
void InitBoard(char board[ROWS][COLS], int rows, int cols, char ret) //初始化棋盘
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = ret;
}
}
}
打印棋盘
/*DisplayBoard(mine, ROW, COL); */ //打印 布置雷的棋盘 (我们无需打印mine数组,这里只是为了检查棋盘初始化是否正确)
DisplayBoard(show, ROW, COL); //打印 排查雷的棋盘 (游戏开始,需打印show数组,这个数组是让玩家去排查的数组)
void DisplayBoard(char board[ROWS][COLS], int row, int col) //打印棋盘
{
int i = 0;
int j = 0;
for (i = 0; i<=col; i++) // 为了方便玩家更快找到坐标 可以打印列号
{
printf("%d ",i);
}
printf("\n");
for (i = 1; i <=row; i++)
{
printf("%d ", i); //打印行号
for (j = 1; j <=col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
?
布置雷
#define EASY_COUNT 3 //设置雷数 用define定义方便以后可以修改
SetMine(mine, ROW, COL); //在mine里面布置雷
void SetMine(char mine[ROWS][COLS], int row, int col) //布置雷
{
int count = EASY_COUNT;
int x = 0;
int y = 0;
while (count)
{
x = rand() % row + 1; //产生1--9 坐标
y = rand() % col + 1; //产生1--9坐标
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
//DisplayBoard(mine, ROW, COL); //(我们不用打印mine数组,这个数组是用来存放雷的,这里打印只是为了检查布置雷是否正确)
排查雷
FindMine(mine,show, ROW, COL); // 排雷
static int get_mine_count(char mine[ROWS][COLS], int x, int y) //计算所输入坐标周围8个坐标的雷数
{ //用static修饰使它只能在本文件中使用(也可不用)
return mine[x + 1][y - 1] + //为后面的FindMine函数做准备
mine[x][y - 1] +
mine[x - 1][y - 1] +
mine[x - 1][y] +
mine[x + 1][y] +
mine[x - 1][y + 1] +
mine[x][y + 1]+ mine[x + 1][y + 1] - 8 * '0';
}
static int Check(char show[ROWS][COLS], int row, int col) //遍历整个棋盘
{ //若未排的位置个数与雷数相等,则排雷成功
int i = 0;
int j = 0;
int win = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (show[i][j] == '*')
{
win++; //计算未排的位置并返回,与雷数作比较(为下面的FineMine函数做准备)
}
}
}
return win;
}
void board(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) //拓展周围是不是雷区
{
int count = 0;
if (x == 0 || y == 0 || x == ROWS - 1 || y == COLS - 1) //判断该坐标是否越界
{
return;
}
if (show[x][y] != '*') //判断该坐标是否已经排查
{
return;
}
count = get_mine_count(mine, x, y);
if (count > 0)
{
show[x][y] = count + '0'; //若该坐标未排除,且周围8个坐标有雷,则通过get_mine_count函数计算返回计算值
return;
}
else if (count == 0) //若该坐标周围8个坐标都没有雷,则标志该坐标为'0',且沿着这8个坐标的方向进行递归,遇到雷就停下来。
{
show[x][y] = '0';
board(mine, show, x - 1, y);
board(mine, show, x - 1, y - 1);
board(mine, show, x, y - 1);
board(mine, show, x + 1, y - 1);
board(mine, show, x + 1, y);
board(mine, show, x + 1, y + 1);
board(mine, show, x, y + 1);
board(mine, show, x - 1, y + 1);
}
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) //排雷
{
int x = 0;
int y = 0;
int win = 0;
while (win<row*col-EASY_COUNT) //循环条件不能写为1,否则将会漏掉玩家全部排查成功的可能。
{
printf("请输入坐标>:");
scanf("%d%d", &x, &y);
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (mine[x][y] == '1')
{
printf("猜到雷,游戏结束\n");
DisplayBoard(mine, row, col); //玩家输了,展示布置雷的数组,让玩家输的明白
break;
}
else
{
board(mine,show,x,y); //调用board函数
DisplayBoard(show, row, col); //玩家排完一次雷,要打印排查雷的结果(show数组)
}
win = Check(show, row, col); //调用Check函数
if (win == EASY_COUNT)
{
break;
}
}
else
{
printf("输入的坐标非法,请重新输入\n");
}
}
if (win == EASY_COUNT) //若未排的位置个数与雷数相等,则排雷成功
{
printf("恭喜你排雷成功\n");
DisplayBoard(mine, row, col);
}
}
运行结果
完整代码
扫雷(含递归展开)完整代码
? ?? ??
|