[英]Printing PacMan steps on maze, Breadth First Search - Java
我正在嘗試創建一種沒有鬼影的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 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;
}
問題是,對於真正的BFS,您必須為隊列中的每個元素保存迷宮的整個狀態。 其中包括整個地圖,訪問過的節點集,尤其是未食用盒子的數量和位置。 這是因為BFS中沒有“回溯”的概念,因此您必須基本上創建迷宮的多個狀態。
替代方法是使用DFS。 這樣,您可以在每次遞歸調用之前更新迷宮的狀態,然后在從方法返回之前還原狀態。 這樣,您只能保留一個迷宮狀態的副本。 當然,要獲得DFS中最短的路徑,您將必須嘗試所有可能的路徑,其中可能有很多。 另外,如果迷宮中包含循環路徑,則還必須避免重復循環。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.