代碼地址以下:
http://www.demodashi.com/demo/14547.htmlhtml
使用深度優先算法求解迷宮路徑,使用Java實現求解過程的可視化,可單步運行,形象直觀。java
紅色格子爲迷宮終點,迷宮可放大縮小,爲了錄屏選擇了較小的尺寸,有多種不一樣難度的迷宮能夠加載。node
文件中有兩個運行腳本,Windows下直接雙擊win運行.bat
便可,linux和Mac運行sh文件中的命令便可,喜歡用IDE的也可自行建立項目。
運行項目後,點擊菜單欄左上角的Map
加載迷宮地圖, 點擊右下角的Run
開始解迷宮,Step
可單步運行,可經過速度進度條調節速度。linux
Maze ├── classes # 存放編譯生成的class文件 ├── lib.jar # 打包好的gui庫 ├── map # 迷宮地圖文件 │ ├── EasyMaze.txt │ ├── FinalMaze01.txt │ ├── FinalMaze02.txt │ ├── FinalMaze03.txt │ ├── FinalMaze04.txt │ └── FinalMaze05.txt ├── src │ ├── MazeBug.java │ └── MazeBugRunner.java ├── linux運行.sh # 運行腳本 └── win運行.bat # 運行腳本
使用深度優先算法
,每一個格子下一步都有上下左右4種走法,可是這4種走法並非都是合法的,好比有些格子有障礙物,有些格式在邊界以外,去掉這些剩下的纔是合法的走法。算法
深度優先算法的思想就是:ide
算法優化
:上面的方法選擇下一步走的方向是隨機的,或者按照上下左右的順序選擇。可是不少迷宮都有偏向性,好比若是有右偏向性,那麼每次都優先往右走能夠更快走出迷宮。因此在實現的時候,記錄每一個方向走的次數,每往一個方向走一步就加1,若是回退就該方向減1,每次走都優先走次數最多的方向,當迷宮有偏向性時,該方法效率更高。優化
以項目中的迷宮爲例,大部分狀況下偏向性所需步數更少。ui
普通方法: 534 1175 350 973 1052 偏向性: 552 761 330 175 420
/* * 節點:存儲方向和該方向所走的次數 * 往一個方向前進則加1,後退則減1 */ class Node { private int dir; // 方向,角度值 private int ct; // 該方向所走次數 public Node(int initdir, int initct) { dir = initdir; ct = initct; } public int getDir() { return dir; } public int getCt() { return ct; } public void setCt(int deta) { ct += deta; } } // 深度優先算法解迷宮,而且以小甲蟲的形式呈現 public class MazeBug extends Bug { private Location next; // 下一步要走的格子 private Integer stepCount = 0; // 所走的步數 private boolean isEnd = false; // 是否到達迷宮出口 private boolean hasShown = false; // 是否顯示告終束信息 private Stack<Location> path = new Stack<>(); // 存儲走過的路徑 private ArrayList<Node> arr = new ArrayList<>(); public MazeBug() { setColor(Color.GREEN); arr.add(new Node(0, 0)); arr.add(new Node(90, 0)); arr.add(new Node(270, 0)); arr.add(new Node(180, 0)); } // 週期性執行 public void act() { boolean willMove = canMove(); // 是否還能繼續移動 if (isEnd) { // 是否結束 if (!hasShown) { // 是否顯示結束消息 String msg = stepCount.toString() + " steps"; JOptionPane.showMessageDialog(null, msg); hasShown = true; } return; } else if (willMove) { // 向前移動一個,步數加1 move(); ++stepCount; } else { // 不能移動,後退一步,將該方向的計數器減1 Grid<Actor> grid = getGrid(); Location loc = this.getLocation(); Location top = path.pop(); ++stepCount; grid.remove(top); this.setDirection(loc.getDirectionToward(top)); this.moveTo(top); // 在走過的死路留下一朵白花 Flower flower = new Flower(Color.WHITE); flower.putSelfInGrid(getGrid(), loc); // 方向計數器減1 int dir = 180 + ((getDirection() / 90) % 2) * 180 - getDirection(); for (Node node : arr) if (node.getDir() == dir) { node.setCt(-1); return; } } } // 找出和當前位置相鄰的、合法的而且從未走過的格子 public Location getValid(Location loc) { Grid<Actor> gr = getGrid(); if (gr == null) return null; // 將每一個方向走過的次數從大到小排序,下一步優先選次數多的方向走 Location adjLocation; arr.sort(new Comparator<Node>() { @Override public int compare(Node a, Node b) { return (a.getCt() < b.getCt()) ? 1 : -1; } }); for (Node node : arr) { adjLocation = this.getLocation().getAdjacentLocation(node.getDir()); if (gr.isValid(adjLocation) && (gr.get(adjLocation) == null || gr.get(adjLocation).getColor().equals(Color.RED))) { node.setCt(1); return adjLocation; } } return null; } // 判斷當前位置是否能夠繼續移動 public boolean canMove() { Grid<Actor> gr = getGrid(); Actor adj; Location loc = this.getValid(this.getLocation()); if (loc != null) { adj = gr.get(loc); next = loc; isEnd = adj != null && adj.getColor().equals(Color.RED); return true; } return false; } // 將甲蟲的方向轉向下一格,往前移動一步,將原來的位置壓棧,並放置一朵綠花,表示走過的路徑 public void move() { Grid<Actor> gr = getGrid(); if (gr == null) return; Location loc = this.getLocation(); path.push(loc); this.setDirection(loc.getDirectionToward(next)); this.moveTo(next); Flower flower = new Flower(this.getColor()); flower.putSelfInGrid(gr, loc); } }
跟算法無關的代碼,好比GUI方面的都打包成lib.jar
了,若是想要本身更改能夠自行解壓。Java實現可視化迷宮this
代碼地址以下:
http://www.demodashi.com/demo/14547.htmlcode
注:本文著做權歸做者,由demo大師代發,拒絕轉載,轉載須要做者受權