问题描述
我编写了一种方法,该方法可以通过堆栈和递归来解决给定的文本编辑器迷宫,并且可以解决迷宫问题。但是,我的问题是,当给定的迷宫无法解决时(由于迷宫的壁而实际上无法解决),就好像我的基本情况已被跳过并且没有返回假。这是代码
private boolean findpath(MazeLocation cur,MazeLocation finish) {
int row = cur.row;
int col = cur.col;
mazetoSolve.setChar(row,col,'o');
fileWriter.println("\n"+mazetoSolve.toString());
char strX = 'X';
char strH = 'H';
// First,we need to scan the 4 directions around current location to see where to go
MazeLocation up = new MazeLocation(row-1,col);
MazeLocation down = new MazeLocation(row+1,col);
MazeLocation right = new MazeLocation(row,col+1);
MazeLocation left = new MazeLocation(row,col-1);
// BASE CASE - WHEN WE'VE REACHED FINISH COORDINATES
if(cur.row == finish.row && cur.col == finish.col){
return true;
}
// SECOND BASE CASE - IF MAZE ISNT SOLVABLE
if (path.isEmpty() == true){ // if the path is empty,then there is no solution.
return false;
}
// Check if we can go up
if(up.getRow() >= 0){
if(mazetoSolve.getChar(up.getRow(),up.getCol()) == ' '){
row = up.getRow();
col = up.getCol();
MazeLocation newCur = new MazeLocation(row,col);
path.push(newCur);
return findpath(newCur,finish);
}
}
// Check if we can go down
if(down.getRow() < mazetoSolve.getRows()){
if(mazetoSolve.getChar(down.getRow(),down.getCol()) == ' '){
row = down.getRow();
col = down.getCol();
MazeLocation newCur = new MazeLocation(row,finish);
}
}
// Check if we can go right
if(right.getCol() < mazetoSolve.getCols()){
if(mazetoSolve.getChar(right.getRow(),right.getCol()) == ' '){
row = right.getRow();
col = right.getCol();
MazeLocation newCur = new MazeLocation(row,finish);
}
}
// Check if we can go left
if(left.getCol() >= 0){
if(mazetoSolve.getChar(left.getRow(),left.getCol()) == ' '){
row = left.getRow();
col = left.getCol();
MazeLocation newCur = new MazeLocation(row,finish);
}
}
// If we cant do any of the above then we need to backtrack by popping the top of stack
// and leaving X's until we can move up,down,left,or right again.
MazeLocation newCur = new MazeLocation(row,col);
path.pop(); // popping the cur where we are putting the x
mazetoSolve.setChar(row,'x'); // putting the x
return findpath(path.top(),finish); // Now we need to return to the position where the stack is Now after the pop
}
如您所见,有两种基本情况。一个返回真-迷宫解决了。另一个返回false-迷宫是无法解决的。我的isEmpty()方法的代码如下:
public boolean isEmpty() {
if(head == null){
return true;
}
return false;
}
通过检查堆栈是否为空返回false。例如,如果迷宫赛跑者撞到墙壁并转身,它将在文本编辑器中留下x,如下所示:
0123456
0HHHHHHH
1ooooxxH
2HHHoHxH
3H oHxH
4H HoHHH
5H Hoooo
6HHHHHHH
迷宫从6,5开始;并以0,1结尾。这是可以解决的。 x代表失败的路线,o代表从头到尾的路径。
HHHHHHH
H
HHH H H
H H H
H HHHHH
H H
HHHHHHH
它将尝试向左移动两次,留下x,然后堆栈弹出,直到没有堆栈并且堆栈顶部指向null为止。但是我的基本案例代码被跳过了,它应该在尝试弹出空栈之前测试栈是否为空,如果是,则返回false。但事实并非如此。有什么帮助吗?
解决方法
首先,让我们先了解问题陈述。我们试图在这里使用深度优先的方法找到从源头到目标的可能路径。
该算法存在一个主要缺陷,无处不在
// Check if we can go up
if(up.getRow() >= 0){
if(mazeToSolve.getChar(up.getRow(),up.getCol()) == ' '){
row = up.getRow();
col = up.getCol();
MazeLocation newCur = new MazeLocation(row,col);
path.push(newCur);
return findPath(newCur,finish);
}
}
// Check if we can go down
if(down.getRow() < mazeToSolve.getRows()){
if(mazeToSolve.getChar(down.getRow(),down.getCol()) == ' '){
row = down.getRow();
col = down.getCol();
MazeLocation newCur = new MazeLocation(row,finish);
}
}
考虑我们当前在点(2,2)并可以选择在4个方向之一上移动,即(1,2),(3,2),(1,3),(2,1)
根据您的逻辑。我们首先向上移动(1,2)
可能有两种可能性。
- 您会找到一条从这一点开始的路径(返回true)
- 您找不到路径,想继续搜索其他三个选项。 (返回假)
如果路径导致失败,您的代码当前将不再探索其他选项 由于返回语句
return findPath(newCur,finish);
这个问题归结为所有操作完成之前方法的过早退出。
必须从当前仅在一种情况下调用的方法的任何return语句之前调用以下堆栈清理
// If we cant do any of the above then we need to backtrack by popping the top of stack
// and leaving X's until we can move up,down,left,or right again.
path.pop(); // popping the cur where we are putting the x
我仍然完全不了解显式堆栈的用法。递归解决了您尝试使用堆栈解决的类似问题。但是, 我想在以下几方面提出改进建议。
// Check if we can go up
if(up.getRow() >= 0){
if(mazeToSolve.getChar(up.getRow(),col);
path.push(newCur);
boolean val = findPath(newCur,finish);
if(val){
path.pop();
return true;
}
}
}