我正在尝试创建某种没有鬼影的PacMan模拟,它以6x10的矩阵表示。我已经实现了BFS的一个变体,我在递归调用两个被搜索节点之间的算法,它给了我满意的结果。然而,我真正想做的是在每次PacMan运动之后打印迷宫的状态,其中PacMan用“2”表示,方框用“3”表示,墙用“1”表示,自由方式用“0”表示。我试图将每个节点的符号更改为“2”,对于每个新移动,然后将其父节点符号更改为“0”,但是这不能按预期工作,并且它给了我一些奇怪的结果。
我想我知道问题在哪里,虽然我还没有设法解决它。因此,对于每个被探索的节点,我将它放入一个列表中(可以更高效地完成它,这只是第一次运行),问题是它不会访问已经访问过的节点,所以它无法打印PacMan运动的每一步。我已经尝试在检查之前更改节点标志,如果它们已经被探索过,尽管它不能很好地工作。
我想这听起来相当令人困惑,所以我会尝试绘制一些我希望它看起来的步骤。
这是一个起始迷宫:
1 1 1 1 1 1 1 1 1 1
2 0 0 3 1 0 0 0 3 1
1 3 1 1 1 3 1 1 0 1
1 0 1 0 3 0 1 1 3 1
1 3 0 3 1 3 0 1 0 1
1 1 1 1 1 1 0 3 0 1
这就是解决方案的外观:
1 1 1 1 1 1 1 1 1 1
0 0 0 0 1 0 0 0 0 1
1 0 1 1 1 2 1 1 0 1
1 0 1 0 0 0 1 1 0 1
1 0 0 0 1 0 0 1 0 1
1 1 1 1 1 1 0 0 0 1
现在,我希望为pacman所采取的每一步打印一个新的迷宫:
1 1 1 1 1 1 1 1 1 1 /////// 1 1 1 1 1 1 1 1 1 /////// 1 1 1 1 1 1 1 1 1 1
0 2 0 3 1 0 0 0 3 1 /////// 0 0 2 3 1 0 0 0 3 1 /////// 0 0 0 2 1 0 0 0 3 1
1 3 1 1 1 3 1 1 0 1 /////// 1 3 1 1 1 3 1 1 0 1 /////// 1 3 1 1 1 3 1 1 0 1
1 0 1 0 3 0 1 1 3 1 ///////。
1 3 0 3 1 3 0 1 0 1 ///////。
1 1 1 1 1 1 0 3 0 1 ///////
/////////
1 1 1 1 1 1 1 1 1 1
0 0 2 0 1 0 0 0 3 1
1 3 1 1 1 3 1 1 0 1
等等,抱歉这些令人困惑的图片,我只写了前三行。
这是函数的代码和所有相关函数,以及完整源代码的链接。我也做了一些评论,并且我已经尝试了最后一件事。任何建议都可以。谢谢。
源代码:http://www.speedyshare.com/DkXgQ/BreadthFirstSearch.rar
public static boolean breadthFirstSearch(Node root, Node[][] mazeGrid, int boxCounter) {
root.setSign("0");
toExplore.add(root);
int[] x_coord = { 0, 1, 0, -1};
int[] y_coord = {1, 0, -1, 0 };
while(!toExplore.isEmpty()) {
Node node = toExplore.poll();
explored.add(node);
//for moving!!!!!
/*if(node.getParent() != null) {
node.getParent().setSign("0");
}
node.setSign("2");*/
for(int i = 0; i < 4; i++) {
//new coordinates
int x = node.getX_coord() + x_coord[i];
int y = node.getY_coord() + y_coord[i];
if(x >= 0 && y >=0 && x < 6 && y < 10) {
Node child = maze[x][y];
//show moving steps!!!!!
/*System.out.println("\nStep : \n");
for(int xx = 0; xx < 6; xx++) {
for(int j = 0; j < 10; j++) {
System.out.print(maze[xx][j].getSign() + " ");
}
System.out.print("\n");
}*/
//is current node explored?
if(!isExplored(child) && !child.getSign().equals("1")) {
//save parent for the shortest path between root and node being searched for
child.setParent(node);
//have we found a box?
if(child.getSign().equals("3")) {
System.out.println("Node number " + boxCounter + " has been found : " +
child.getX_coord() + " , " + child.getY_coord());
//counter for rest of the existing boxes
boxCounter--;
Node temp = child;
printPath(temp);
//this is used for path printing between two nodes, and not from the main root and last node being found
temp.setParent(null);
//just jumping from box to box, so I can print where the last position on the maze is
child.setSign("2");
if(boxCounter != 0) {
//if there are more boxes on the maze, recursion
breadthFirstSearch(child, mazeGrid, boxCounter);
}
return true;
}
if(child.getSign().equals("0")) {
//new node to explore
toExplore.add(child);
}
}
}
}
}
System.out.println("Node not found!");
return false;
}
public static void printPath(Node child) {
while(child.getParent() != null) {
path.add(0, child);
child = child.getParent();
}
System.out.println("Shortest path : ");
for(Node n: path) {
System.out.println(n.getX_coord() + " - " + n.getY_coord());
}
path.clear();
}
public static boolean isExplored(Node node) {
for(Node n : explored) {
if(n.getX_coord() == node.getX_coord() && n.getY_coord() == node.getY_coord()) {
return true;
}
}
return false;
}
答案 0 :(得分:2)
问题在于,对于真正的BFS,您必须为队列中的每个元素保存迷宫的整个状态。这包括整个地图,一组访问过的节点,尤其是未吃过的盒子的数量和位置。这是因为在BFS中没有“回溯”的概念,所以你必须基本上创建迷宫的多个状态。
另一种方法是使用DFS。这样,您可以在每次递归调用之前更新迷宫的状态,然后在从方法返回之前恢复状态。这样,您只能保留一个迷宫状态的副本。当然,要获得DFS中的最短路径,您必须尝试所有可能的路径,其中可能有很多路径。如果您的迷宫包含循环路径,您还必须避免重复循环。