我看过每个帖子都有这个问题,每个指南,每个算法,我仍然无法找到问题的答案。奇怪的是,它并没有引起任何问题。错误,但对于每个迷宫,它说它无法解决,并将开始标记为死胡同。
我盯着我的代码几个小时,我无法弄清楚我做错了什么! 我的代码:
(其他非重要的类 - MazeSymbol =包含符号名称及其字符串的枚举,Position =行/列类,Coordinate =包含MazeSymbol和位置的类))
Maze.java:
private Coordinate[][] map;
private Position start;
private Position goal;
private ArrayList<Coordinate> solutionPath;
boolean solveable;
public Maze(Coordinate[][] map, Position start, Position goal){
this.start=start;
this.map=map;
this.goal=goal;
this.solutionPath=new ArrayList<>();
this.solveable = solveMaze(Coordinate.fromMaze(start, this)); //fromMaze takes a position and finds it's symbol.
}
public boolean isSolveable(){
return solveable;
}
private boolean solveMaze(Coordinate c){
System.out.println("Solving - "+c.getPosition().row+","+c.getPosition().column);
if(!c.getPosition().isOnMaze(this)){//Checks if it is between the bounds of the maze (larger than 0 and smaller than length both for X and Y)
System.out.println(c.getPosition().row+","+c.getPosition().column+"Isnt on maze! ");
return false;
}
if(c.getPosition().equals(goal)){
System.out.println(c.getPosition().row+","+c.getPosition().column+"Is goal!");
return true;
}
if(!c.getSymbol().equals(MazeSymbol.OPEN)){//If it isnt an open path - walked/dead end/wall
System.out.println(+c.getPosition().row+","+c.getPosition().column+" isn't open!(it's "+c.getSymbol()+")");
return false;
}
map[c.getPosition().getRow()][c.getPosition().getColumn()] = new Coordinate(c.getPosition(), MazeSymbol.PATH);//Replace the open path sign with a walked path sign
solutionPath.add(c);//Add the coordinate to the solution path
if(solveMaze(c.setPosition(c.getPosition().positionAbove())))return true;//row-1
if(solveMaze(c.setPosition(c.getPosition().positionLeft())))return true;//column+1
if(solveMaze(c.setPosition(c.getPosition().positionBelow())))return true;//row+1
if(solveMaze(c.setPosition(c.getPosition().positionRight())))return true;//column-1
map[c.getPosition().getRow()][c.getPosition().getColumn()] = c.setSymbol(MazeSymbol.DEAD_END);//If none was the path, mark it as a dead end
return false;
}
请帮忙!当我插入这个非常简单的迷宫时:
{&#34; O&#34;&#34; W&#34;&#34; W&#34;},
{&#34; O&#34;&#34; O&#34;&#34; W&#34;},
{&#34; W&#34;&#34; O&#34;&#34; O&#34;}
它表示无法解决,输出:
XWW
OOW
WOO
提前致谢!
编辑:更改了这一行
map[c.getPosition().getRow()][c.getPosition().getColumn()] = new Coordinate(c.getPosition(), MazeSymbol.PATH);
现在它根本不起作用,它只是在2行中产生StackOverflowError然后在第3行中反复出现:
System.out.println("Solving - "+c.getPosition().row+","+c.getPosition().column);
if(solveMaze(c.setPosition(c.getPosition().positionAbove())))return true;
if(solveMaze(c.setPosition(c.getPosition().positionRight())))return true;
答案 0 :(得分:0)
我在这里猜测,因为您没有给我们Coordinate
的确切代码,但假设所有set
操作实际上都在Coordinate
实例中设置了信息,问题是您在此行中更改了c
的符号:
map[c.getPosition().getRow()][c.getPosition().getColumn()] = c.setSymbol(MazeSymbol.PATH);//Replace the open path sign with a walked path sign
现在,您的c
被标记为PATH
而不是OPEN
。然后你做一个递归调用。让我们说它到了下面的方向,这是它应该看到它是开放的。您设置c
的位置,但其值仍为PATH
。然后,在递归步骤内,它到达
if(!c.getSymbol().equals(MazeSymbol.OPEN)){//If it isnt an open path - walked/dead end/wall
System.out.println(+c.getPosition().row+","+c.getPosition().column+" isn't open!(it's "+c.getSymbol()+")");
return false;
}
当然,价值不是OPEN
。因此,该位置以及原始位置周围的所有其他位置都失败了。
您需要在新位置更新实际地图中c
的值,而不是这样做。
修改强>
我看了你的问题编辑。你做了什么确实阻止了程序走向死胡同,但实际上并没有解决问题。你看,现在发生的是你更新地图中的位置,但是当你调用递归版本时,坐标保持OPEN
的值(或者开头的任何值)。
递归步骤会发生什么?让我们忽略不在地图内的方向。它到了
if(!c.getSymbol().equals(MazeSymbol.OPEN)){//If it isnt an open path - walked/dead end/wall
System.out.println(+c.getPosition().row+","+c.getPosition().column+" isn't open!(it's "+c.getSymbol()+")");
return false;
}
但无论地图中该坐标的实际内容如何,c
的值仍为OPEN
。所以它不会进入这个if
块。它认为它处于开放状态。所以很高兴一次又一次地进入递归步骤。它将转到上面的位置,并且无论地图显示它是P
,都会认为它处于打开位置,然后再次递归,返回到下面的位置,依此类推,依此类推。
正如我上面所说,你要做的是从地图的新位置更新c的值。基本上,你永远不会从地图上读书。您永远不会检查地图中的任何位置是墙,路径还是打开。您只需查看c
,c
未从地图更新,因此它不会为您提供所需的信息。
答案 1 :(得分:0)
我建议solveMaze应该使用Position而不是Coordinate,而迷宫可能只是MazeSymbol [] []。
事实上,我根本看不到Coordinate类的用途 - 它只是通过存储另一个MazeSymbol实例来增加混乱,这可能与全局地图不同。我认为这是问题@RealSkeptic强调的建议:
从地图的新位置
更新c的值
我只是更进一步,根本不打算使用Coordinate类。
这里的关键概念是当你进行尝试时,你会更新全局状态(迷宫图和解决方案路径);当你从那次尝试中退出时,你可以逆转这些变化。
然后solveMaze的递归部分变为:
private boolean solveMaze(Position p){
if(!p.isOnMaze(this)) {
return false;
}
if(p.equals(goal)) {
return true;
}
if(!map[p.getRow()][p.getColumn()].equals(MazeSymbol.OPEN)) { // See NOTE 1
return false;
}
map[p.getRow()][p.getColumn()] = MazeSymbol.PATH;
solutionPath.add(p);
if(solveMaze(p.positionAbove())) return true; // See NOTE 2
if(solveMaze(p.positionLeft())) return true;
if(solveMaze(p.positionBelow())) return true;
if(solveMaze(p.positionRight())) return true;
solutionPath.remove(solutionPath.size() - 1); // See NOTE 3
map[p.getRow()][p.getColumn()] = MazeSymbol.DEAD_END;
return false;
}
注1:这将检查实际迷宫中的符号,而不是通过堆栈传递的临时坐标中的符号。
注2:我假设positionAbove / Left ...方法都返回一个新的位置实例,不修改传递的实例;他们可能会这样做,但如果没有代码,我无法确定。
注意3:您需要从解决方案路径中删除无效尝试。
免责声明:没有编译/运行任何此类内容,只需在此输入,因此可能包含拼写错误等。
HTH