扫雷游戏
扫雷游戏也是我们常见的小游戏,今天我们来简单实现一下这个小游戏(简陋版).
1. 菜单
首先我们创建一个菜单,供玩家选择,菜单跟上一期的三子棋的菜单一样,这里就不多说了;
void menu() { printf("*************************************************\n"); printf("************** 1.进入游戏 *****************\n"); printf("************** 0.退出游戏 *****************\n"); printf("*************************************************\n"); printf("*************************************************\n"); }
这里是主函数部分,实现玩家选择哪个菜单的代码:
int main() { int input = 0; srand((unsigned int)time(NULL)); do { menu(); printf("请选择:\n"); scanf("%d", &input); switch (input) { case 1: game(); break; case 2: printf("退出游戏\n"); break; default: break; } } while (input); return 0; }
2.game()函数
是实现整个游戏的主体部分,在这里我们一步一步看;
- 首先创建两个数组mine和show,mine数组是布置雷的信息,show数组是展示给玩家看的扫雷界面;其中ROW=COL=9,ROWS=COLS=ROW+2= COL+2=11,这里创建11×11的数组是为了后面统计雷的个数,但实际玩家操作的是9×9的数组;
- InitBoard()函数将两个数组都初始化为对应的字符;
- DisplayBoard()函数是打印相应数组的扫雷界面的函数;
- SetMine()函数是布置雷的函数;
- FindMine()函数是实现排雷的函数;
void game() { //雷的信息存储 //1.布置雷的信息 char mine[ROWS][COLS] = { 0 }; //2.排查出雷的信息 char show[ROWS][COLS] = { 0 }; //初始化 InitBoard(mine, ROWS, COLS,'0'); InitBoard(show, ROWS, COLS,'*'); //打印扫雷界面 DisplayBoard(show, ROW, COL); //布置雷 SetMine(mine,ROW,COL); //DisplayBoard(mine, ROW, COL); //扫雷 FindMine(mine,show,ROW,COL); }
3.InitBoard()函数
这里InitBoard()函数是将两个数组初始化成相应的字符,mine数组初始化成’ 0 ',0代表不是雷;show数组初始化成’ * ‘;这里设置一个char set来接收字符,然后数组需要哪个字符就可以用一次循环完成初始化;
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set) { int i = 0; int j = 0; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { board[i][j] = set; } } }
4. DisplayBoard()函数
DisplayBoard()函数是打印当前扫雷界面的函数,在显示给玩家参考的show数组中,我们用’ * ‘给玩家参考;此外,为了让玩家的游戏效率高一些,我们在扫雷游戏的界面打印了列号和行号,方便玩家参考;这里要注意打印字符的循环,下标要从1开始,不能从0开始,我一开始就是从0开始,结果在打印布置完雷的函数的时候,假如布置10个雷,有时候就不够10个雷,结果调试半天才找出这个bug;
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"); } printf("\n"); }
5. SetMine()函数
SetMine()函数是布置雷的函数,我们传入mine数组,行数为row,列数为col,我们需要布置雷的范围是1-9行和1-9列,所以传入的行数和列数分别是row和col;这里调用rand()函数生成随机数,而rand() % row是随机生成0-8的数,所以加1是生成1-9的数,刚好满足行数和列数的要求;我们布置雷的过程是,当这个随机生成的坐标位置是’ 0 ‘,就把当前位置改为’ 1 ',即为雷;否则继续循环生成随机数,当count减到0时循环结束,布置雷成功;
void SetMine(char board[ROWS][COLS], int row, int col) { //定义EASY_COUNT为10 int count = EASY_COUNT; while (count) { int x = rand() % row + 1; //1-9 int y = rand() % col + 1; //1-9 if (board[x][y] == '0') { board[x][y] = '1'; count--; } } }
6.FindMine()函数
(1)FindMine()函数是实现排雷的函数,在这里需要传进来两个数组mine和show,需要对两个数组进行操作;
首先进来先判断坐标合理性,合理则判断是否踩雷,即玩家输入的坐标位置是否是字符 ’ 1 ',若是则提示玩家,退出到游戏菜单;否则提示玩家坐标不合法,重新输入;如果没有踩雷,则提示玩家输入的当前坐标周围的8个坐标雷的个数,这里调用get_mine_count()函数进行统计(下面介绍);当玩家排完雷即提示玩家排雷成功.
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) { printf("请输入排查雷的坐标:\n"); scanf_s("%d%d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { //坐标合法 //1.踩雷 if (mine[x][y] == '1') { printf("很遗憾,您踩雷了\n"); DisplayBoard(mine, row, col); break; } //2.没踩雷 else { //计算x,y周围有多少雷 int count = get_mine_count(mine, x, y); show[x][y] = count + '0';//count是数字,相当于把数字转成字符 DisplayBoard(show, row, col); win++; } } else printf("输入坐标非法,请重新输入!\n"); } if (win == row * col - EASY_COUNT) { printf("恭喜您,排雷成功\n"); DisplayBoard(mine, row, col); } }
(2) get_mine_count()函数
这里将玩家输入坐标的周围8个坐标的雷统计出来,返回这个值;注意棋盘中放的雷和非雷,即1和0都是字符,所以将字符转成数字需要减去字符’ 0 ',计算这8个坐标的和的时候就要减去8 * ’ 0 ';
int get_mine_count(char mine[ROWS][COLS], int x, int y) { return mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] + mine[x][y + 1] + mine[x - 1][y - 1] - 8 * '0';//字符0不是数字0,原数组存放的都是字符,相当于把字符转成数字 }