扫雷
- 一、问题描述
- 二、基本流程
- 三、步骤
-
- 1.菜单界面
- 2.创建地图
- 3.初始化地图
- 4.打印地图
- 5.玩家翻开坐标
- 6.判断是否为地雷
- 7.更新地图
- 8.判断是否胜利
- 四、代码实现
一、问题描述
用C语言实现简易版扫雷。
二、基本流程
1.菜单界面。
2.创建地图 (两个地图)。
3.初始化地图。
4.打印地图。
5.程序读取玩家输入的要翻开位置的坐标,并校验。
6.如果不是地雷,统计当前位置周围雷的个数, 并显示到地图上.。
7.判定游戏是否胜利。
三、步骤
1.菜单界面
1.开始游戏 0.退出游戏
1int menu(){ 2 3 4 printf("----------------------\n"); 5 printf("------1.开始游戏------\n"); 6 printf("------0.退出游戏------\n"); 7 printf("----------------------\n"); 8 int choice = 0; 9 printf("请输入你的选择:"); 10 scanf("%d", &choice); 11 return choice; 12}
2.创建地图
我们需要两张地图,所以要创建两个二维数组。
第一个二维数组,表示玩家看到的地图。(show)
第二个二维数组,表示当前位置是不是地雷(1表示是地雷,0表示不是地雷)。(mine)
使用宏定义的原因:
1.推高代码可读性,后续代码中遇到9,方便理解含义。
2.提高扩展性,如果将来要修改棋盘尺寸,代码修改会很方便。
1#define MAX_ROW 9 2#define MAX_COL 9 3 char show[MAX_ROW][MAX_COL] = { 4 5 0 }; 6 char mine[MAX_ROW][MAX_COL] = { 7 8 0 };
3.初始化地图
使用 * 表示未翻开的地。
show地图一开始全都是 * 。
mine地图是由0,1组成的。(1表示是地雷,0表示不是地雷)一开始都为0,随后由电脑随机在地图上生成1。
这里我们使用宏定义了DIFFICULTY,表示地雷的数量:10个。
1#define DIFFICULTY 10 2void init(char show[MAX_ROW][MAX_COL], char mine[MAX_ROW][MAX_COL]){ 3 4 5 for (int row = 0; row < MAX_ROW; row++){ 6 7 8 for (int col = 0; col < MAX_COL; col++){ 9 10 11 show[row][col] = '*'; 12 //初始化 mine,先全设为'0', 然后随机生成n个'1' 13 mine[row][col] = '0'; 14 } 15 } 16 int n = DIFFICULTY; 17 while (n>0){ 18 19 20 // 生成雷的随机位置 21 int row = rand() % MAX_ROW; 22 int col = rand() % MAX_COL; 23 if (mine[row][col] == '1'){ 24 25 26 // 如果当前位置已经有雷了,就直接进入下次循环, 重新产生随机位置 27 continue; 28 } 29 mine[row][col] = '1'; 30 n--; 31 } 32}
4.打印地图
打印出地图。
1void printMap(char themap[MAX_ROW][MAX_COL]){ 2 3 4 printf(" |"); 5 for (int col = 0; col < MAX_COL; col++) { 6 7 8 printf("%d ", col); 9 } 10 printf("\n"); 11 printf("--+------------------\n"); 12 for (int row = 0; row < MAX_ROW; row++) { 13 14 15 printf(" %d|", row); 16 for (int col = 0; col < MAX_COL; col++) { 17 18 19 printf("%c ", themap[row][col]); 20 } 21 printf("\n"); 22 } 23}
5.玩家翻开坐标
玩家通过输入坐标的方式翻开土地。
注意:
1.输入坐标要在地图范围内。
2.不能重复翻开土地。
1 //程序读取玩家输入的要翻开位置的坐标, 并校验 2 int row = 0; 3 int col = 0; 4 printf("请输入翻开的坐标(row col):"); 5 scanf("%d %d", &row, &col); 6 if (row < 0 || col < 0 || row >= MAX_ROW || col >= MAX_COL){ 7 8 9 printf("输入的坐标超过范围,重新输入:\n"); 10 continue; 11 } 12 if (show[row][col] != '*'){ 13 14 15 printf("已经翻开,请重新输入:\n"); 16 continue; 17 }
6.判断是否为地雷
如果翻开的位置在mine上显示为1,那么翻到地雷了,输出被炸死,打印地雷地图,让玩家死得明白。
如果翻开的位置上在mine上不是1,那么继续下一步骤。
1if (mine[row][col] == '1'){ 2 3 4 printf("你已经被炸死了!!!\n"); 5 printMap(mine); 6 break; 7 }
7.更新地图
计算周围的地雷数量,在翻开位置显示。
1updateShow(show,mine,row,col); 2 3 4// 根据当前 row, col 的位置, 计算出当前位置周围有几个雷 5// 并且更新显示到 show 中 6void updateShow(char show[MAX_ROW][MAX_COL], char mine[MAX_ROW][MAX_COL], int row, int col){ 7 8 9 int count = 0; 10 for (int r = row - 1; r <= row + 1; r++) { 11 12 13 for (int c = col - 1; c <= col + 1; c++) { 14 15 16 if (r < 0 || r >= MAX_ROW 17 || c < 0 || c >= MAX_COL) { 18 19 20 continue; 21 } 22 if (mine[r][c] == '1') { 23 24 25 count++; 26 } 27 } 28 } 29 //此时 count 里面就已经存好了 row, col 周围 八个格子 的雷的个数 30 // 把这个结果写到 show 中即可. 31 // 需要把数字 count 转成对应的字符 32 show[row][col] = count + '0'; 33 34}
8.判断是否胜利
定义一个变量safe,表示翻开的不是地雷的土地,每次更新地图后,safe加一。如果最后翻开的不是地雷的土地等于地图的大小减地雷数,那么排除所有地雷,确认安全。
1 //记录翻开的格子的个数 2 int safe = 0; 3 updateShow(show,mine,row,col); 4 safe++; 5 if (safe == MAX_ROW*MAX_COL - DIFFICULTY){ 6 7 8 printf("已经排除所有的雷,你已经安全!!!\n"); 9 printMap(mine); 10 break; 11 }
四、代码实现
1#define _CRT_SECURE_NO_WARNINGS 2#define MAX_ROW 9 3#define MAX_COL 9 4#define DIFFICULTY 10 5#include <stdio.h> 6#include <time.h> 7#include <stdlib.h> 8 9int menu(){ 10 11 12 printf("----------------------\n"); 13 printf("------1.开始游戏------\n"); 14 printf("------0.退出游戏------\n"); 15 printf("----------------------\n"); 16 int choice = 0; 17 printf("请输入你的选择:"); 18 scanf("%d", &choice); 19 return choice; 20} 21void init(char show[MAX_ROW][MAX_COL], char mine[MAX_ROW][MAX_COL]){ 22 23 24 for (int row = 0; row < MAX_ROW; row++){ 25 26 27 for (int col = 0; col < MAX_COL; col++){ 28 29 30 show[row][col] = '*'; 31 mine[row][col] = '0'; 32 } 33 } 34 int n = DIFFICULTY; 35 while (n>0){ 36 37 38 int row = rand() % MAX_ROW; 39 int col = rand() % MAX_COL; 40 if (mine[row][col] == '1'){ 41 42 43 continue; 44 } 45 mine[row][col] = '1'; 46 n--; 47 } 48} 49void printMap(char themap[MAX_ROW][MAX_COL]){ 50 51 52 printf(" |"); 53 for (int col = 0; col < MAX_COL; col++) { 54 55 56 printf("%d ", col); 57 } 58 printf("\n"); 59 printf("--+------------------\n"); 60 for (int row = 0; row < MAX_ROW; row++) { 61 62 63 printf(" %d|", row); 64 for (int col = 0; col < MAX_COL; col++) { 65 66 67 printf("%c ", themap[row][col]); 68 } 69 printf("\n"); 70 } 71} 72void updateShow(char show[MAX_ROW][MAX_COL], char mine[MAX_ROW][MAX_COL], int row, int col){ 73 74 75 int count = 0; 76 for (int r = row - 1; r <= row + 1; r++) { 77 78 79 for (int c = col - 1; c <= col + 1; c++) { 80 81 82 if (r < 0 || r >= MAX_ROW 83 || c < 0 || c >= MAX_COL) { 84 85 86 continue; 87 } 88 if (mine[r][c] == '1') { 89 90 91 count++; 92 } 93 } 94 } 95 show[row][col] = count + '0'; 96 97} 98void game(){ 99 100 101 char show[MAX_ROW][MAX_COL] = { 102 103 0 }; 104 char mine[MAX_ROW][MAX_COL] = { 105 106 0 }; 107 init(show, mine); 108 int safe = 0; 109 while (1){ 110 111 112 printMap(show); 113 int row = 0; 114 int col = 0; 115 printf("请输入翻开的坐标(row col):"); 116 scanf("%d %d", &row, &col); 117 if (row < 0 || col < 0 || row >= MAX_ROW || col >= MAX_COL){ 118 119 120 printf("输入的坐标超过范围,重新输入:\n"); 121 continue; 122 } 123 if (show[row][col] != '*'){ 124 125 126 printf("已经翻开,请重新输入:\n"); 127 continue; 128 } 129 if (mine[row][col] == '1'){ 130 131 132 printf("你已经被炸死了!!!\n"); 133 // 打印一遍地雷的地图, 让玩家死的明白 134 printMap(mine); 135 break; 136 } 137 updateShow(show, mine, row, col); 138 safe++; 139 if (safe == MAX_ROW*MAX_COL - DIFFICULTY){ 140 141 142 printf("已经排除所有的雷,你已经安全!!!\n"); 143 // 打印一遍地雷的地图, 让玩家知道雷在哪 144 printMap(mine); 145 break; 146 } 147 } 148} 149int main() 150{ 151 152 153 srand((unsigned int)time(0)); 154 while (1){ 155 156 157 int choice = menu(); 158 if (choice == 1){ 159 160 161 game(); 162 } 163 else if (choice == 0){ 164 165 166 printf("退出游戏,byebye!"); 167 break; 168 } 169 else{ 170 171 172 printf("输入错误,请重新输入:"); 173 continue; 174 } 175 176 } 177}