我正在尝试使用Stack(深度优先搜索)来解决迷宫问题。除了主要问题之外,我遇到了一些问题,即当我的堆栈变空时,我正在获得无限循环。我很清楚我需要做什么我只是在将它应用到我的代码时遇到了麻烦。
我正在使用此算法来解决迷宫:
1.创建一个空堆栈
2.在数组中搜索起始位置。
3.将起点放在堆栈上
4.从堆栈中删除一个点
5.试着看这一点是否结束(如果是,结束循环)
6.否则,将迷宫中的斑点标记为已评估以显示路径
7.检查邻近的迷宫中的斑点 当前位置(上,下,左,右)。
8.如果它们不是墙,并且尚未进行评估,则将这些点添加到堆栈中作为其他要评估的位置。
使用辅助方法解决方法(大多数错误在solveDFS()中)
//Tries going up,down,left,or right from current location and
//marks path if valid. The algorithm should finish when reaching
//the finish spot
public static boolean solveDFS( char [][] maze ){
LinkedStack stack = new LinkedStack();
Point startLoc = findPoint(maze,'s');
Point finishLoc = findPoint(maze, 'f');
stack.push(startLoc);
Point[] neighborSpots = getNeighborSpots(startLoc);
boolean test = true;
while ( test ){
stack.pop();
if(stack.peek().equals(finishLoc)){
printMaze(maze);
test = false;
return true;
}else{
for( Point evaluate : neighborSpots ){
if( validSpot( stack, maze ) ){
placeMarker( stack, maze );
if( stack.peek().equals(evaluate)){
return true;
}
removeMarker( stack, maze);
}
}
}
}
return false;
}
//Returns true of coordinates of free spot is valid or finish spot
//Should not be off edge of maze
private static boolean validSpot( LinkedStack spot, char [][] maze ){
if ( spot.peek().x < 0 || spot.peek().x >= maze.length ||
spot.peek().y < 0 || spot.peek().y >= maze[spot.peek().x].length ) {
return false;
}
return ( maze[spot.peek().x][spot.peek().y] == ' ' || maze[spot.peek().x][spot.peek().y] == 'f' );
}
//Searches the array for a point
private static Point findPoint( char [][] maze, char c ) {
for ( int i = 0; i < maze.length; i++ ) {
for ( int j = 0; j < maze[i].length; j++ ) {
if ( maze[i][j] == c ) {
return new Point(i, j);
}
}
}
return null;
}
//returns an array containing coordinates of neighbor spots
private static Point[] getNeighborSpots( Point spot ) {
Point[] neighborSpots = new Point[4];
neighborSpots[0] = new Point(spot.x + 1, spot.y);
neighborSpots[1] = new Point(spot.x, spot.y + 1);
neighborSpots[2] = new Point(spot.x - 1, spot.y);
neighborSpots[3] = new Point(spot.x, spot.y - 1);
return neighborSpots;
}
//Marks the path by adding a '.'
private static void placeMarker( LinkedStack spot, char [][] maze ){
maze[spot.peek().x][spot.peek().y] = '.';
}
//Removes marker from path by adding a blank space
private static void removeMarker ( LinkedStack spot, char [][] maze ) {
maze[spot.peek().x][spot.peek().x] = ' ';
}
答案 0 :(得分:1)
如果找到路径,你的循环会将循环变量(test
)更改为false(但效果无关紧要,因为你直接从方法返回。
在其他情况下,你的循环永远不会改变循环变量。如果所有路径都已完成,则将test
设置为false,并且没有一个成功。
或者只是不测试布尔变量,而是在循环表达式(while (!stack.isEmpty())
)中测试堆栈的空白。
答案 1 :(得分:0)
您无法从空白堆栈的顶部弹出或查看。因此,堆栈的实现需要有一个谓词(boolean isEmpty()
方法)来检查堆栈是否为空。从堆栈中查看或弹出的代码必须使用此谓词并将空堆栈作为特殊情况处理,或者必须以保证它永远不会操作空堆栈的方式编写。后者在实践中更难,更罕见。
但是如果为空堆栈调用 ,那么堆栈的pop或peep方法应该怎么做?也就是说,如果该方法被错误地调用了?该方法应通过抛出合适的未经检查的异常来发出错误信号。这将使调试错误变得更加容易。堆栈是否为空是堆栈状态信息的一部分。因此堆栈处于对pop或peek方法无效的状态。因此IllegalStateException
最合适。
答案 2 :(得分:0)
3.将起点放在堆栈上
4.从堆栈中删除一个点
你确定这是一个好主意吗?
答案 3 :(得分:0)
我试图纠正代码中的逻辑错误。以下代码应该可以使用,但不会根据需要放置标记:
public static boolean solveDFS( char [][] maze ){
LinkedStack stack = new LinkedStack();
Point startLoc = findPoint(maze,'s');
Point finishLoc = findPoint(maze, 'f');
stack.push(startLoc);
while (!stack.isEmpty()) {
Point curr = stack.pop();
if(curr.equals(finishLoc)) {
printMaze(maze);
return true;
} else {
Point[] neighborSpots = getNeighborSpots(curr);
for(Point evaluate: neighborSpots) {
if(validSpot(stack, maze)) {
placeMarker(stack, maze);
stack.push(evaluate);
removeMarker(stack, maze);
}
}
}
}
return false;
}