簡體   English   中英

在迷宮上打印PacMan步驟,廣度優先搜索-Java

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM