c++实现扫雷游戏
设计思路
定义一个结构体,里面存放每一个格子是否被翻开,已经地雷和格子周围地雷数量。用结构体定义一个二维数组,随机放入特定数量的地雷。玩家输入要翻开的格子的行数和列数。用一个函数来翻开目标格子,如果是地雷游戏失败,否则用一个函数统计目标格子周围的地雷数。如果周围没有地雷,则递归使用一个函数将附近周围没有地雷的格子全部打开,最后判断是否游戏胜利,没有就继续让玩家输入行数和列数。
代码实现
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<time.h> 4 5 #define HEIGHT 10 //定义地图高度 6 #define WIDHT 10 //定义地图宽度 7 #define BOON_NUM 10 //定义地雷数量 8 9 struct square 10 { 11 bool isOpen; //定义是否被翻开 12 int groundBoon; //定义格子周围的地雷数量,值为-1时代表本格就是地雷 13 }; 14 square map[HEIGHT][WIDHT]; //定义地图 15 16 //地图初始化 17 void csh() 18 { 19 int *p; 20 //地图初始化 21 for (int i = 0;i < HEIGHT;i++) 22 for (int j = 0;j < WIDHT;j++) 23 { 24 map[i][j].groundBoon = 0; 25 map[i][j].isOpen = false; 26 } 27 28 //随机地雷 29 srand(time(NULL)); 30 p = &map[rand() % HEIGHT][rand() % WIDHT].groundBoon; 31 *p = -1; 32 for(int i=0;i<BOON_NUM-1;i++) 33 { 34 while (*p == -1) 35 { 36 p = &map[rand() % HEIGHT][rand() % WIDHT].groundBoon; 37 } 38 *p = -1; 39 } 40 41 } 42 43 //输出地图 44 void sc() 45 { 46 printf(" "); 47 for (int i = 0;i < WIDHT;i++) 48 printf("%d ",i); 49 printf("\n"); 50 for (int i = 0;i < HEIGHT;i++) 51 { 52 printf("%d ",i); 53 for (int j = 0;j < WIDHT;j++) 54 { 55 if (map[i][j].isOpen) 56 if (map[i][j].groundBoon==-1) 57 printf("* "); 58 else if (map[i][j].groundBoon == 0) 59 printf(" "); 60 else 61 printf("%d ", map[i][j].groundBoon); 62 else 63 printf("@ "); 64 } 65 printf("\n"); 66 } 67 printf("\n总共%d个地雷\n",BOON_NUM); 68 } 69 //大面积翻开周围没有雷的方块 70 void bigOpen(int openH, int openW) 71 { 72 int temp; 73 int ground(int openH, int openW); //定义判断周围地雷数量的函数 74 75 map[openH][openW].groundBoon = 0; 76 map[openH][openW].isOpen = true; 77 78 if (openH - 1 >= 0 && openW - 1 >= 0&&map[openH - 1][openW - 1].isOpen == false) 79 { 80 temp = ground(openH-1, openW-1); 81 map[openH - 1][openW - 1].groundBoon = temp; 82 map[openH - 1][openW - 1].isOpen = true; 83 } 84 if (openH - 1 >= 0 && map[openH - 1][openW].isOpen == false) 85 { 86 temp = ground(openH-1, openW); 87 map[openH - 1][openW].groundBoon = temp; 88 map[openH - 1][openW].isOpen = true; 89 } 90 if (openH - 1 >= 0 && openW + 1 < WIDHT && map[openH - 1][openW + 1].isOpen == false) 91 { 92 temp = ground(openH-1, openW+1); 93 map[openH - 1][openW + 1].groundBoon = temp; 94 map[openH - 1][openW + 1].isOpen = true; 95 } 96 if (openW - 1 >= 0 && map[openH][openW - 1].isOpen == false) 97 { 98 temp = ground(openH, openW-1); 99 map[openH][openW - 1].groundBoon = temp; 100 map[openH][openW - 1].isOpen = true; 101 } 102 if (openW + 1 < WIDHT && map[openH][openW + 1].isOpen == false) 103 { 104 temp = ground(openH, openW+1); 105 map[openH][openW + 1].groundBoon = temp; 106 map[openH][openW + 1].isOpen = true; 107 } 108 if (openH + 1 < HEIGHT && openW - 1 >= 0 && map[openH + 1][openW - 1].isOpen == false) 109 { 110 temp = ground(openH+1, openW-1); 111 map[openH + 1][openW - 1].groundBoon = temp; 112 map[openH + 1][openW - 1].isOpen = true; 113 } 114 if (openH + 1 < HEIGHT && map[openH + 1][openW].isOpen == false) 115 { 116 temp = ground(openH+1, openW); 117 map[openH + 1][openW].groundBoon = temp; 118 map[openH + 1][openW].isOpen = true; 119 } 120 if (openH + 1 < HEIGHT && openW + 1 < WIDHT && map[openH + 1][openW + 1].isOpen == false) 121 { 122 temp = ground(openH+1, openW+1); 123 map[openH + 1][openW + 1].groundBoon = temp; 124 map[openH + 1][openW + 1].isOpen = true; 125 } 126 } 127 //查找周围地雷数量 128 int ground(int openH, int openW) 129 { 130 int sum = 0; //用以累计周围地雷数量 131 132 if (openH - 1 >= 0 && openW - 1 >= 0 && map[openH - 1][openW - 1].groundBoon == -1) 133 sum++; 134 if (openH - 1 >= 0 && map[openH - 1][openW].groundBoon == -1) 135 sum++; 136 if (openH - 1 >= 0 && openW + 1 < WIDHT && map[openH - 1][openW + 1].groundBoon == -1) 137 sum++; 138 if ( openW - 1 >= 0 && map[openH ][openW - 1].groundBoon == -1) 139 sum++; 140 if (openW + 1 < WIDHT && map[openH][openW +1].groundBoon == -1) 141 sum++; 142 if (openH + 1 < HEIGHT && openW - 1 >= 0 && map[openH +1][openW - 1].groundBoon == -1) 143 sum++; 144 if (openH + 1 < HEIGHT && map[openH+ 1][openW ].groundBoon == -1) 145 sum++; 146 if (openH +1 < HEIGHT && openW + 1 < WIDHT && map[openH + 1][openW + 1].groundBoon == -1) 147 sum++; 148 if (sum == 0) //如果周围没有雷,则大面积翻开周围的同样周围没雷的方块 149 bigOpen(openH, openW); 150 return sum; 151 } 152 //翻开指定方块 153 bool open(int openH,int openW) 154 { 155 if (map[openH][openW].isOpen) //如果翻开重复的方块则返回0 156 return false; 157 if (map[openH][openW].groundBoon == -1) //如果翻开地雷游戏结束 158 return true; 159 160 map[openH][openW].groundBoon=ground(openH, openW); 161 map[openH][openW].isOpen = true; 162 return false; 163 } 164 //游戏结束画面 165 void end() 166 { 167 for (int i = 0;i < HEIGHT;i++) 168 for (int j = 0;j < WIDHT;j++) 169 if (map[i][j].groundBoon == -1) 170 map[i][j].isOpen = true; 171 sc(); 172 } 173 //判断是否胜利 174 bool win() 175 { 176 for (int i = 0;i < HEIGHT;i++) 177 for (int j = 0;j < WIDHT;j++) 178 if (!map[i][j].isOpen && map[i][j].groundBoon != -1) //只要找到没翻开的并且不是地雷的方块就没胜利 179 return false; 180 return true; 181 } 182 void main() 183 { 184 bool isEnd=false,isWin=false; //定义游戏结束条件和胜利条件 185 int openH, openW; //定义要打开的行数和列数 186 int isAgain; //定义结束后是否重开游戏 187 188 csh(); 189 while(!isEnd&&!isWin) 190 { 191 sc(); 192 printf("请输入要打开的格子行数:"); 193 scanf_s("%d",&openH); 194 while (openH<0||openH>HEIGHT) //如果输入数字不正确则循环重新输入 195 { 196 printf("请输入正确的行数:"); 197 scanf_s("%d", &openH); 198 } 199 printf("请输入要打开的格子列数:"); 200 scanf_s("%d", &openW); 201 while (openW<0 || openW>HEIGHT) //如果输入数字不正确则循环重新输入 202 { 203 printf("请输入正确的列数:"); 204 scanf_s("%d", &openW); 205 } 206 isEnd=open(openH,openW); 207 isWin = win(); 208 system("cls"); 209 } 210 end(); 211 if (isWin) 212 printf("恭喜你,扫雷成功!!!\n"); 213 else 214 printf("可惜,扫雷失败!\n"); 215 printf("输入1重开游戏,输入其他任意数字退出游戏:"); 216 scanf_s("%d",&isAgain); 217 if (isAgain == 1) 218 { 219 system("cls"); 220 main(); 221 } 222 }
运行结果