一、扫雷游戏大致逻辑
扫雷游戏作为1992年的代表游戏一经发行便风靡全球,通过锻炼玩家的耐心和观察推理能力吸引了广大爱好者,今天我们通过C语言来实现扫雷游戏。
为了方便代码的整体性和逻辑性,我们采用多文件的形式进行创作。
game.h:头文件的包含和函数的声明
game.c:函数的实现
test.c:菜单的打印,代码的测试及游戏大致框架的构建
和猜数字游戏一样,我们需要在test.c文件中使用分支循环语句实现菜单打印和游戏整体循环(为了保证main函数的简洁性封装test()函数加以实现)。接下来就是初始化、打印、布置雷,排查雷。多使用数组和函数相关的知识,这就是扫雷大致的逻辑。
二、数组初始化和打印
我们假设用字符‘1’表示雷,字符‘0’表示空(这样方便后续排查雷的计算)。
通过使用二维数组把棋盘初始化的信息保存起来。我们先使用9*9的棋盘,用#define宏定义指令ROW(9),COL(9)为雷坐标的行和列。但是这里有一个问题,后续排查雷的时候需要统计九宫格内雷的个数,在访问到边界时会造成数组越界,因此我们将棋盘扩展为11*11,用ROWS(ROW+2)和COLS(COL+2)表示新的行和列。
扫雷的关键是布置雷的信息和排查雷的信息。为此我们定义两个数组char mine[ROWS][COLS](布置雷的信息),char show[ROWS][COLS](排查雷的信息)。封装函数 void InitBoard(char arr[ROWS][COLS],int rows,int cols,int set);(set 表示要初始化的信息,mine初始化成‘0’,show初始化成'*') 。多设计一个set参数可以在初始化时让arr[ROWS][COLS]=set,这样既保证了数据内容的正确性,又不用初始化两次减少了代码冗余,体现了设计巧妙性。
通过循环将行号列号标注,更加的清晰明了。
游戏实现需用到的函数:
创建11*11的棋盘主要是辅助9*9,后续的主要功能都是在9*9棋盘上实现,之后传参回改变为ROW和COL,但数组大小一旦给定就无法改变,仍然为ROWS和COLS,这里需要注意。
三、布置雷
封装函数:void SetMind(char arr[ROWS][COLS],int row,int col);
宏定义EASY_COUNT表示雷的个数。调用srand((unsigned int)time.h(NULL))函数,定义count=EASY_COUNT进入循环每循环一次count--,在9*9棋盘上随机生成10个雷。
四、排查雷
封装函数:void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);我们先在mine数组的九宫格中统计雷的个数,再赋给show数组。
排查雷是本游戏实现的重点和难点,我们需要统计输入坐标九宫格的雷的个数。为此我们再次封装一个函数:GetMineCount (char mine[ROWS][COLS],int x,int y);(x,y表示玩家输入的坐标) 这里有两个方法实现 (1)统计九宫格的字符数和—8*‘0’ (2)定义ret变量+=(mine[i][j]—'0')(i j是循环变量) (注意:字符'1'和字符'0'不是数字1和0,但差值仍为1,体现了雷和空的巧妙性)。
定义变量win,循环条件是win<row*col—EASY_COUNT,结束条件是win=row*col—EASY_COUNT或者被雷炸死break跳出循环。
FindMine()函数的分支较多:(1)判断输入坐标是否越界,是否有效 (2)判断坐标是否为雷 (3)是雷跳出循环打印mine棋盘,不是雷调用GetMineCount()函数,用count接收其返回值。show [ROWS] [COLS] = count+'0'打印show棋盘。
五、扩展及完整代码
1.是否可以选择难度 9*9 16*16 30*30
2.如果输入位置不是雷,周围也没有雷,是否可以展开一片。(提示用递归)
3.是否可以标记雷
4.是否可以加上排雷显示
game.h
game.c
test.c
到此为止扫雷游戏已全部完成,创作不易还请各位多多三连哦。