☰
BFS迷宫算法:像水一样漫出最短路
2026/10/17 1:42:55 网站建设 项目流程

一句话:从起点出发,一圈一圈往外走,每圈多走一步。第一次碰到终点时,走的就是最短的路。

这个方法叫BFS(广度优先搜索),是走迷宫最常用、最好懂的方法。


一、生活里的例子:往地上倒一杯水

在起点倒一杯水:

  • 第 1 秒,水流到起点旁边的格子
  • 第 2 秒,再往外流一格
  • 墙挡住的地方,水过不去

水最先流到终点的那条路,就是最短路。BFS 就是在模仿这个过程。


二、准备一个小迷宫

S . # . . . . # . # # . . . . . # # # . . . . # E
  • S起点,E终点
  • .能走,#是墙
  • 每次只能上下左右走一格

三、手动"倒水":看每个格子要走几步

从 S 开始,把"走到这里要几步"写进格子:

0 1 # 7 8 1 2 # 6 # # 3 4 5 6 - # # # 7 - - - # 8
  • 0是起点,旁边的格子是1,再旁边是2……
  • -表示水流不到(被墙围住了)
  • 终点 E 是 8 → 最短要走 8 步

怎么找出路线?从终点倒着走:8 → 7 → 6 → … → 0,每次走到比自己小 1 的格子。


四、程序需要三样东西

东西作用比喻
队列 Queue存放"接下来要去看的格子"排队,先来的先处理
visited 数组记录哪些格子来过了在地上做记号,不走回头路
from 数组记录"我是从哪个格子走过来的"留面包屑,最后用来找回路线

五、完整代码(可以直接运行)

新建一个 C# 控制台项目,把下面的代码全部粘进去:

usingSystem;usingSystem.Collections.Generic;classProgram{staticvoidMain(){string[]maze={"S.#..","..#.#","#....",".###.","...#E",};List<(intr,intc)>path=FindPath(maze);if(path==null){Console.WriteLine("走不通!");return;}Console.WriteLine($"最短要走{path.Count-1}步:");// 把路线用 * 画出来char[][]map=newchar[maze.Length][];for(inti=0;i<maze.Length;i++)map[i]=maze[i].ToCharArray();foreach(var(r,c)inpath)if(map[r][c]=='.')map[r][c]='*';foreach(varrowinmap)Console.WriteLine(newstring(row));}staticList<(intr,intc)>FindPath(string[]maze){introws=maze.Length;intcols=maze[0].Length;// 1. 找到起点和终点(intr,intc)start=(0,0),end=(0,0);for(intr=0;r<rows;r++)for(intc=0;c<cols;c++){if(maze[r][c]=='S')start=(r,c);if(maze[r][c]=='E')end=(r,c);}// 上、下、左、右 四个方向int[]dr={-1,1,0,0};int[]dc={0,0,-1,1};varqueue=newQueue<(intr,intc)>();varvisited=newbool[rows,cols];varfrom=new(intr,intc)[rows,cols];// 2. 起点先入队,做记号queue.Enqueue(start);visited[start.r,start.c]=true;// 3. 不断从队列里拿格子出来,往四周扩散while(queue.Count>0){varcur=queue.Dequeue();if(cur==end)returnBuildPath(from,start,end);// 到终点了for(inti=0;i<4;i++){intnr=cur.r+dr[i];intnc=cur.c+dc[i];if(nr<0||nr>=rows||nc<0||nc>=cols)continue;// 出界if(maze[nr][nc]=='#')continue;// 是墙if(visited[nr,nc])continue;// 来过了visited[nr,nc]=true;// 做记号from[nr,nc]=cur;// 记住从哪来queue.Enqueue((nr,nc));// 排队,等会儿再从它往外走}}returnnull;// 队列空了还没到终点 → 走不通}// 4. 从终点沿着 from 倒着走回起点staticList<(intr,intc)>BuildPath((intr,intc)[,]from,(intr,intc)start,(intr,intc)end){varpath=newList<(intr,intc)>();varcur=end;while(cur!=start){path.Add(cur);cur=from[cur.r,cur.c];}path.Add(start);path.Reverse();// 倒过来,变成 起点 → 终点returnpath;}}

运行结果

最短要走 8 步: S.#.. **#.# #**** .###* ...#E

*就是找到的路线。


六、代码其实就四步

  1. 找起点终点
  2. 起点入队,做记号
  3. 循环:拿出一个格子 → 看上下左右 → 能走、没来过的就做记号、记来路、入队
  4. 到终点后,沿着from倒着走回去,得到路线

七、其他走迷宫的方法

方法怎么走特点
BFS(本篇)一圈一圈往外漫✅ 一定找到最短路,好懂
DFS一条路走到黑,撞墙再回头能找到路,但不一定最短
A*BFS + “优先朝终点方向走”更快,游戏里的寻路基本都用它

A* 就是 BFS 的升级版。先把 BFS 弄懂,A* 只需要多加一点点东西。


八、常见的坑

坑现象原因
程序卡死 / 内存爆掉一直跑不停忘了visited,在两个格子之间来回走
报错数组越界IndexOutOfRangeException忘了检查出界
路线方向反了从终点画到起点忘了path.Reverse()
和 Unity 坐标对不上角色往反方向走数组的行 r 是往下数的,而 Unity 的y 是往上的(上一篇讲的坐标系问题)

一句话总结

BFS 走迷宫 = 从起点像水一样一圈圈往外漫,做记号不走回头路,记住每格是从哪来的。第一次到终点就是最短路,再顺着记录倒着走回去,就得到路线。


需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询