Maze shortest path using recursion

允我心安 提交于 2019-12-11 19:23:56

问题


First of all I want to note that I posted this same question before and did not found a right answer, so sorry for repeating question.

Note that I am required to use recursion here. I am aware that shortest path is usually found using BFS, which is not recursive, but I need to know how can this be done recursively.

I am working on a rouge game and one of my monsters behaves like this. In a maze, if monster can reach the player in 15 or less steps, it makes the most optimal move possible. In order to implement this, I wrote a small program mimicking basically what is going to happen in my game. My program works in a way that it is able to check if x amount of moves will get him to destination. The only part I am not sure is how to get the first step, so I can pass that info to my monster move function. Here is the program that I wrote so far.

One of my fellow students suggests to fill the empty space with different values and find the path that way, but I could not understand what he meant. Can someone explain to me how this can be done?

#include <iostream>

using namespace std;



bool pathExists(char maze[][10], int sr, int sc, int er, int ec, int distance) {
    if (maze[sr][sc] != '.')
        return false;

    if (sr == er  &&  sc == ec)
        return true;

    if(distance == 15) {
        cout<<"Cant make it in 15 steps"<<endl;
        return false;
    }
    maze[sr][sc] = '@';  // anything non-'.' will do

    if (pathExists(maze, sr-1, sc, er, ec, distance+1))
        return true;
    if (pathExists(maze, sr+1, sc, er, ec,distance+1))
        return true;
    if (pathExists(maze, sr, sc-1, er, ec, distance+1))
        return true;
    if (pathExists(maze, sr, sc+1, er, ec, distance+1))
        return true;

    return false;
}

int main() {
    char maze[10][10] = {
        { 'X','X','X','X','X','X','X','X','X','X'},
        { 'X','.','.','.','.','.','.','.','.','X'},
        { 'X','.','X','X','X','X','.','X','X','X'},
        { 'X','.','.','X','.','X','.','.','.','X'},
        { 'X','.','.','X','.','.','.','X','.','X'},
        { 'X','.','X','X','.','X','X','X','.','X'},
        { 'X','.','X','.','.','.','.','X','X','X'},
        { 'X','.','.','X','X','.','X','X','.','X'},
        { 'X','.','.','x','.','.','.','.','.','X'},
        { 'X','X','X','X','X','X','X','X','X','X'}
    };

    if (pathExists(maze, 8,8, 1,1,0))
        cout << "Solvable!" << endl;
    else
        cout << "Out of luck!" << endl;
}

回答1:


Your algorithm works well. The only thing missing is to restore the '.' in pathExist() if the tested path is not successful :

    ...
    if(pathExists(maze, sr, sc + 1, er, ec, distance + 1))
        return true;

    maze[sr][sc] = '.'; //<===========  add this to restore the maze state

    return false;
    }

Without this line, your failed attempts to find the right path will fill the array with '@' so that subsequent exploration will not find any praticable '.' anymore.

By the way, the maze that you've posted in your question is not solvable in less than 15 attempts, because of the 'x' in position [8][3].

Additional comment:

You've also asked how this work. In fact, your recursive algorithm without the trick of the '@' has no memory. So in the recursive call, it doesn't remember were it came from, which will result in infinite recursion accrding to the following pattern:


The fact of changing the current position temporarily to '@' is as if you'd mark the different cells of the path currently being explored:

Note that if you print out the grid at the end, you'll see the full path that was found (with the problematic 'x' removed):




回答2:


The only part I am not sure is how to get the first step, so I can pass that info to my monster move function. Here is the program that I wrote so far.

A possible way would be to return a code for the next step from the function if the path exists, otherwise 0 (although this might not be a recommended way for readable code, but just to propose the idea)

int pathExists(char maze[][10], int sr, int sc, int er, int ec, int distance) {
    if (maze[sr][sc] != '.')
        return 0; //

    if (sr == er  &&  sc == ec)
        return 5; // we are there

    if(distance == 15) {
        cout<<"Cant make it in 15 steps"<<endl;
        return 0;
    }
    maze[sr][sc] = '@';  // anything non-'.' will do

    if (pathExists(maze, sr-1, sc, er, ec, distance+1))
        return -1; // move north
    if (pathExists(maze, sr+1, sc, er, ec,distance+1))
        return 1; // move south
    if (pathExists(maze, sr, sc-1, er, ec, distance+1))
        return -2; // move west
    if (pathExists(maze, sr, sc+1, er, ec, distance+1))
        return 2; // move east

    maze[sr][sc] = '.'; // restore the maze, as in the previous answer
    return 0;
}


来源:https://stackoverflow.com/questions/30466403/maze-shortest-path-using-recursion

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!