C++ BFS迷宫帮助c++;

C++ BFS迷宫帮助c++;,c++,breadth-first-search,maze,C++,Breadth First Search,Maze,我正在尝试使用广度优先搜索制作迷宫解算器,并使用字符“*”标记最短路径 迷宫实际上只是一堆文字。迷宫由一个nxn网格组成,由“#”符号组成,这些符号是墙,而句点表示可行走区域/路径。“S”表示开始,“F”表示结束。现在,这个函数似乎没有找到解决方案(它认为它有解决方案,即使不可能)。我正在检查四个邻居,如果它们“未找到”(-1),则将它们添加到要处理的队列中 迷宫适用于多个迷宫,但不适用于此迷宫: ...###.#.... ##.#...####. ...#.#.#.... #.####.##

我正在尝试使用广度优先搜索制作迷宫解算器,并使用字符“*”标记最短路径

迷宫实际上只是一堆文字。迷宫由一个nxn网格组成,由“#”符号组成,这些符号是墙,而句点表示可行走区域/路径。“S”表示开始,“F”表示结束。现在,这个函数似乎没有找到解决方案(它认为它有解决方案,即使不可能)。我正在检查四个邻居,如果它们“未找到”(-1),则将它们添加到要处理的队列中

迷宫适用于多个迷宫,但不适用于此迷宫:

...###.#.... 
##.#...####.
...#.#.#....
#.####.####.
#F..#..#.##.
###.#....#S.
#.#.####.##.
....#.#...#.
.####.#.#.#.
........#...
我的逻辑中可能遗漏了什么

int mazeSolver(char *maze, int rows, int cols)
{
int start = 0;
int finish = 0;
for (int i=0;i<rows*cols;i++) {
    if (maze[i] == 'S') { start=i; }
    if (maze[i] == 'F') { finish=i; }
}
if (finish==0 || start==0) { return -1; }

char* bfsq;
bfsq = new char[rows*cols]; //initialize queue array
int head = 0;
int tail = 0;
bool solved = false;
char* prd;  
prd = new char[rows*cols]; //initialize predecessor array
for (int i=0;i<rows*cols;i++) {
    prd[i] = -1;
}
prd[start] = -2; //set the start location
bfsq[tail] = start;
tail++;

int delta[] = {-cols,-1,cols,+1};   // North, West, South, East neighbors

while(tail>head) {
    int front = bfsq[head];
    head++;
    for (int i=0; i<4; i++) {
        int neighbor = front+delta[i];
        if (neighbor/cols < 0 || neighbor/cols >= rows || neighbor%cols < 0 || neighbor%cols >= cols) {
            continue;
        }
        if (prd[neighbor] == -1 && maze[neighbor]!='#') {
            prd[neighbor] = front;
            bfsq[tail] = neighbor;
            tail++;
            if (maze[neighbor] == 'F') { solved = true; }
        }   
    }
}

if (solved == true) {   
    int previous = finish;
    while (previous != start) {
        maze[previous] = '*';
        previous = prd[previous];
    }
    maze[finish] = 'F';
    return 1;
}
else { return 0; }

delete [] prd;
delete [] bfsq;

}
int-mazeSolver(字符*迷宫、int行、int列)
{
int start=0;
int finish=0;
for(int i=0;i=cols){
继续;
}
如果(prd[邻居]=-1&&maze[邻居]!='#'){
珠江三角洲[近邻]=前沿;
bfsq[tail]=邻居;
tail++;
如果(迷宫[邻居]='F'){solved=true;}
}   
}
}
如果(已解决==true){
int-previous=完成;
while(上一个!=开始){
迷宫[先前]='*';
上一次=珠三角[上一次];
}
迷宫[完成]=“F”;
返回1;
}
else{return 0;}
删除[]珠三角;
删除[]bfsq;
}
一些评论:

