目录
游戏整体思路
游戏主要内容实现
1、存储布雷位置信息
2、初始化扫雷棋盘信息
3、打印棋盘
4、布置雷
5、排查雷
扫雷游戏优化
在写代码前,我们将次游戏的组成分为三部分:
第一部分:源文件添加创建test.c ,用于测试游戏逻辑。
第二部分:源文件添加创建game.c ,用于函数的实现。
第三部分:头文件添加创建game.h ,用于函数的声明。
游戏整体思路
玩游戏时,首先映入眼帘的应是菜单界面,所以在我们main函数中应写入菜单函数,菜单中包括1.play,0.exit。在玩游戏时应选择玩游戏或者退出游戏,在这里使用switch case分支语句进行实现。进行游戏过程是多次的,直至不想玩退出游戏,在这里使用do while语句实现。
代码实现:
void menu()
{
printf("**********************\n");
printf("******* 1.play *******\n");
printf("******* 0.exit *******\n");
printf("**********************\n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请输入选项:>\n");
scanf_s("%d", &input);
switch (input)
{
case 1:
printf("扫雷游戏\n");
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入:>\n");
break;
}
} while (input);
return 0;
}
代码测试运行结果展现:
游戏主要内容实现
1、存储布雷位置信息
在这里,我们首先选择一个9*9的二维数组存储布置雷的位置信息,布雷的位置记为1,没布雷的位置记为0。再另外使用9*9的二维数组,存储排查出的雷的信息,没有排查的位置全部初始化为'*',排查出来雷的,记成周围雷的个数。我们游戏的规则一般是排查以一个方块为中心其余8个方块的位置是否有雷,为了防止在排查的过程中数组访问越界,我们在9*9的数组基础上扩展为11*11数组。
2、初始化扫雷棋盘信息
我们希望布雷的棋盘所有位置初始化为0;排查雷的信息的棋盘所有位置初始化为*。把两类棋盘全部初始化为没有雷和没有排查雷的情况。
代码实现:
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
}
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
3、打印棋盘
在打印棋盘这部分,值得我们注意的是,我们之前为了避免数组访问越界将棋盘的行和列都各增加了两行两列,但是在我们展现游戏界面的时候,这两行两列是不用展现出来的。更重要的是这应该在我们之前初始化的原11*11的数组上展现9*9的数组。
代码实现:
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
代码测试运行结果展现:
此展现棋盘有一个弊端就是如果行数和列数再多我们就很难去数我们要扫哪行哪列,所以在这个问题的基础上,我们对代码进行了改进,代码改进结果如下:
代码实现:
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");
}
}
代码测试运行结果展现:
注:这里我们也可以加上布置雷的棋盘的打印
4、布置雷
布置雷是在布置雷的棋盘上进行的,原则上,我们只在9*9的棋盘内布置雷,但是还是在11*11的棋盘基础上布置内部9*9的雷,这是我们在布置雷的过程中需要注意的。
代码实现 :
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
int x = rand() % row + 1;
int y = rand() % col + 1;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
代码测试运行结果展现:
5、排查雷
同上,我们排查雷也是在11*11的数组内进行的,只不过雷存储在9*9的棋盘里。之后就进入我们的排查雷的过程,排查雷的过程是循环的,我们输入我们想排查的坐标,如果是雷,那游戏就结束跳出循环,如果不是雷,就要继续下去,统计该坐标的周围8个坐标有多少雷。在这个过程中我们要不断判断坐标是否被排查过。
统计雷的个数的方法:
将x,y周围的8个坐标所表示的字符加起来再减去8乘字符0,因为我们在初始化布雷数组时,有雷的位置放置的是字符1,没有雷的位置防止的是字符0。
统计完雷的个数后,我们将相应的字符赋值给排查雷信息的数组。之后我们要考虑什么时候才算雷已经排完呢?如果我们在数组内设置了10个雷,那么不是雷的格子就有71个,所以我们循环扫雷的过程就是循环的去统计不是雷的个数,当不是雷的格子个数等于71时,扫雷成功!
代码实现 :
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
return (mine[x - 1][y - 1] +
mine[x - 1][y] +
mine[x - 1][y + 1] +
mine[x][y - 1] +
mine[x][y + 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1]-8*'0');
}
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 < (col * row) - EASY_COUNT)//不是雷格子的个数
{
printf("请输入你要排查的坐标:>\n");
scanf_s("%d", &x);
scanf_s("%d", &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')//坐标没有被排查过
{
if (mine[x][y] == '1')
{
printf("游戏结束,你被炸死了!\n");
DisplayBoard(mine, ROW, COL);
break;
}
else if (mine[x][y] == '0')
{
//统计雷的个数
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';//得到字符3,放在排雷信息数组中
DisplayBoard(show, ROW, COL);
win++;
}
}
else
{
printf("该位置已经被排查\n");
}
}
else
{
printf("坐标非法,请重新输入:>\n");
}
}
if (win == (col * row) - EASY_COUNT)
{
printf("恭喜你,排雷成功!\n");
DisplayBoard(mine, ROW, COL);
}
}
代码测试运行结果展现: