当前位置:   article > 正文

广度优先搜索(BFS)寻找迷宫两点之间最短路径的C语言实现_迷宫最短路径算法c语言

迷宫最短路径算法c语言

一、问题描述

根据输入的长和宽随机生成一个迷宫,随机生成或者输入一个起点和一个终点,运用广度优先搜索算法,找到这个迷宫中起点到终点的最短路径,并输出结果。

二、思路与算法

1.根据给定的迷宫长和宽创建一个动态数组,初始化数组并随机生成一个迷宫,再随机生成或者输入一个起点和一个终点。

2.设置一个结构体Node,其中包括点的坐标,以及五个指针:front(用于后期回溯得出的最短路径)、left、right、up、down。将起点和终点存入Node,从起点开始分别遍历其上下左右四个坐标是否有“墙”,若没有,向所查询的方向前进一步,新建一个Node,存入该点。

3.另设置一个结构体Queue,每前进一步,将新的点的指针存入Queue组成的链表,从头到尾遍历这个链表,链表中每个指针所指向的点都会重复步骤2。

4.重复2、3步骤,遍历整个树,以此实现广度搜索算法,直至找到终点。

5.如果找到了终点,则从已存好的终点Node开始,通过指针front一步步还原这个路径,直至走到起点,然后输出这个过程得到最终的最短路径。如果没有找到,则输出“No path.”。

三、C语言实现

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <malloc.h>
  5. #include <Windows.h>
  6. typedef struct Point
  7. {
  8. int arrrow;
  9. int arrcol;
  10. }Point;
  11. typedef struct Node
  12. {
  13. Point point;
  14. struct Node* front;
  15. struct Node* left;
  16. struct Node* right;
  17. struct Node* up;
  18. struct Node* down;
  19. }Node;
  20. typedef struct Queue
  21. {
  22. struct Node* node;
  23. struct Queue* next;
  24. };
  25. struct Node* CreateNode(int row, int col)//长长的链表捏
  26. {
  27. struct Node* node = (struct Node*)malloc(sizeof(struct Node));
  28. node->point.arrrow = row;
  29. node->point.arrcol = col;
  30. node->front = NULL;
  31. node->left = NULL;
  32. node->right = NULL;
  33. node->up = NULL;
  34. node->down = NULL;
  35. return node;
  36. }
  37. struct Queue* CreateQueue(struct Node* addnode)//动态队列记录每层搜索
  38. {
  39. struct Queue* queue = (struct Queue*)malloc(sizeof(struct Queue));
  40. queue->node = addnode;
  41. queue->next = NULL;
  42. return queue;
  43. }
  44. //设置颜色的捏
  45. VOID SetColor(UINT uFore, UINT uBack)
  46. {
  47. HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
  48. SetConsoleTextAttribute(handle, uFore + uBack * 0x10);
  49. }
  50. //测试,打印全部迷宫
  51. void TextPrint(char** maze, int mazerow, int mazecol)
  52. {
  53. for (int i = 0; i < mazerow; i++)
  54. {
  55. for (int j = 0; j < mazecol; j++)
  56. {
  57. printf("%c", maze[i][j]);
  58. }
  59. printf("\n");
  60. }
  61. printf("\n");
  62. }
  63. //打印整个迷宫捏
  64. void PrintMaze(char** maze, int mazerow, int mazecol)
  65. {
  66. for (int i = 0; i < mazerow; i++)
  67. {
  68. for (int j = 0; j < mazecol; j++)
  69. {
  70. if (maze[i][j] == '=')
  71. printf(" ");
  72. else if (maze[i][j] == '1')
  73. printf(" ");
  74. else if (maze[i][j] == '0')
  75. printf(" ");
  76. else if (maze[i][j] == '-')
  77. printf("---");
  78. else if (maze[i][j] == ' ')
  79. printf(" ");
  80. else if (maze[i][j] == '!')
  81. {
  82. SetColor(4, 0);
  83. printf(" ! ");
  84. SetColor(7, 0);
  85. }
  86. else if (maze[i][j] == '<' || maze[i][j] == '>')
  87. {
  88. SetColor(4, 0);
  89. printf("%c", maze[i][j]);
  90. SetColor(7, 0);
  91. }
  92. else if (maze[i][j] == '*')
  93. {
  94. SetColor(4, 0);
  95. printf(" * ");
  96. SetColor(7, 0);
  97. }
  98. else
  99. printf("%c", maze[i][j]);
  100. }
  101. printf("\n");
  102. }
  103. printf("\n");
  104. }
  105. //初始化迷宫
  106. void InitMaze(char **maze, int mazerow, int mazecol)
  107. {
  108. //初始
  109. for (int i = 0; i < mazerow; i++)
  110. {
  111. for (int j = 0; j < mazecol; j++)
  112. {
  113. maze[i][j] = ' ';
  114. }
  115. }
  116. //拐角
  117. for (int i = 0; i < mazerow; i += 2)
  118. {
  119. for (int j = 0; j < mazecol; j += 2)
  120. {
  121. maze[i][j] = '+';
  122. }
  123. }
  124. //左右墙壁
  125. for (int i = 1; i < mazerow; i += 2)
  126. {
  127. maze[i][0] = '|';
  128. maze[i][mazecol - 1] = '|';
  129. }
  130. //上下墙壁
  131. for (int i = 1; i < mazecol; i += 2)
  132. {
  133. maze[0][i] = '-';
  134. maze[mazerow - 1][i] = '-';
  135. }
  136. }
  137. //随机生成迷宫
  138. void CreateMaze(char **maze, int mazerow, int mazecol, int wallweight)
  139. {
  140. srand((unsigned)time(NULL));
  141. for (int i = 1; i < mazerow; i += 2)
  142. {
  143. for (int j = 2; j < mazecol - 2; j += 2)
  144. {
  145. int randnum = rand() % 10 + 1;
  146. if (randnum <= wallweight)
  147. {
  148. maze[i][j] = '|';
  149. }
  150. else
  151. maze[i][j] = '=';//原本所有通路都是1,为了打印时的美观性,将上下与左右区分
  152. }
  153. }
  154. for (int i = 1; i < mazecol; i += 2)
  155. {
  156. for (int j = 2; j < mazerow - 2; j += 2)
  157. {
  158. int randnum = rand() % 10 + 1;
  159. if (randnum <= wallweight)
  160. {
  161. maze[j][i] = '-';
  162. }
  163. else
  164. maze[j][i] = '1';
  165. }
  166. }
  167. PrintMaze(maze, mazerow, mazecol);
  168. }
  169. //设置起点和终点
  170. Point StartAndEnd(char** maze, int row, int col)
  171. {
  172. /*srand((unsigned)time(NULL)); */
  173. Point point;
  174. int randomrow = rand() % row + 1;
  175. int randomcol = rand() % col + 1;
  176. printf("[%d, %d]\n", randomrow, randomcol);
  177. point.arrrow = randomrow * 2 - 1;
  178. point.arrcol = randomcol * 2 - 1;
  179. return point;
  180. }
  181. //广度优先算法
  182. int BFS(char** maze, Point start, Point end, int mazerow, int mazecol)
  183. {
  184. int row = start.arrrow;
  185. int col = start.arrcol;
  186. struct Node* startnode = CreateNode(row, col);//startnode不能动
  187. row = end.arrrow;
  188. col = end.arrcol;
  189. struct Node* endnode = CreateNode(row, col);
  190. struct Node* tmpnode = startnode;
  191. struct Queue* headqueue = CreateQueue(startnode);
  192. struct Queue* head = headqueue;//便于释放内存
  193. struct Queue* tmpqueue = headqueue;
  194. int flag = 0;
  195. //广度搜索遍历
  196. while (1)
  197. {
  198. row = headqueue->node->point.arrrow;
  199. col = headqueue->node->point.arrcol;
  200. tmpnode = headqueue->node;
  201. maze[row][col] = '0';
  202. if (maze[row][col - 1] == '=' && maze[row][col - 2] != '0')
  203. {
  204. struct Node* node = CreateNode(row, col - 2);
  205. node->front = tmpnode;
  206. tmpnode->left = node;
  207. maze[row][col - 2] = '0';
  208. if (row == end.arrrow && col - 2 == end.arrcol)
  209. {
  210. flag = 1;
  211. endnode = node;
  212. printf("found\n");
  213. break;
  214. }
  215. struct Queue* queue = CreateQueue(node);
  216. tmpqueue->next = queue;
  217. tmpqueue = queue;
  218. }
  219. if (maze[row][col + 1] == '=' && maze[row][col + 2] != '0')
  220. {
  221. struct Node* node = CreateNode(row, col + 2);
  222. node->front = tmpnode;
  223. tmpnode->right= node;
  224. maze[row][col + 2] = '0';
  225. if (row == end.arrrow && col + 2 == end.arrcol)
  226. {
  227. flag = 1;
  228. endnode = node;
  229. printf("found\n");
  230. break;
  231. }
  232. struct Queue* queue = CreateQueue(node);
  233. tmpqueue->next = queue;
  234. tmpqueue = queue;
  235. }
  236. if (maze[row - 1][col] == '1' && maze[row - 2][col] != '0')
  237. {
  238. struct Node* node = CreateNode(row - 2, col);
  239. node->front = tmpnode;
  240. tmpnode->up = node;
  241. maze[row - 2][col] = '0';
  242. if (row - 2 == end.arrrow && col == end.arrcol)
  243. {
  244. flag = 1;
  245. endnode = node;
  246. printf("found\n");
  247. break;
  248. }
  249. struct Queue* queue = CreateQueue(node);
  250. tmpqueue->next = queue;
  251. tmpqueue = queue;
  252. }
  253. if (maze[row + 1][col] == '1' && maze[row + 2][col] != '0')
  254. {
  255. struct Node* node = CreateNode(row + 2, col);
  256. node->front = tmpnode;
  257. tmpnode->down = node;
  258. maze[row + 2][col] = '0';
  259. if (row + 2 == end.arrrow && col == end.arrcol)
  260. {
  261. flag = 1;
  262. endnode = node;
  263. printf("found\n");
  264. break;
  265. }
  266. struct Queue* queue = CreateQueue(node);
  267. tmpqueue->next = queue;
  268. tmpqueue = queue;
  269. }
  270. if (headqueue->next == NULL)
  271. {
  272. flag = 0;
  273. printf("No path...\n");
  274. break;
  275. }
  276. headqueue = headqueue->next;
  277. }
  278. //如果找到,回溯路线
  279. if (flag)
  280. {
  281. //测试
  282. TextPrint(maze, mazerow, mazecol);
  283. flag = 0;
  284. tmpnode = endnode;
  285. while (1)
  286. {
  287. row = tmpnode->point.arrrow;
  288. col = tmpnode->point.arrcol;
  289. maze[row][col] = '*';
  290. tmpnode = tmpnode->front;
  291. if (tmpnode == NULL)
  292. break;
  293. if (tmpnode->left == endnode)
  294. {
  295. maze[row][col + 1] = '<';
  296. }
  297. else if (tmpnode->right == endnode)
  298. {
  299. maze[row][col - 1] = '>';
  300. }
  301. else if (tmpnode->up == endnode)
  302. {
  303. maze[row + 1][col] = '!';
  304. }
  305. else if (tmpnode->down == endnode)
  306. {
  307. maze[row - 1][col] = '!';
  308. }
  309. endnode = endnode->front;
  310. flag++;
  311. }
  312. }
  313. tmpqueue = head;
  314. while (tmpqueue != NULL)
  315. {
  316. tmpqueue = tmpqueue->next;
  317. free(head->node);
  318. free(head);
  319. head = tmpqueue;
  320. }
  321. return flag;
  322. }
  323. int main()
  324. {
  325. //输入行和列
  326. int row = 0, col = 0;
  327. printf("please input row(行)and col(列):\n");
  328. scanf("%d %d", &row, &col);
  329. if (!(row > 0 && col > 0))
  330. {
  331. printf("input ERROR\n");
  332. return 1;
  333. }
  334. int wallweight = 0;
  335. printf("please input the weight of wall(1 ~ 10, less than 4 best):\n");
  336. scanf("%d", &wallweight);
  337. if (!(wallweight > 0 && wallweight <= 10))
  338. {
  339. printf("input ERROR\n");
  340. return 1;
  341. }
  342. //创建一个动态数组
  343. int mazerow = row * 2 + 1;
  344. int mazecol = col * 2 + 1;
  345. char **maze = (char**)calloc(mazerow, sizeof(char*));
  346. if (maze == NULL)
  347. {
  348. printf("malloc ERROR\n");
  349. return 1;
  350. }
  351. for (int i = 0; i < mazerow; i++)
  352. {
  353. maze[i] = (char*)calloc(mazecol, sizeof(char));
  354. if (maze[i] == NULL)
  355. {
  356. printf("malloc ERROR\n");
  357. return 1;
  358. }
  359. }
  360. //初始化迷宫
  361. InitMaze(maze, mazerow, mazecol);
  362. //随机生成迷宫
  363. int x = 0;
  364. do
  365. {
  366. CreateMaze(maze, mazerow, mazecol, wallweight);
  367. printf("Reset the maze? Yes(1)/No(0)\n");
  368. scanf("%d", &x);
  369. } while (x);
  370. //设置起点和终点
  371. int choice = 0;
  372. Point start;
  373. Point end;
  374. printf("Random point(1) OR Input point(0)\n");
  375. scanf("%d", &choice);
  376. if (choice == 1)
  377. {
  378. start = StartAndEnd(maze, (int)(row / 2), (int)(col / 2));
  379. end = StartAndEnd(maze, row, col);
  380. }
  381. else if (choice == 0)
  382. {
  383. int row = 0;
  384. int col = 0;
  385. printf("Please input startpoint row col\n");
  386. scanf("%d %d", &row, &col);
  387. start.arrrow = row * 2 - 1;
  388. start.arrcol = col * 2 - 1;
  389. printf("Please input endpoint row col\n");
  390. scanf("%d %d", &row, &col);
  391. end.arrrow = row * 2 - 1;
  392. end.arrcol = col * 2 - 1;
  393. }
  394. else
  395. {
  396. printf("Input ERROR\n");
  397. return -1;
  398. }
  399. //广度优先算法
  400. int flag = BFS(maze, start, end, mazerow, mazecol);
  401. //输出结果
  402. if (flag)
  403. {
  404. PrintMaze(maze, mazerow, mazecol);
  405. printf("step = %d\n", flag);
  406. }
  407. //释放内存
  408. for (int i = 0; i < mazerow; i++)
  409. {
  410. free(maze[i]);
  411. }
  412. free(maze);
  413. return 0;
  414. }

四、实例运行结果

C语言课老师留的小作业,孩子记录一下。

迷宫我一开始是想做成完全没有死胡同的迷宫,任意两个点之间都有且仅有一条通路,即迷宫的通路构成一个树,但是没有想到怎么实现,就只好随机生成了,希望能有大佬提提意见。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/445363
推荐阅读
相关标签
  

闽ICP备14008679号