可以在C++中使用队列容器,使用起来更容易
  • 在本任务中,您可以编写如下内容:
  • 然后你可以简单地遍历所有的四个方面,你不应该复制粘贴相同的代码

  • 数组的边界将出现问题。因为你没有检查它
  • 当你们建立了终点时,你们应该从循环中解脱出来
  • 在上一个循环中,您有一个错误。它将在您所在的所有单元格中打印*(不仅以最佳方式)。它应该看起来:
  • 当然,这个周期应该在最后一个if,因为你不知道在那一刻你是否到达了终点


    PS和清除在函数中分配的内存更好可以大大简化遍历邻居的过程(我知道这与kobra的建议有些相似,但可以进一步改进)。我使用移动数组定义给定移动的x和y增量,如下所示:

    int moves[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
    
    请注意,tis不仅列出了给定单元格中所有可能的移动,而且还按顺时针方向列出了它们,这对解决某些问题很有用。 现在,为了遍历数组,我使用了一个
    std::queue
    ,通过这种方式,当前位置由对应于它的一对坐标定义。下面是我如何循环通过一个gien cell c的邻居:

    pair<int,int> c;
    for (int l = 0;l < 4/*size of moves*/;++l){
      int ti = c.first + moves[l][0];
      int tj = c.second + moves[l][1];
      if (ti < 0 || ti >= n || tj < 0 || tj >= m) {
        // This move goes out of the field
        continue;
      }
    
      // Do something.
    }
    
    c对;
    对于(int l=0;l<4/*移动大小*/;++l){
    int ti=c.first+moves[l][0];
    int tj=c.秒+移动[l][1];
    如果(ti<0 | | ti>=n | | tj<0 | | tj>=m){
    //这一举动是不切实际的
    继续;
    }
    //做点什么。
    }
    
    我知道这段代码与你的代码并没有太大关系,但在我教授这类问题时,相信我,当我向很多学生展示这种方法时,他们都非常感激

    现在回到您的问题-您需要从结束位置开始,使用prd数组查找其父级,然后查找其父级的父级,依此类推,直到到达父级为负的单元格。相反,您所做的是考虑所有访问的单元格,其中一些单元格不在从
    S
    F
    的最短路径上

    一旦设置了
    solved=true
    就可以中断,这将稍微优化算法

    我个人认为,你总能找到解决办法,因为你没有任何从球场上摔下来的检查。(我的代码中的
    if(ti<0 | | ti>=n | | tj<0 | | tj>=m)
    位)


    希望这对您有所帮助,并为您提供一些如何改进编码的提示

    我还没有学会排队,不幸的是,我被你的指导弄糊涂了。在您的示例中,“ti”和“tj”到底代表什么?实际上,我给出的代码片段与队列无关。我只展示了如何迭代单元格的邻居
    c
    是当前单元格,其候选相邻单元格的坐标是
    (ti,tj)
    我计算这些坐标以验证它们没有从字段中脱落。希望这能让它更清楚。那么“n”和“m”将是行和列的数量,例如?您正在确定坐标是否在迷宫的范围内,对吗?感谢您的帮助,该程序现在可以在几个测试迷宫上运行,但不能在其中一个上运行(请参阅原始帖子)。有什么想法吗?看来你的代码现在应该没问题了。我注意到的是,您的电路板是矩形的,所以有一种猜测是您可能传递了错误的行和列值(即交换的值)。在您的示例中,行应该是10,列应该是12。您能否澄清您的函数,以便为所选路径填写“*”?它似乎不起作用,我不清楚我是否理解您的意图。这部分代码看起来不错,可能您的代码中仍然有一些错误。在您的代码中,您试图将*放在BFS中访问过的所有单元格中,在我的代码中,我使用数组prd从最后一个顶点返回到第一个顶点。所以我只把*放在一个路径中。我刚刚编辑了我的原始帖子以反映我的最新尝试-但是,它有两个问题:它标记了不应该成为路径一部分的空格(与以前不同,但仍然是错误的),在代码运行后,我收到一个错误声明“glibc detected***./迷宫:双重释放或损坏(out)”你有什么指导吗?谢谢你的帮助,这个程序现在可以在几个测试迷宫上运行,但没有一个(见原始帖子)。有什么想法吗?只是一个与您的问题无关的评论-您永远不会删除prd或bfsq,因为您已经编写了代码。
    int moves[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
    
    pair<int,int> c;
    for (int l = 0;l < 4/*size of moves*/;++l){
      int ti = c.first + moves[l][0];
      int tj = c.second + moves[l][1];
      if (ti < 0 || ti >= n || tj < 0 || tj >= m) {
        // This move goes out of the field
        continue;
      }
    
      // Do something.
    }