欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

C语言实现一个走迷宫小游戏(深度优先算法)

最编程 2024-08-14 18:02:43
...
1 #include<stdio.h> 2 #include<windows.h> 3 #include<conio.h> 4 #include<time.h> 5 #include<math.h> 6 7 //地图边长L,包括迷宫主体20,外侧的包围的墙体2,最外侧包围路径2(之后会解释) 8 //可根据需要修改,有上限 9 #define L 24 10 11 #define WALL 0 // 12 #define ROUTE 1 //路径 13 #define PLAYER 2//玩家 14 15 //控制迷宫的复杂度,数值越大复杂度越低,最小值为0 16 //默认为简单难度,可根据需要在degree函数里调整不同难度的复杂度 17 int Rank = 6; 18 19 void menu(); //主菜单界面 20 void start(); //开始游戏 21 void degree(); //游戏难度 22 void explain();//游戏说明 23 int init(int** Maze); //初始化迷宫 24 void print(int** Maze);//画迷宫 25 void CreateMaze(int **maze, int x, int y); //创建迷宫 26 void move(int** Maze, char t, int *x, int *y);//移动角色 27 28 int main() { 29 menu(); 30 return 0; 31 } 32 33 void menu() { //主菜单 34 while(1) { 35 system("cls"); //清屏 36 char t; 37 printf("*******(走迷宫)*******"); 38 printf("\n======================\n"); 39 printf("\n|| 1. 开始 游戏 ||\n"); 40 printf("\n|| 2. 游戏 说明 ||\n"); 41 printf("\n|| 3. 游戏 难度 ||\n"); 42 printf("\n|| 4. 关闭 游戏 ||\n"); 43 printf("======================\n"); 44 t=getch(); //不回显函数 45 switch(t) { 46 case '1': 47 start(); 48 break; //开始一局游戏 49 case '2': 50 explain(); 51 break; //进入游戏说明界面 52 case '3': 53 degree(); 54 break; //调整游戏难度 55 case '4': 56 printf("\n欢迎下次再玩,再见( ̄︶ ̄)↗"); 57 Sleep(1500); 58 exit(0); 59 break; //结束程序 60 default : 61 break; 62 } 63 } 64 } 65 66 void CreateMaze(int **maze, int x, int y) {//构建迷宫 67 maze[x][y] = ROUTE; 68 //确保四个方向随机,而不再是固定的上下左右这种排列 69 int direction[4][2] = { { 1,0 },{ -1,0 },{ 0,-1 },{ 0,1 } }; 70 int i, j; 71 for (i = 0; i < 4; i++) { 72 int r = rand() % 4; 73 int temp = direction[0][0]; 74 direction[0][0] = direction[r][0]; 75 direction[r][0] = temp; 76 temp = direction[0][1]; 77 direction[0][1] = direction[r][1]; 78 direction[r][1] = temp; 79 } 80 //向四个方向开挖 81 for (i = 0; i < 4; i++) { 82 int dx = x; 83 int dy = y; 84 //控制挖的距离,由Rank来调整大小 85 int range = 1 + (Rank == 0 ? 0 : rand() % Rank); 86 while (range > 0) { 87 //计算出将要访问到的坐标 88 dx += direction[i][0]; 89 dy += direction[i][1]; 90 //排除掉回头路 91 if (maze[dx][dy] == ROUTE) { 92 break; 93 } 94 //判断是否挖穿路径 95 int count = 0, k; 96 for (j = dx - 1; j < dx + 2; j++) { 97 for (k = dy - 1; k < dy + 2; k++) { 98 //abs(j - dx) + abs(k - dy) == 1 确保只判断九宫格的四个特定位置 99 if (abs(j - dx) + abs(k - dy) == 1 && maze[j][k] == ROUTE) { 100 count++; 101 } 102 } 103 } 104 //count大于1表明墙体会被挖穿,停止 105 if (count > 1) 106 break; 107 //确保不会挖穿时,前进 108 range -= 1; 109 maze[dx][dy] = ROUTE; 110 } 111 //没有挖穿危险,以此为节点递归 112 if (range <= 0) { 113 CreateMaze(maze, dx, dy); 114 } 115 } 116 } 117 118 int init(int** Maze) {//初始化迷宫 119 int i; 120 //最外围层设为路径的原因,为了防止挖路时挖出边界,同时为了保护迷宫主体外的一圈墙体被挖穿 121 for (i = 0; i < L; i++) { 122 Maze[i][0] = ROUTE; 123 Maze[0][i] = ROUTE; 124 Maze[i][L - 1] = ROUTE; 125 Maze[L - 1][i] = ROUTE; 126 } 127 //创造迷宫,(2,2)为起点 128 CreateMaze(Maze, 2, 2); 129 //画迷宫的入口和出口,给出玩家初始位置 130 Maze[2][1] = PLAYER; 131 //由于算法随机性,出口有一定概率不在(L-3,L-2)处,此时需要寻找出口 132 for (i = L - 3; i >= 0; i--) { 133 if (Maze[i][L - 3] == ROUTE) { 134 Maze[i][L - 2] = ROUTE; 135 //返回出口所在的纵坐标 136 return i; 137 } 138 } 139 } 140 141 void print(int** Maze) {//画迷宫 142 int i, j; 143 for (i = 0; i < L; i++) { 144 for (j = 0; j < L; j++) { 145 if (Maze[i][j] == ROUTE) 146 printf(" ");//表示道路 147 else if(Maze[i][j] == WALL) 148 printf("");//表示墙体 149 else 150 printf("");//表示玩家 151 } 152 printf("\n"); 153 } 154 } 155 //将原先的引用int &x,更改为现在的指针指向int *x 156 void move(int** Maze, char t, int *x, int *y) {//移动角色 157 int i = *x, j = *y;//记录原始位置 158 switch(t) { 159 case 'w': //向上移动 160 *x -= 1; 161 break; 162 case 's': //向下移动 163 *x += 1; 164 break; 165 case 'a': //向左移动 166 *y -= 1; 167 break; 168 case 'd': //向右移动 169 *y += 1; 170 break; 171 default: 172 break; 173 } 174 if(*x>=0 && *x<L-1 && *y>=0 && *y<L-1 && Maze[*x][*y]!=WALL) {//符合条件,移动 175 Maze[i][j] = 1; 176 Maze[*x][*y] = 2; 177 } else {//保持位置不变 178 *x = i; 179 *y = j; 180 } 181 } 182 183 void start() { //开始一局游戏 184 char t; 185 //y,x表示角色横纵坐标, out表示出口的纵坐标 186 int *p, *q; 187 int x = 2, y = 1, out = 0, i = 0; 188 p = &x; 189 q = &y; 190 //随机数发生器初始化函数 191 srand((unsigned)time(NULL)); 192 //申请数组空间 193 int **Maze = (int**)malloc(L * sizeof(int *)); 194 for (i = 0; i < L; i++) { 195 Maze[i] = (int*)calloc(L, sizeof(int)); 196 } 197 //得到出口纵坐标 198 out = init(Maze); 199 //游戏开始 200 system("cls"); 201 print(Maze); 202 while(t = getch()) { 203 if(t == 27) //如果输入为ESC键,结束游戏回到主菜单 204 break; 205 system("cls");//清屏 206 move(Maze, t, p, q);//根据输入t进行移动 207 print(Maze);//重新绘制迷宫 208 if(x == out && y == L-2) {//已经到出口,游戏结束 209 system("cls"); 210 printf("=============\n"); 211 printf("游 戏 胜 利!\n"); 212 printf("=============\n"); 213 printf("即将后返回主菜单……"); 214 Sleep(1500);//执行挂起一段时间,暂停1.5秒后打印 215 break; 216 } 217 } 218 //一局游戏结束,释放内存 219 for (i = 0; i < L; i++) free(Maze[i]); 220 free(Maze); 221 } 222 223 void explain() { //操作说明 224 while(1) { 225 char t; 226 system("cls"); 227 printf("=================================================\n"); 228 printf("感谢您体验本游戏,游戏的操作如下:\n"); 229 printf("\n1.将输入法调整为英文(小写)\n"); 230 printf("\n2.通过w,s,a,d四个键控制角色上下左右移动\n"); 231 printf("\n3.在任意界面均可按“ESC”键返回到主菜单\n"); 232 printf("\n胜利条件:移动角色到出口处,加油各位( ̄▽ ̄)\"!\n"); 233 printf("=================================================\n"); 234 t=getch(); //不回显函数 235 switch(t) { 236 //ESC键的ASCII码值 237 case 27: 238 //返回主菜单 239 menu(); 240 break; 241 default : 242 break; 243 } 244 } 245 } 246 247 void degree() { //调整游戏难度 248 while(1) { 249 char t; 250 system("cls"); 251 printf("=======================\n"); 252 printf("输入1,2,3进行难度调整:\n"); 253 printf("\n|| 1.简 单 ||\n"); 254 printf("\n|| 2.中 等 ||\n"); 255 printf("\n|| 3.困 难 ||\n"); 256 printf("=======================\n"); 257 t=getch(); //不回显函数 258 switch(t) { 259 case '1': 260 Rank = 6; 261 printf("\n当前难度:简单,即将返回主菜单……"); 262 Sleep(1500); 263 menu();//返回主菜单 264 break; 265 case '2': 266 Rank = 3; 267 printf("\n当前难度:中等,即将返回主菜单……"); 268 Sleep(1500); 269 menu();//返回主菜单 270 break; 271 case '3': 272 Rank = 0; 273 printf("\n当前难度:困难,即将返回主菜单……"); 274 Sleep(1500); 275 menu();//返回主菜单 276 break; 277 case 27: 278 menu(); 279 break; 280 default : 281 break; 282 } 283 } 284 }