递归成员函数调用时vector越界错误排查求助
问题分析与修复方案
1. 直接触发越界的边界判断错误
看代码中第四个方向(south)的条件判断:
if((x<=columns && y+1<=rows && x >= 0 && y+1 >= 0) && seed%4==3)
cellVector的行索引范围是0~rows-1,列索引是0~columns-1,这里y+1<=rows会允许y+1等于rows,超出vector的最大合法索引;同理x<=columns也会让x等于columns,超出列的合法范围。
修正后的判断:
if((x <= columns-1 && y+1 <= rows-1 && x >= 0 && y+1 >= 0) && seed%4==3)
2. 传值导致的逻辑错误(间接引发越界)
函数参数cell currentCell是传值传递,你执行currentCell.setVisited(true)只会修改副本,不会改变cellVector里的原对象。这会导致后续递归中,原cell的visited状态未被标记,可能重复尝试访问同一cell,甚至触发错误的边界判断。
改成传引用:
void generateMaze(bool seedSet, cell& currentCell)
递归调用时的参数无需修改,但要确保函数参数能接收引用。
3. seed逻辑缺陷(易引发无限递归或错误方向)
当前逻辑中,只有第一次调用(seedSet=false)时会设置seed,后续递归seedSet=true时,seed会一直沿用之前的值,导致每次递归都往同一个方向走,极易触发边界错误或无限递归。
更合理的方式是每次递归随机打乱方向顺序(符合深度优先迷宫生成的标准逻辑):
// 替代原有的if-else链 vector<pair<int, int>> dirs = {{-1,0}, {0,-1}, {1,0}, {0,1}}; // west, north, east, south random_shuffle(dirs.begin(), dirs.end()); // 需要包含<algorithm>头文件 for(auto& dir : dirs) { int dx = dir.first; int dy = dir.second; int nx = x + dx; int ny = y + dy; if(nx >=0 && nx < columns && ny >=0 && ny < rows) { if(!cellVector.at(ny).at(nx).checkVisited()) { // 根据方向处理墙和可视化数组 if(dx == -1) { // west cellVector.at(y).at(x).setWestWall(false); cellVector.at(ny).at(nx).setEastWall(false); mazeVisual.at(y*2+1).at(x*4) = ' '; } else if(dy == -1) { // north cellVector.at(y).at(x).setNorthWall(false); cellVector.at(ny).at(nx).setSouthWall(false); mazeVisual.at(y*2).at(x*4+1) = ' '; mazeVisual.at(y*2).at(x*4+2) = ' '; mazeVisual.at(y*2).at(x*4+3) = ' '; } else if(dx == 1) { // east cellVector.at(y).at(x).setEastWall(false); cellVector.at(ny).at(nx).setWestWall(false); mazeVisual.at(y*2+1).at(x*4+4) = ' '; } else if(dy == 1) { // south cellVector.at(y).at(x).setSouthWall(false); cellVector.at(ny).at(nx).setNorthWall(false); mazeVisual.at(y*2+2).at(x*4+1) = ' '; mazeVisual.at(y*2+2).at(x*4+2) = ' '; mazeVisual.at(y*2+2).at(x*4+3) = ' '; } cellVector.at(ny).at(nx).setVisited(true); generateMaze(true, cellVector.at(ny).at(nx)); break; } } }
4. 可视化数组的大小验证
确保mazeVisual的初始化大小正确:根据代码中的索引计算,rows个cell对应的可视化行数应为2*rows +1,列数应为4*columns +1。初始化时添加检查:
mazeVisual.resize(2*rows +1); for(auto& row : mazeVisual) { row.resize(4*columns +1, '#'); // 用墙字符初始化 }
总结
优先修复边界判断错误,再解决传值导致的状态不更新问题,最后优化随机方向逻辑,即可解决vector越界问题。
内容的提问来源于stack exchange,提问作者tommyBruiser
相关产品推荐
相关产品推荐

