基于单元格值融合的迷宫生成代码死循环问题求助
排查迷宫生成代码的死循环与生成失败问题
嗨,我仔细扒了你的代码,发现几个致命的小问题,直接导致了死循环、生成失败甚至调试断点失效,咱们一个个说:
1. 内存分配错误(断点失效的元凶)
你定义的Maze结构体里,array是二级指针MazeCell**,但在initMaze里却用了malloc(nbCells*sizeof(MazeCell))——这是给一级指针分配内存的写法!这种不匹配的内存分配会直接破坏堆结构,导致程序运行时内存越界,IDE的调试器根本没法正常工作,断点自然触发不了。
如果你的逻辑是把迷宫当成一维数组处理(看代码里是用i从0到m*n-1遍历),那直接把结构体里的array改成一级指针就行:
typedef struct _maze_t { int row, column; MazeCell* array; // 改成一级指针,匹配一维数组的用法 } Maze;
这样原来的内存分配代码就没问题了。
2. 随机数函数逻辑错误(永远选不到左侧墙)
你的rand_a_b函数返回的是[a, b)区间的随机数,但你调用rand_a_b(1,2)想选1或2——这根本不可能!因为b-a=1,rand()%1永远是0,加a=1后结果永远是1,左侧墙的代码块从来不会执行!
这就导致迷宫只能合并上下区域,左右区域永远孤立,循环永远等不到所有单元格值相同的时刻,直接死循环。
修复方法有两种:
- 要么修改函数返回
[a, b]区间:int rand_a_b(int a, int b){ return rand() % (b - a + 1) + a; // 这样rand_a_b(1,2)会返回1或2 } - 要么调用时传入
rand_a_b(1,3),利用原来的[a,b)区间覆盖1和2。
3. 墙的判断条件错误(漏掉有效合并,触发无效合并)
- 处理上方墙时,你写的
if(nbAl>n),比如n=5时,索引5的单元格(第二行第一个)的nbAl>n是5>5?不成立,直接跳过了它和上方单元格(索引0)的合并,漏掉了大量有效合并机会。正确的判断应该是if(nbAl >=n)(只要不是第一行的单元格,都有上方墙)。 - 处理左侧墙时,
if(nbAl>0)不够,比如索引5(第二行第一个)的nbAl-1是4(第一行最后一个),这会错误地合并不同行的单元格,导致区域逻辑混乱。正确的判断应该是if(nbAl %n !=0)(只有不是每行第一个的单元格,才有左侧墙)。
4. 循环终止条件的逻辑漏洞(基准值被修改导致死循环)
你原来的终止判断是拿第一个单元格的初始值a和其他单元格比较,但合并时可能会把第一个单元格的cellValue改成其他值(比如把1改成5),这时候a还是初始的1,而所有单元格的值都是5,循环会认为还有不同的值,永远不会终止。
改成直接检查所有单元格的值是否相同就行:
int firstValue = oMaze->array[0]->cellValue; done = 1; for(i=0; i<m*n; i++){ if(oMaze->array[i]->cellValue != firstValue){ done = 0; break; // 只要有一个不同,直接跳出循环,不用遍历全部 } }
修正后的核心循环代码示例
把上面的修复点整合后,核心循环部分大概是这样:
int done=0; while(done==0) { int nbAl = rand_a_b(0, m*n); // 选0到m*n-1的单元格 int wallChoosen = rand_a_b(1, 2); // 假设已经修复了rand_a_b函数 if(wallChoosen == 1) { // 处理上方墙:不是第一行的单元格 if(nbAl >= n) { int aboveIndex = nbAl - n; int oldValue = oMaze->array[aboveIndex]->cellValue; int newValue = oMaze->array[nbAl]->cellValue; if(oldValue != newValue) { oMaze->array[nbAl]->wallAbove = 0; // 统一把大值合并到小值,避免基准值混乱 int target = oldValue < newValue ? oldValue : newValue; int source = oldValue < newValue ? newValue : oldValue; for(i=0; i<m*n; i++){ if(oMaze->array[i]->cellValue == source){ oMaze->array[i]->cellValue = target; } } } } } else if(wallChoosen == 2) { // 处理左侧墙:不是每行第一个的单元格 if(nbAl % n != 0) { int leftIndex = nbAl - 1; int oldValue = oMaze->array[leftIndex]->cellValue; int newValue = oMaze->array[nbAl]->cellValue; if(oldValue != newValue) { oMaze->array[nbAl]->wallLeft = 0; int target = oldValue < newValue ? oldValue : newValue; int source = oldValue < newValue ? newValue : oldValue; for(i=0; i<m*n; i++){ if(oMaze->array[i]->cellValue == source){ oMaze->array[i]->cellValue = target; } } } } } // 检查是否所有单元格值相同 int firstValue = oMaze->array[0]->cellValue; done = 1; for(i=0; i<m*n; i++){ if(oMaze->array[i]->cellValue != firstValue){ done = 0; break; } } }
把这些修复点都改完后,你的代码应该就能正常生成迷宫,不会死循环,断点也能正常触发了。
内容的提问来源于stack exchange,提问作者Sam Paciência
相关产品推荐
相关产品推荐

