我正在开发一个小程序来解决DFS的迷宫问题。但似乎算法在找到它的目标之前就太早停止了。任何人都可以给我一个暗示我做错的事吗?
SO墙是1,3是目标,我用2标记路径。
代码:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Stack;
public class Maze {
private final int size;
private final int[][] maze;
Maze(int[][] maze){
this.size = maze.length;
this.maze = maze;
}
private boolean inBounds(int number){
return number >= 0 && number < this.size;
}
/*
* This one has no information where the end point is so it uses DFS to find a path to the
* the end point. The end point must be marked by a 3.
*
* procedure DFS-iterative(G,v):
* let S be a stack
* S.push(v)
* while S is not empty
* v = S.pop()
* if v is not labeled as discovered:
* label v as discovered
* for all edges from v to w in G.adjacentEdges(v) do
* S.push(w)
*
*
*/
public void solve(Node start){
Stack<Node> stack = new Stack<Node>();
HashSet<Node> visited = new HashSet<Node>();
stack.push(start);
while(!stack.isEmpty()){
Node tmp = stack.pop();
this.maze[tmp.getY()][tmp.getX()] = 2;
if(!visited.contains(tmp)){
visited.add(tmp);
for(Node n : this.getAdjacentEdges(tmp))
stack.push(n);
}
}
}
private List<Node> getAdjacentEdges(Node tmp) {
List<Node> neighbours = new ArrayList<Node>();
if(this.inBounds(tmp.getX()+1)){
if(this.maze[tmp.getY()][tmp.getX()+1] != 1){
neighbours.add(new Node(tmp.getX()+1, tmp.getY()));
}
}
if(this.inBounds(tmp.getX()-1)){
if(this.maze[tmp.getY()][tmp.getX()-1] != 1){
neighbours.add(new Node(tmp.getX()-1, tmp.getY()));
}
}
if(this.inBounds(tmp.getY()+1)){
if(this.maze[tmp.getY()+1][tmp.getX()] != 1){
neighbours.add(new Node(tmp.getX(), tmp.getY()+1));
}
}
if(this.inBounds(tmp.getY()-1)){
if(this.maze[tmp.getY()-1][tmp.getX()] != 1){
neighbours.add(new Node(tmp.getX(), tmp.getY()-1));
}
}
return neighbours;
}
public static void main(String args[]){
int [][] maze =
{ {1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,1,0,1,0,1,0,0,0,0,0,1},
{1,0,1,0,0,0,1,0,1,1,1,0,1},
{1,0,0,0,1,1,1,0,0,0,0,0,1},
{1,0,1,0,0,0,0,0,1,1,1,0,1},
{1,0,1,0,1,1,1,0,1,0,0,0,1},
{1,0,1,0,1,0,0,0,1,1,1,0,1},
{1,0,1,0,1,1,1,0,1,0,1,0,1},
{1,0,0,0,0,0,0,0,0,0,1,3,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1}
};
Maze m = new Maze(maze);
m.solve(new Node(1,1));
for(int i = 0; i < maze.length; i++){
for(int j = 0; j < maze[i].length; j++){
System.out.print(" " + maze[i][j] + " ");
}
System.out.println();
}
}
}
节点类:
public class Node {
private int x;
private int y;
Node(int x, int y){
this.x = x;
this.y = y;
}
int getX(){
return this.x;
}
int getY(){
return this.y;
}
@Override
public int hashCode(){
return this.getX()+this.getY()+31;
}
@Override
public boolean equals(Object obj){
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
Node tmp = (Node) obj;
return tmp.getX() == this.getX() && this.getY() == tmp.getY();
}
@Override
public String toString(){
return "x: " + this.getX() + " y: " + this.getY();
}
}
答案 0 :(得分:1)
您的代码中存在一些错误。我稍微修改了你的代码,现在它可以工作了。
一些重要的观察结果:
1)您的inBounds
方法应用不正确,因为迷宫阵列的尺寸不相等。这就是为什么算法没有达到迷宫中的许多网格的原因。因此,我删除了inBounds
方法,修改了Maze
构造函数以接受这两个维度大小,并添加了两个方法:inBoundsY
和inBoundsX
以分别检查每个维度。
2)我确信,将每个访问过的网格标记在路径中的想法是不正确的。我添加了一个名为prev
的新数组来存储路径中每个网格的前一个网格。然后我更改了您的solve
方法并添加了fillPath
方法,以便将路径中的所有网格填充为2.然后我们可以简单地打印所有迷宫并显示赎回。
新代码如下所示:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Stack;
public class Maze {
private int[][] maze;
// previous grids array
private Node[][] prev;
private int sizeX;
private int sizeY;
private Node lastNode;
Maze(int[][] maze, int sizeY, int sizeX) {
this.maze = maze;
this.sizeY = sizeY;
this.sizeX = sizeX;
prev = new Node[sizeY][sizeX];
}
private boolean inBoundsX(int number){
return number >= 0 && number < sizeX;
}
private boolean inBoundsY(int number){
return number >= 0 && number < sizeY;
}
public void solve(Node start){
Stack<Node> stack = new Stack<>();
HashSet<Node> visited = new HashSet<>();
stack.push(start);
while(!stack.isEmpty()) {
Node tmp = stack.pop();
visited.add(tmp);
if (maze[tmp.getY()][tmp.getX()] == 3) {
lastNode = tmp;
break;
}
for(Node node : this.getAdjacentEdges(tmp)) {
if (!visited.contains(node)) {
stack.push(node);
prev[node.getY()][node.getX()] = tmp;
}
}
}
}
public void fillPath() {
if (lastNode == null) {
System.out.println("No path in maze");
} else {
// assume, that start point and end point are different
for (;;) {
lastNode = prev[lastNode.getY()][lastNode.getX()];
// There's no previous node for start point, so we can break
if (lastNode == null) {
break;
}
maze[lastNode.getY()][lastNode.getX()] = 2;
}
}
}
private List<Node> getAdjacentEdges(Node tmp) {
List<Node> neighbours = new ArrayList<Node>();
if(this.inBoundsX(tmp.getX()+1)){
if(this.maze[tmp.getY()][tmp.getX()+1] != 1){
neighbours.add(new Node(tmp.getX()+1, tmp.getY()));
}
}
if(this.inBoundsX(tmp.getX()-1)){
if(this.maze[tmp.getY()][tmp.getX()-1] != 1){
neighbours.add(new Node(tmp.getX()-1, tmp.getY()));
}
}
if(this.inBoundsY(tmp.getY()+1)){
if(this.maze[tmp.getY()+1][tmp.getX()] != 1){
neighbours.add(new Node(tmp.getX(), tmp.getY()+1));
}
}
if(this.inBoundsY(tmp.getY()-1)){
if(this.maze[tmp.getY()-1][tmp.getX()] != 1){
neighbours.add(new Node(tmp.getX(), tmp.getY()-1));
}
}
return neighbours;
}
public static void main(String args[]){
int [][] maze =
{ {1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,1,0,1,0,1,0,0,0,0,0,1},
{1,0,1,0,0,0,1,0,1,1,1,0,1},
{1,0,0,0,1,1,1,0,0,0,0,0,1},
{1,0,1,0,0,0,0,0,1,1,1,0,1},
{1,0,1,0,1,1,1,0,1,0,0,0,1},
{1,0,1,0,1,0,0,0,1,1,1,0,1},
{1,0,1,0,1,1,1,0,1,0,1,0,1},
{1,0,0,0,0,0,0,0,0,0,1,3,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1}
};
// Create maze with certain dimensions
Maze m = new Maze(maze, 10, 13);
m.solve(new Node(1,1));
m.fillPath();
for(int i = 0; i < maze.length; i++){
for(int j = 0; j < maze[i].length; j++){
System.out.print(" " + maze[i][j] + " ");
}
System.out.println();
}
}
}
结果将是:
1 1 1 1 1 1 1 1 1 1 1 1 1
1 2 1 0 1 0 1 2 2 2 2 2 1
1 2 1 0 0 0 1 2 1 1 1 2 1
1 2 0 0 1 1 1 2 0 0 0 2 1
1 2 1 2 2 2 2 2 1 1 1 2 1
1 2 1 2 1 1 1 0 1 0 0 2 1
1 2 1 2 1 0 0 0 1 1 1 2 1
1 2 1 2 1 1 1 0 1 0 1 2 1
1 2 2 2 0 0 0 0 0 0 1 3 1
1 1 1 1 1 1 1 1 1 1 1 1 1