简体   繁体   中英

3D Maze solving with BFS. How to get a full shortest path to the end point if found in C++?

I am trying to implement the BFS algorithm to check if a goal is reachable in a 3D maze given a starting position. The maze was imported from a txt file. My solution seems to find the goal however I am not able to display just the path that was taken. My issue: I am able to find the goal but I have no idea how to get the shortest path and print it out. I was thinking about using parents/children concept but I am not sure whether it works. I hope I can finally print out the path like this: (from start point to end point)

1 3 1
1 3 2
2 3 3

This is my code:

I use struct to store informations from txt file.

struct Maze
{
    int x,y,z; //dimensions
    int sx,sy,sz;//start point
    int ex,ey,ez;//exit point
    int grids; //number of grids in the maze where are actions available
    vector<vector<int> > glist;
    vector< pair<int, pair<int, int> > > gpoint; // list of (x,y,z) accessible
};
void BFS(Maze &maze,vector< pair<int, pair<int, int> > > result){
    bool reach_end = false;
    int xx,yy,zz;                               
    int j=0;
    int move_count = 0;
    int nodes_left_in_layer = 1;
    int nodes_in_next_layer = 0;
    queue<int> xq,yq,zq;
    xq.push(maze.sx);yq.push(maze.sy);zq.push(maze.sz);
    

    vector< pair<int, pair<int, int> > > visited(maze.grids);
    visited.push_back(make_pair(xx, make_pair(yy, zz)));
    result.push_back(make_pair(xx, make_pair(yy, zz)));

    while(!xq.empty()){
        int xfront = xq.front();int yfront = yq.front();int zfront = zq.front();
        xq.pop();yq.pop();zq.pop();
        
        if(xfront==maze.ex && yfront==maze.ey && zfront==maze.ez){
            reach_end = true;
            cout << "reach end!" <<endl;
            break;
        }
        int index=0;
        index = getindex(maze,xfront,yfront,zfront);
    
        
        //EXPLORE NEIGHBORS
        for(j=0;j<maze.glist[index].size()-3;j++){
        
            int action = maze.glist[index][3+j];
            
            xx = xfront+dx[action-1];    // dx,dy,dz are lists of actions. 
            yy = yfront+dy[action-1];
            zz = zfront+dz[action-1];
            auto p2 = make_pair(xx,make_pair(yy,zz));
        
            //skip bounds
            if(xx<0 || yy<0 || zz<0){}
            else if(xx >= maze.x || yy>= maze.y || zz >= maze.z){}
            else if(find(visited.begin(),visited.end(),p2)!=visited.end()){
                cout << "Visited: "<<xx <<yy<<zz<<endl;
            }
            else if(find(maze.gpoint.begin(),maze.gpoint.end(),p2)!=maze.gpoint.end()){
            
                int index2 = getindex(maze,xx,yy,zz);
                xq.push(xx);yq.push(yy);zq.push(zz);
                visited.push_back(p2);
                nodes_in_next_layer++;
            }else{
                cout<<"Not in glist!! "<<endl;
            }
        
        }
  
        nodes_left_in_layer--;
        if(nodes_left_in_layer==0){
            nodes_left_in_layer = nodes_in_next_layer;
            nodes_in_next_layer=0;
            move_count++;
        }
    
    
    }
    if(reach_end){
    
        cout<< "move_count: " <<move_count<<endl;
        cout << "nodes_left_in_layer: " <<nodes_left_in_layer<<endl;
        cout << "nodes_in_next_layer: " <<nodes_in_next_layer<<endl;
    }else{
        cout<< "xxxFAILxxx " <<endl;
    }
}

There 2 common ways:

  1. You remember the distance of every visited cell from the start, and then when you find the end you walk back to the start, along the path that decreases distance with every step. This method is memory-efficient when you can use a bit-packed representation for visited vertexes, since you only need to remember the lowest 2 bits of the distance. This doesn't apply easily to you.

  2. You directly remember the predecessor of every visited cell, and when you find the end you just follow all those links back to the start.

You should probably use method (2).

I suggest you replace your visited vector, which is currently very inefficient, with a std::unordered_map that maps each visited vertex to the index of its predecessor.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM