问题
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