如何为老鼠走迷宫问题实现支持自定义输入的用户交互接口
迷宫程序交互功能修复方案
核心错误原因
- 变量作用域冲突:main函数内定义的局部
Maze数组和全局的固定6×6Maze数组重名,Solution函数默认访问全局旧数组,完全没有用到用户输入的迷宫数据 - 变长数组定义顺序错误:在读取
col、row参数之前就定义了int Maze[col][row];,此时col、row是未初始化的脏值,数组大小完全不符合预期 - 循环条件笔误:输入迷宫的内层循环判断条件误写为
i<col,而非j<col,会导致数组越界写入,破坏内存数据 - 方向逻辑错误:方向判断的
dir=0分支错误赋值i0 = j-1,应该是i0 = i-1,方向逻辑完全错误 - 边界硬编码:
Solution里的坐标边界判断写死了i0 <=5 && j0 <=5,如果用户输入的迷宫行列不是6,合法坐标会被误判为越界
修复步骤
- 删除全局的
Maze数组定义,将Maze、迷宫行数、列数作为参数传入Solution函数 - 调整输入逻辑顺序:先读取行列数,再定义变长数组
Maze - 修正输入迷宫的循环条件笔误
- 修正方向判断的逻辑错误
- 将边界判断改为动态读取传入的行列数
完整可运行代码
#include<stdio.h> #define MAXSIZE 1000 // 带坐标的点位结构体 typedef struct { int x; int y; int pre; // 栈中上一个点位的索引 }Point; // 迷宫队列结构体 typedef struct { Point data[MAXSIZE]; int front; int rear; }Queue; // 初始化队列 int InitQueue(Queue *q) { q->front = q->rear = -1; return 1; } // 判断队列是否为空 int IsEmpty(Queue *q) { return q->front == q->rear ? 1 : 0; } // 判断队列是否已满 int IsFull(Queue *q) { return q->rear == MAXSIZE-1 ? 1 : 0; } // 入队 int Enqueue(Queue *q, Point b) { if(IsFull(q)) { printf("队列已满\n"); return 0; } q->rear++; q->data[q->rear] = b; return 1; } // 出队 int Dequeue(Queue *q, Point *b) { if(IsEmpty(q)) { printf("队列为空\n"); return 0; } q->front++; *b = q->data[q->front]; return 1; } // 打印路径 void PrintPath(Queue *q, int front) { int p = front, temp; while(p != 0) { temp = q->data[p].pre; q->data[p].pre = -1; p = temp; } for(int i = 0; i <= q->rear; i++) { if(q->data[i].pre == -1) { printf("(%d, %d)->", q->data[i].x, q->data[i].y); } } printf("\n"); } // 迷宫求解函数 int Solution(Queue *q, int x1, int y1, int xe, int ye, int row, int col, int Maze[row][col]) { Point now; int i, j, i0, j0; now.x = x1; now.y = y1; now.pre = -1; Enqueue(q, now); Maze[x1][y1] = -1; // 标记起点已访问 while(!IsEmpty(q)) { Dequeue(q, &now); i = now.x; j = now.y; if(i == xe && j == ye) // 到达终点 { PrintPath(q, q->front); return 1; } // 四个方向遍历:上、右、下、左 int dir; for(dir = 0; dir < 4; dir++) { switch(dir) { case 0: i0 = i-1; j0 = j; break; case 1: i0 = i; j0 = j+1; break; case 2: i0 = i+1; j0 = j; break; case 3: i0 = i; j0 = j-1; break; } // 判断坐标合法且可通行 if(i0 >= 0 && j0 >= 0 && i0 < row && j0 < col && Maze[i0][j0] == 0) { now.x = i0; now.y = j0; now.pre = q->front; Enqueue(q, now); Maze[i0][j0] = -1; // 标记已访问 } } } return 0; } int main() { int col, row; printf("请输入迷宫的列数(不超过10):\n"); scanf("%d", &col); printf("请输入迷宫的行数(不超过10):\n"); scanf("%d", &row); int Maze[row][col]; // 读取参数后再定义变长数组 printf("迷宫由墙和通路组成,输入1代表墙,0代表通路,请逐行输入迷宫:\n"); for(int i = 0; i < row; i++) { printf("输入第%d行的%d个元素:", i+1, col); for(int j = 0; j < col; j++) // 修正循环条件 { scanf("%d", &Maze[i][j]); } } int x2, y2; printf("请输入终点坐标(x y,坐标从0开始计数):\n"); scanf("%d %d", &x2, &y2); // 校验终点合法性 if(x2 <0 || x2 >= row || y2 <0 || y2 >= col || Maze[x2][y2] == 1) { printf("输入的终点不合法\n"); return 0; } Queue queue; InitQueue(&queue); printf("迷宫最短路径为:\n"); if(Solution(&queue, 0, 0, x2, y2, row, col, Maze) == 0) { printf("未找到有效路径!\n"); } return 0; }
内容的提问来源于stack exchange,提问作者Betty Gandhi
相关产品推荐
相关产品推荐

