(This is not a duplicate) We have a 2D maze surrounded by X on all 4 sides and there are inner blocks too.
All these characters of the maze is stored in 2D array. The program must find the path from start 'S' to goal 'G'. For this, a boolean method called 'solve(int row, int col) is uses and is initialized with row and column index of 'S'. The algorithm must be recursive. It should return true if its able to find the path to 'G' and false other wise. Here's how I tried to approach this problem which shows "partial correct result".
public boolean solve(int row, int col) {
char right = this.theMaze[row][col + 1];
char left = this.theMaze[row][col - 1];
char up = this.theMaze[row - 1][col];
char down = this.theMaze[row + 1][col];
if (right == 'G' || left == 'G' || up == 'G' || down == 'G') {
return true;
}
System.out.println("position=>"+"("+row + ":" + col+")");
if (right == ' ') {
return solve(row,col+1);
}
if (down == ' ') {
return solve(row+1,col);
}
if (left == ' ') {
return solve(row,col-1);
}
if (up == ' ') {
return solve(row-1,col);
}
return false;
}
Here is the output it solved :
0 1 2 3 4 5 6 7 8 9 10
0 X X X X X X X X X X X
1 X X S X X X X X X X
2 X X X X X X X X X
3 X X X X X X X X X
4 X X X X X X X X X
5 X X X X X X X X X
6 X X X X X X X X X
7 X X X X X X X G X X
8 X X X X
9 X X X X X X X X X X X
position=>(1:2)
position=>(2:2)
position=>(3:2)
position=>(4:2)
position=>(5:2)
position=>(6:2)
position=>(7:2)
position=>(8:2)
position=>(8:3)
position=>(8:4)
position=>(8:5)
position=>(8:6)
position=>(8:7)
true
But when I place 'G' one step up (at 6,8). It shows stackOverflow error. The reason is because the recursion occurs between 2 points at this state (somehow just like indirect recursion).
How can I solve this problem. Is there anyway to tell the program to move up instead of down? Changing the position of conditional statements wont work though. And think a position that has more than one path to go but only one leads to 'G'. How to come back to initial position and try anther path ? Thanks in advance.
Update:
Here is a Github Repo link to the complete solution of this problem by me.
You could fill in an alternate symbol in the spaces you stepped through already so your program will know that it was there already.
You can use a DFS or BFS. The DFS is the easiest one. You simply make a recursion, navigate in all 4/8-directions and mark that place (X,Y) as visited. If it's you destiny 'G', return true otherwise continue.
Tips:
- Don't use the same matrix to read the map and mark it as visited, KISS
- You have to constantly check if you have discovered G. You can make this by return always FALSE or TRUE, or you can use a global variable.
If you have trouble implementing it try to google for some source code about this problems: http://en.wikipedia.org/wiki/Flood_fill
http://www.geeksforgeeks.org/ford-fulkerson-algorithm-for-maximum-flow-problem/
In your present code there is a possibility that you return out false
without looking at other connected positions.
You should look through other possibilities before returning out from the if
condition.
Also, you should check whether the position has been visited to avoid infinite recursion.
Change your code to:
bool solved = false;
visited[row][col] = true;
if (right == ' ' && !visited[row][col+1]) {
solved = solve(row,col+1);
}
if (down == ' ' && !solved && !visited[row+1][col]) {
solved = solve(row+1,col);
}
if (left == ' ' && !solved && !visited[row][col-1]) {
solved = solve(row,col-1);
}
if (up == ' ' && !solved !visited[row-1][col]) {
solved = solve(row-1,col);
}
return solved;
Here is a pseudo code for you to solve the maze and also retrace the solution : -
boolean Solve(int x,int y) {
if(isTarget(x,y))
return(true)
if(valid(x+1,y)&&Map[x+1][y]==' ') {
Map[x][y] = 'D'
if(Solve(x+1,y))
return(true)
Map[x][y] = ' '
}
if(valid(x-1,y)&&Map[x-1][y]==' ') {
Map[x][y] = 'U'
if(Solve(x-1,y))
return(true)
Map[x][y] = ' '
}
if(valid(x,y+1)&&Map[x][y+1]==' ') {
Map[x][y] = 'R'
if(Solve(x,y+1))
return(true)
Map[x][y] = ' '
}
if(valid(x,y-1)&&Map[x][y-1]==' ') {
Map[x][y] = 'L'
if(Solve(x,y-1))
return(true)
Map[x][y] = ' '
}
return(false);
}
Incase you are looking for the complete solution, I have uploaded it on my Github Repository.
Inspired by this article Solving a 2D Maze, a recursive solution
const CORRIDOR = 0;
const WALL = 1;
const EXIT = 2;
// board - 2D array
// start - [row, column] location of start point
function findPath(board, start) {
let seenPath = new Set();
findPathRecur(board, start, seenPath)
return Array.from(seenPath);
}
function findPathRecur(board, point, seenPath) {
let row = point[0],
column = point[1];
// Base Case
if (!isValidPathPoint(board, point, seenPath)) {
return false;
}
if (board[row][column] === EXIT) {
seenPath.add(point.toString());
return true;
}
// console.log("Curr -", point, ", Seen -", Array.from(seenPath));
seenPath.add(point.toString());
let leftColumn = [row, column - 1],
rightColumn = [row, column + 1],
topRow = [row - 1, column],
bottomRow = [row + 1, column];
if (findPathRecur(board, leftColumn, seenPath)) {
return true;
}
if (findPathRecur(board, rightColumn, seenPath)) {
return true;
}
if (findPathRecur(board, topRow, seenPath)) {
return true;
}
if (findPathRecur(board, bottomRow, seenPath)) {
return true;
}
seenPath.delete(point.toString());
return false;
}
// Check if the point is on valid path
function isValidPathPoint(board, point, seenPath) {
let row = point[0];
let column = point[1];
// Check if point exists
if (board[row] != null && board[row][column] != null) {
// To avoid cycle
if (!seenPath.has(point.toString())) {
// Not a Wall
if (board[row][column] !== WALL) {
return true;
}
}
}
return false;
}
// Test Program
let maze = [
[1, 1, 1],
[0, 0, 1],
[1, 2, 1]
];
let testStart = [
[1,0],
[1,1],
[2,1],
[0,0],
[5,5]
];
testStart.forEach(function(start, i) {
console.log("Test Case:",i);
console.log("\tStart -", start, "Path -", findPath(maze, start));
})
来源:https://stackoverflow.com/questions/20187547/recursive-algorithm-for-2d-maze