ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

老鼠走迷宫游戏升级版课设:C语言数据结构与迷宫算法解析

老鼠走迷宫游戏升级版课设:C语言数据结构与迷宫算法解析 简介这是面向C语言与数据结构课程设计的迷宫游戏升级版实现适合需要完成类似题目或练习图遍历、路径搜索算法的在校学生。程序以控制台呈现迷宫地图支持方向键操控老鼠走向粮仓并包含定时成功/失败判定、迷宫编辑墙变路、路变墙以及全路径和最短路径求解功能覆盖需求分析到编码实现的常见环节。压缩包共5个文件约50KB1个cpp为完整C源代码1个exe为可执行程序3个txt为迷宫数据文件分别对应不同地图布局可替换使用以测试算法效果。算法上涉及图的遍历、回溯、广度/深度优先搜索等经典知识点代码注释清晰可帮助理解迷宫建模、路径存储与最短路径计算思路同时提供可直接运行的exe便于先体验再读源码适合课程设计答辩前快速梳理方案。已有3889人学习资源量不大但麻雀虽小五脏俱全拿来当作课程设计参考或在此基础上扩展界面、增加难度都很有价值。1. 老鼠走迷宫游戏升级版到底在考什么从“能跑通”到“敢答辩”期末课设答辩现场你刚把老鼠走出迷宫的截图放出来老师随手一指地图右下角“你这只老鼠从头到尾绕了个大弯我用眼睛都能看出最短路径不是这个。你写的是深度优先它凭什么叫‘优先’”这个标题里的【老鼠走迷宫游戏升级版课程设计c语言数据结构源代码迷宫文件】说的就是应付这类追问的项目老鼠走迷宫是数据结构课设里出现频率最高的一题升级版通常意味着不只有单条路径还要支持随机生成迷宫、求解并展示路径。它把栈、队列、图遍历、文件读写全串进一个程序适合正在赶课设、或者想把项目从“能运行”打磨到“能解释”的人。这篇我按自己做课设和帮别人改代码的顺序从迷宫文件格式讲到寻路算法再落到避坑全文基于 C 语言实现。2. 迷宫从哪来手工地图、随机生成与迷宫文件格式设计很多人的第一版迷宫是直接在代码里写死一个二维数组8×8 跑通就交差。但老师一眼就能看出来地图写死在代码里换不了图也谈不上“游戏”。升级版的第一个升级点就是把迷宫“数据化”——地图放在文件里程序只负责读。这样换题、换难度、答辩演示都方便。2.1 先定迷宫文件格式0 和 1 之外的三个细节我一般用的格式很简单第一行两个整数表示行数和列数后面每行是若干个 0 或 10 代表可以通过的路1 代表墙。这个格式的好处是能用记事本直接画图也能用脚本批量生成。下面是完整的读取函数建议直接放进maze_io.c#include stdio.h #include stdlib.h #define MAX_ROW 64 #define MAX_COL 64 // 从文件读取迷宫成功返回 1失败返回 0 int loadMaze(const char *filename, int maze[MAX_ROW][MAX_COL], int *row, int *col) { FILE *fp fopen(filename, r); if (fp NULL) { printf(打不开 %s\n, filename); return 0; } // 先读行数和列数 if (fscanf(fp, %d %d, row, col) ! 2) { fclose(fp); return 0; } if (*row MAX_ROW || *col MAX_COL) { printf(迷宫尺寸超过 %d x %d\n, MAX_ROW, MAX_COL); fclose(fp); return 0; } // 逐个数读 0/1跳过空白符 for (int i 0; i *row; i) { for (int j 0; j *col; j) { if (fscanf(fp, %d, maze[i][j]) ! 1) { fclose(fp); return 0; } } } fclose(fp); return 1; }逻辑上和文件格式一一对应先读两个尺寸再按行读迷宫矩阵任何一个数字读不到就直接返回 0避免程序带着残缺数据往下跑。参数MAX_ROW和MAX_COL要和后面生成、求解用的数组声明保持一致我习惯统一写在头文件里迷宫最大能开多大取决于你栈上数组怎么声明64×64 是课设够用的起点超过 128×128 建议改成动态数组。这里有个容易被忽略的细节文件里 0 和 1 之间用什么分隔其实无所谓因为fscanf遇到空格、换行、制表符都会自动跳过。我之前见过同学用fgets逐行读再手动处理结果每次换行符都多吞一个字符地图整体错位。另一个细节是行列数最好用int变量带回来而不是全局变量这样同一个函数可以加载多张地图做对比。第三个细节是文件结尾不要有多余的空白行有些编辑器会自动补一个空行虽然fscanf能跳过但手工检查文件时会干扰判断所以建议统一在格式说明里写清楚“末尾不留空行”。2.2 用 DFS 回溯随机生成迷宫挖墙法的原理与参数手工编辑文件适合做“演示地图”但课设老师更想看到“程序自己生成地图”。常见生成算法是递归回溯挖墙法原理一句话把迷宫当成一块块方格初始全部是墙从起点格子出发每隔一个格子打通一条通道随机挑方向往前走走到没路就退回上一个格子继续试。这样生成的迷宫天然满足“任意两个空地之间只有一条通路”的特性正好和后面求解用的栈结构形成对照。我一般用奇数尺寸的二维数组比如 41 行 41 列外围保留一圈墙然后从 (1,1) 开始挖。核心代码如下#include time.h #include stdlib.h // 跳两格的方向偏移上、右、下、左 int dig_dx[4] {-2, 0, 2, 0}; int dig_dy[4] {0, 2, 0, -2}; // 洗牌让每次生成的迷宫不一样 void shuffle(int *arr, int n) { for (int i n - 1; i 0; i--) { int j rand() % (i 1); int tmp arr[i]; arr[i] arr[j]; arr[j] tmp; } } // 从 (x, y) 开始递归挖墙调用前先把 maze 全部置 1 void dfsGenerate(int maze[MAX_ROW][MAX_COL], int x, int y) { maze[x][y] 0; // 挖开当前格子 int order[4] {0, 1, 2, 3}; shuffle(order, 4); // 随机方向顺序 for (int i 0; i 4; i) { int nx x dig_dx[order[i]]; int ny y dig_dy[order[i]]; // 隔一个格子判断防止打出边界 if (nx 0 nx MAX_ROW - 1 ny 0 ny MAX_COL - 1 maze[nx][ny] 1) { // 把中间的墙也挖开 maze[x dig_dx[order[i]] / 2][y dig_dy[order[i]] / 2] 0; dfsGenerate(maze, nx, ny); } } }这段代码的关键是dig_dx和dig_dy每次跳两格而不是一格跳的那一格是要被挖开的墙跳两格后才到达下一个格子。为什么不能每次走一格因为按格子逐个挖生成的会是一团乱麻几乎没有墙也没有迷惑性。调用前需要先srand(time(NULL))初始化随机种子否则每次生成的地图都一样答辩时会被当成“假随机”。参数上MAX_ROW和MAX_COL必须是奇数因为起点是 (1,1)跳两格后仍然是奇数坐标能保证通道格子都在奇数行奇数列如果你传了偶数尺寸最后会剩下几排墙没法处理。递归生成法最怕的是层数太深。迷宫越大递归调用栈越深Windows 默认 1MB 栈空间下超过一千层就有概率爆栈。这也是一个适合写进课设报告的点递归版本简洁但显式栈版本能承受更大的迷宫。如果你想在代码层面解决可以把递归改成手动栈或者限制迷宫尺寸在 127×127 以内基本安全。2.3 对比 PRIM 生成法选型看特征别跟风除了 DFS 挖墙另一个常见生成法是 PRIM 算法。它维护一个“墙列表”随机挑一堵墙判断墙两边的格子是否一个已打通、一个未打通满足条件就把这堵墙挖开。PRIM 生成出来的迷宫分叉多、支路均匀不会出现 DFS 那种一条长走廊走到黑的情况。但是实现上要额外维护墙的集合代码量比递归挖墙大一圈。如果你只想要“能生成迷宫”我建议选 DFS 挖墙代码短、好讲如果你追求“迷宫好看”可以在课设报告里写清楚两种算法的差异然后用 PRIM 做加分项。整理一张对比表生成算法特征代码量适用场景DFS 递归挖墙路径偏长、分支较少小课设够用重点讲回溯PRIM 挖墙分支均匀、路线多样中想加分的同学纯随机布墙可能无解极小不建议作为主方案纯随机布墙就是每个格子按概率置 0/1这种做法经常出现整块死区老鼠根本走不到出口还得额外做连通性检查不如直接用上面两种有理论保证的算法。2.4 把迷宫写回文件存档与读档的最小实现生成完迷宫不能只存在内存里否则程序一关图就没了。写回文件和读文件是对称的核心是fprintf按同样的格式输出// 把迷宫保存到文件成功返回 1 int saveMaze(const char *filename, int maze[MAX_ROW][MAX_COL], int row, int col) { FILE *fp fopen(filename, w); if (fp NULL) return 0; fprintf(fp, %d %d\n, row, col); // 先写尺寸 for (int i 0; i row; i) { for (int j 0; j col; j) { fprintf(fp, %d , maze[i][j]); // 0/1 后面跟空格 } fprintf(fp, \n); } fclose(fp); return 1; }逻辑上先写行列数再写矩阵和loadMaze正好互逆。这里有个课设实操建议随机生成一张 61×61 的迷宫直接saveMaze(maps/demo.txt, maze, row, col)保存然后在主程序里用loadMaze重新加载既演示了生成又演示了文件读写比口头说“我支持文件加载”更有说服力。文件命名建议统一放到maps/目录避免和源码混在一起答辩时也更好找。3. 寻路核心栈、递归与 BFS 最短路径的落地写法迷宫生成完真正的重头戏是求解。数据结构课设里老师最关注的就是你能不能把栈和队列这两个“线性结构”用到具体问题上。老鼠走迷宫最经典的解法是深度优先搜索它天然对应栈升级版要求的最短路径则对应队列。这一章把两条路线都写清楚。3.1 递归和栈到底什么关系老师追问的底层问题先回答一个答辩高频问题递归是不是栈递归不是栈但递归调用依赖系统栈。每次调用函数系统会把当前函数的局部变量、返回地址压入调用栈一层层递归下去栈就越压越深。网上有个热梗叫“单片机 c 语言没有堆栈吗为什么”其实不是没有堆栈而是单片机默认给的栈空间太小递归稍微深一点就栈溢出直接硬件异常。你在 PC 上写课设1MB 栈跑 64×64 迷宫没问题但老师真正想听的是你知道递归背后要消耗栈空间并且知道怎么把递归改成手动栈。这就引出升级版的常见加分点同一个 DFS 求解先写递归版本再写显式栈版本在报告里对比两种实现的栈占用。递归版的优点是代码短缺点是每个递归帧有函数调用开销而且没法在深搜过程中随时“跳出来”做状态展示显式栈版把状态全部捏在自己手里想暂停、想演示、想记录每一步都更方便。3.2 用显式栈实现 DFS回溯的路径记录与参数调优显式栈做 DFS 的思路是栈里保存“当前走到哪个格子、下一步该尝试哪个方向”。每走一步就压栈四个方向都走不通就把栈顶弹出——弹出的动作就是“回溯”。我用的数据结构是结构体数组#define MAX_STACK 8192 typedef struct { int x, y; // 当前坐标 int dir; // 下一个要尝试的方向下标 0~3 } Step; // 单步方向上、右、下、左 int mv_dx[4] {-1, 0, 1, 0}; int mv_dy[4] {0, 1, 0, -1}; // 显式栈 DFS 求解找到路径返回 1并把路径标记到 path 数组 int solveWithStack(int maze[MAX_ROW][MAX_COL], int row, int col, int sx, int sy, int ex, int ey, int path[MAX_ROW][MAX_COL]) { Step stack[MAX_STACK]; int visited[MAX_ROW][MAX_COL] {0}; int top -1; stack[top] (Step){sx, sy, 0}; visited[sx][sy] 1; while (top 0) { Step *cur stack[top]; if (cur-x ex cur-y ey) { // 从栈底到栈顶就是完整路径 for (int i 0; i top; i) { path[stack[i].x][stack[i].y] 1; } return 1; } int found 0; while (cur-dir 4) { int nx cur-x mv_dx[cur-dir]; int ny cur-y mv_dy[cur-dir]; cur-dir; // 方向指针自增回溯时接着试下一个 if (nx 0 nx row ny 0 ny col maze[nx][ny] 0 !visited[nx][ny]) { stack[top] (Step){nx, ny, 0}; visited[nx][ny] 1; found 1; break; // 找到路就立即深入 } } if (!found) { top--; // 四个方向都试完回退一格 } } return 0; // 栈空没有通路 }这段代码里最重要的字段是dir。它记录“这个格子下一步该试哪个方向”因为回溯时不能从头再试否则会死循环。每尝试一个方向就cur-dir就算这个方向走不通下次回到这个栈顶元素时也会从下一个方向继续而不是重新从 0 开始。visited数组防止走回头路否则老鼠会在两个空格之间来回踩栈越压越满。参数方面MAX_STACK开多大取决于迷宫大小。64×64 的迷宫路径最长也就几千步8192 足够如果迷宫开到 200×200建议把栈声明成动态数组或者至少 20000 起步。另外注意我传入了row和col而不是直接用MAX_ROW这样同一个函数可以在不同尺寸的迷宫上复用代码更规范。显式栈版本跑通后倒回去看递归版本就是同一件事递归函数自己压栈dir体现在 for 循环的i上。两种实现的最终路径一样但显式栈可以在每一步输出当前栈的内容这是做“路径搜索过程可视化”的基础。3.3 BFS 求最短路径手写队列与前驱数组恢复路径升级版最明显的功能就是“最短路径”。DFS 找到一条路径就收工不保证最短想拿最短路径要用 BFS也就是一层一层往外扩散。BFS 天然对应队列先进先出先到达出口的层数就是最短步数。typedef struct { int x, y; } Point; // BFS 求 (sx, sy) 到 (ex, ey) 的最短路径返回步数不可达返回 0 int bfsShortest(int maze[MAX_ROW][MAX_COL], int row, int col, int sx, int sy, int ex, int ey, int path[MAX_ROW][MAX_COL]) { Point queue[MAX_ROW * MAX_COL]; int dist[MAX_ROW][MAX_COL]; Point pre[MAX_ROW][MAX_COL]; int head 0, tail 0; for (int i 0; i row; i) for (int j 0; j col; j) dist[i][j] -1; // -1 表示还没访问过 queue[tail] (Point){sx, sy}; dist[sx][sy] 0; while (head tail) { Point cur queue[head]; if (cur.x ex cur.y ey) break; for (int k 0; k 4; k) { int nx cur.x mv_dx[k]; int ny cur.y mv_dy[k]; if (nx 0 nx row ny 0 ny col maze[nx][ny] 0 dist[nx][ny] -1) { dist[nx][ny] dist[cur.x][cur.y] 1; pre[nx][ny] cur; // 记下“从哪来” queue[tail] (Point){nx, ny}; } } } if (dist[ex][ey] -1) return 0; // 不可达 // 从出口倒着走回入口恢复路径 Point cur {ex, ey}; while (cur.x ! sx || cur.y ! sy) { path[cur.x][cur.y] 1; cur pre[cur.x][cur.y]; } path[sx][sy] 1; return dist[ex][ey] 1; // 1 是因为入口也算一步 }这里我用手写数组当队列tail负责入队head负责出队队空条件是head tail。为什么手写而不是用标准库的队列因为课设要求“用数据结构”手写队列能展示你对先进先出的理解而且答辩时老师一定会问“队列怎么实现的”手写版本可以直接讲清楚head和tail的滑动。dist数组记录每个格子到起点的最短步数同时也是访问标记-1表示未访问。pre数组是“前驱”记录每个格子是从哪个格子走过来的最后从出口反向回溯到入口就能把最短路径标出来。三个数组的职责要分清dist算距离、pre恢复路径、path输出。初学者常犯的错误是把pre省掉最后输出不了路径或者只用visited标记却不知道步数。BFS 返回值的单位也要注意dist[ex][ey]是从起点到出口走了多少步加上起点本身路径格子数就是“步数 1”。如果你在报告里写“最短路径长度为 12”必须说清楚是 12 步还是 12 个格子别再小细节上被扣分。4. “升级版”升级在哪多路径收集、动画演示与交互菜单做完生成和求解一个 60 分的课设已经成型。但“升级版”三个字意味着还要再加点东西打印所有路径、把搜索过程做成动画、做一个能循环操作的控制台菜单。这些不是算法题是工程题写起来不难但对答辩观感提升很大。4.1 打印所有可行路径访问标记撤销是唯一难点DFS 只找一条路径因为找到出口就 return。想收集所有路径做法是把 return 改成“记录一条继续找”同时保证已经为当前解设置的访问标记在返回前被撤销。看下面的代码int allPathCount 0; // 收集从 (x, y) 到 (ex, ey) 的所有路径 void collectAllPaths(int maze[MAX_ROW][MAX_COL], int row, int col, int x, int y, int ex, int ey, int visited[MAX_ROW][MAX_COL]) { if (x ex y ey) { allPathCount; printf(第 %d 条路径(%d, %d) 到出口\n, allPathCount, x, y); return; } for (int k 0; k 4; k) { int nx x mv_dx[k]; int ny y mv_dy[k]; if (nx 0 nx row ny 0 ny col maze[nx][ny] 0 !visited[nx][ny]) { visited[nx][ny] 1; // 进入前标记 collectAllPaths(maze, row, col, nx, ny, ex, ey, visited); visited[nx][ny] 0; // 返回后撤销关键 } } }唯一的难点就在visited[nx][ny] 0;这一行。撤销标记意味着这个格子虽然在“方案 A”里走过了但换一条分支时它还能重新被走。如果把撤销去掉第一次深搜会把所有走过的格子永久标记后续分支全部被堵死收集到的路径数会少很多。注意“打印所有路径”的开销是指数级的64×64 的迷宫路径数量可能非常庞大所以这个功能只适合在小迷宫上演示比如 9×9 的手工图。答辩演示用 9×9性能演示用 41×41 的 BFS两个场景分开效果最好。4.2 让求解过程动态化延时、清屏与光标定位纯控制台程序最直观的升级是动画老鼠一步一步往前走每一步把画面重画一遍。Windows 下的做法是system(cls)清屏加上Sleep延时再用一个光标定位函数把老鼠画在指定位置。注意这段代码依赖 Windows APILinux/macOS 用户可以用 ANSI 转义序列替代#include windows.h // Sleep、system 都在这个头文件里 // 按当前坐标和迷宫状态刷一帧画面 void render(int maze[MAX_ROW][MAX_COL], int row, int col, int cur_x, int cur_y) { system(cls); // 清屏重新画 for (int i 0; i row; i) { for (int j 0; j col; j) { if (i cur_x j cur_y) { printf(); // 当前老鼠位置 } else if (maze[i][j] 1) { printf(#); // 墙 } else { printf( ); // 空地 } } printf(\n); } Sleep(80); // 每帧 80ms太快看不清太慢老师着急 }调用时机放在 BFS 或 DFS 每走一步之后也就是循环里面每访问一个新格子就调用一次render。参数上Sleep(80)是最常用的值60 到 120 之间都可以小于 30 毫秒人眼基本跟不上大于 200 毫秒会显得程序很卡。清屏方式在 Windows 控制台可以直接用system(cls)但注意system调用会频繁拉起子进程有性能损耗如果以后想跨平台建议改用光标定位加\033[2J的 ANSI 序列。这一点写进课设报告里能体现你考虑过可移植性。4.3 菜单循环与存档读档让课设看起来像一个作品最后一个工程化点是主菜单。不要用“一个 main 函数从头跑到尾”的方式而是做一个while(1)循环用户输入数字选择功能int main(void) { int maze[MAX_ROW][MAX_COL] {0}; int row 0, col 0; int choice 0; while (1) { printf(\n 老鼠走迷宫课设 \n); printf(1. 从文件读取迷宫\n); printf(2. 随机生成迷宫并保存\n); printf(3. DFS 显示一条路径\n); printf(4. BFS 显示最短路径\n); printf(5. 统计所有路径数量\n); printf(0. 退出\n); printf(请选择); if (scanf(%d, choice) ! 1) break; if (choice 0) break; if (choice 1) { char name[64]; printf(输入文件名); scanf(%s, name); if (!loadMaze(name, maze, row, col)) printf(加载失败\n); else printf(加载成功%d 行 %d 列\n, row, col); } else if (choice 2) { // 初始化全墙 - dfsGenerate - saveMaze printf(随机生成功能初始化后调用 dfsGenerate\n); } else if (choice 3) { // 调用 solveWithStack然后打印路径图 } else if (choice 4) { // 调用 bfsShortest打印路径和步数 } } return 0; }菜单不是核心算法但能把前面所有函数串起来。尤其建议把“随机生成并保存”和“从文件读取”做成两个互相独立的功能答辩时老师让你现场生成一张新迷宫你保存后再读回来整个过程非常完整。scanf的返回值也要检查否则输入字母时缓冲区残留会导致菜单死循环这一点在下一章的避坑里细说。5. 老鼠走迷宫课设避坑指南5 个最常见的翻车现场这一章是我帮别人改课设时实际踩过的坑每一个都足够让程序在答辩现场崩溃按现象、原因、解决三步写清楚建议把这一节内容直接并入你的课设报告“调试过程”部分。5.1 数组越界行和列写反墙没包边现象程序一运行就报“内存访问冲突”或者迷宫打印出来第一行正常、后面全部错位。原因最常见的是把maze[x][y]的下标顺序写反。我习惯用x表示行、y表示列但文件里写的是“行数 列数”读文件时如果两层循环写成i col数组就会越界。另一个原因是生成迷宫时没有保留外围一圈墙DFS 从边缘格子出发nx 0直接访问负下标。解决读取和生成时都统一用“行、列”的顺序并给迷宫加一圈 1 的墙。我一般在数组声明上多留两行两列外围强制置 1内部才允许挖开。写完读函数后先用 3×3 的小迷宫跑一遍快速肉眼检查别一上来就跑 64×64。5.2 回溯时不撤销访问标记把路“焊死”现象函数能跑但打印出来的路径只有一条而且明显绕远或者“打印所有路径”功能只输出 1 条。原因DFS 里visited[nx][ny] 1之后递归返回时没有恢复为 0。这样第一次深搜走过的所有格子都被永久标记后面的分支再也进不去。这是“回溯”两个字里最容易丢的动作。解决每次递归调用返回后立刻把visited[nx][ny] 0还原。可以把这个写代码的顺序固定下来先写进入标记再写递归调用最后补还原顺序不要颠倒。显式栈版本里对应的坑是出栈时忘了清visited同样会让搜索提前结束。5.3 读文件多读一个换行符迷宫整体错位现象同一个文件别人读是对的自己读出来最后一行多一串 0或者行数少 1。原因用fgets逐行读再手动按字符解析时Windows 文件每行结尾是\r\nfgets会把\n保留在缓冲区里sscanf跳过它是没问题的但如果你用strlen数长度、再按字符判断就会把\r当成一个数字的一部分。还有同学在fscanf读完后顺手加一个fscanf(fp, \n)反而吞掉了下一行第一个数字。解决迷宫数字读取全部交给fscanf(%d)它天然跳过所有空白字符不要手动处理换行。要检查是否读完只判断fscanf返回值是不是 1而不是判断文件指针到了哪一行。这是最省心的做法也是我坚持用fscanf而不是fgets的原因。5.4 求解直接改迷宫地图导致第二次求解失败现象第一次求解成功路径用*或#画出来第二次再求解程序要么找不到路要么路径全是*。原因很多同学直接把路径标记写进maze数组把原本是 0 的空地改成了 2 或*。第二次搜索时maze[nx][ny] 0的判断永远不成立。解决路径标记单独用一个path数组求解函数只读maze、只写path。这样迷宫地图保持只读可以反复求解也可以在做完 BFS 后立刻做 DFS互不干扰。如果一定要让路径显示在原图上也得先复制一份maze在副本上操作。5.5 一条可行路径都没有起点终点与不可达判断现象生成的迷宫看似正常但求解函数返回 0程序直接卡住或什么都不显示。原因很可能是起点或终点坐标本身就是墙也可能是随机生成时出口角落被堵死。DFS 挖墙生成的迷宫理论上全连通但如果你把某个格子手动改成墙或者 PRIM 实现有 bug就会产生不可达区域。解决求解前先做两件事检查maze[sx][sy] 0 maze[ex][ey] 0然后调用一次 BFS如果返回 0 直接提示“出口不可达”而不是一头扎进 DFS 死循环。把不可达判断单独写成一个函数课设报告里可以写“本程序具备可达性校验能力”这句话比“我调通了”更有分量。6. 用三种方法验证你的求解器人眼、交叉算法与自动比对求解器写完怎么证明它是对的我习惯三种方法一起上从快到慢排。第一种是人眼对照把迷宫原图打印出来再打印带路径的图两张并排看。路径必须是一条连续的 4 连通通路从入口到出口中间没有穿过墙。这种方法对小迷宫最快但大迷宫人眼容易看花而且只能证明“有一条路”证明不了“是最短路径”。第二种是交叉算法验证用 DFS 和 BFS 分别求解同一张迷宫DFS 找到的路径长度一定大于等于 BFS 返回的最短步数。如果 DFS 结果比 BFS 短那一定有一方写错了如果 BFS 返回 0 而 DFS 有输出问题出在坐标或边界条件。这个对照不用写额外代码菜单里已经有两个功能跑两次对比就行。第三种是自动比对把求解结果写回文件写一个简单的检查函数遍历路径数组验证三点——起点和终点被标记路径上每个格子都是maze 0相邻两个路径点之间曼哈顿距离为 1。这一步看起来麻烦但一旦迷宫尺寸加大人眼完全不可靠自动化检查是唯一能兜底的方案。我现在的习惯是每改一次寻路逻辑先跑一遍自动检查再继续下一个功能。最后说一个答辩时的小技巧不要只在控制台闪一遍结果提前准备好三张图——一张原迷宫、一张 DFS 路径、一张 BFS 最短路径并排放在报告里标注清路径长度。老师问到算法复杂度时直接答 DFS 最坏 O(行×列)、BFS 同样 O(行×列)空间上 BFS 的队列最多存整张图。这也是我对每个迷宫数据的第一反应先检查可达性再谈算法对比。希望帮到你。本文还有配套的精品资源点击获取
返回列表