Java基于深度優(yōu)先遍歷的隨機迷宮生成算法
這兩天因為要做一個隨機的地圖生成系統(tǒng),所以一直在研究隨機迷宮生成算法,好吧,算是有一點小小的成果。
隨機迷宮生成我自己的理解簡而言之分為以下幾步:
1、建立一張地圖,我用的二維數(shù)組表示,地圖上全是障礙物。然后再創(chuàng)建一個用來表示每個格子是否被訪問過的二維數(shù)組。再創(chuàng)建一個用來表示路徑的棧結(jié)構(gòu)。
2、隨機選擇地圖上的一點,呃為了方便我初始點直接取的是左上角即坐標(biāo)表示為0,0的格子。終點的話因為不涉及到交互就暫時沒有。
3、查找當(dāng)前格子的鄰接格(注意,這里的鄰接格子都是還未被訪問的,下面的代碼里有寫)。隨機選擇一個鄰接格子為下一格,當(dāng)前格移動到下一格,標(biāo)記當(dāng)前格為已訪問,將當(dāng)前格壓入路徑棧中。一直重復(fù)第三步操作。
4、在第三步操作中,如果當(dāng)前格子不存在可訪問的鄰接格,則將棧頂?shù)脑貜棾?,即退回上一步操作,如果棧為空,則結(jié)束程序,打印結(jié)果。
附上結(jié)果和源碼,這是基于JAVA控制臺來寫的。
package maze; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.Stack; public class Maze { int len = 11; //迷宮長度 int wid = 11; //迷宮寬度 char wall = '■'; //代表墻 char blank = '○'; //代表空地 char[][] maze; //迷宮 boolean[][] visit; //用來標(biāo)記某一格是否被訪問過 Node start = new Node(0,0); //開始節(jié)點 Node exit = new Node(len - 1, wid - 1); //出口,其實現(xiàn)在也沒什么用,因為沒有交互只是生成了一個迷宮而已 Node cur; //當(dāng)前格 Node next; //下一格 Stack<Node> path = new Stack<Node>(); //表示路徑的棧 int[][] adj = { {0,2},{0,-2},{2,0},{-2,0} }; //用來計算鄰接格 /** * 迷宮的格子類 * @author Yan */ class Node { int x,y; public Node(){} public Node(int x, int y) { this.x = x; this.y = y; } public String toString() { return "Node [x=" + x + ", y=" + y + "]"; } } /** * 初始化,初始化迷宮參數(shù) */ void init() { maze = new char[len][wid]; visit = new boolean[len][wid]; for(int i = 0; i < len; i++) { for(int j = 0; j < wid; j++) { maze[i][j] = wall; visit[i][j] = false; } } visit[start.x][start.y] = true; maze[start.x][start.y] = blank; cur = start; //將當(dāng)前格標(biāo)記為開始格 } /** * 打印結(jié)果 */ void printMaze() { for(int i = 0; i < len; i++) { for(int j = 0; j < wid; j++) { System.out.print(maze[i][j] + " "); // if(maze[i][j] == '○') // { // System.err.print(maze[i][j] + " "); // } // else // { // System.out.print(maze[i][j] + " "); // } // try { // Thread.sleep(100); // } catch (InterruptedException e) { // e.printStackTrace(); // } } System.out.println(); } System.out.println("=========================================="); } /** * 開始制作迷宮 */ void makeMaze() { path.push(cur); //將當(dāng)前格壓入棧 while(!path.empty()) { Node[] adjs = notVisitedAdj(cur);//尋找未被訪問的鄰接格 if(adjs.length == 0) { cur = path.pop();//如果該格子沒有可訪問的鄰接格,則跳回上一個格子 continue; } next = adjs[new Random().nextInt(adjs.length)]; //隨機選取一個鄰接格 int x = next.x; int y = next.y; //如果該節(jié)點被訪問過,則回到上一步繼續(xù)尋找 if(visit[x][y]) { cur = path.pop(); } else//否則將當(dāng)前格壓入棧,標(biāo)記當(dāng)前格為已訪問,并且在迷宮地圖上移除障礙物 { path.push(next); visit[x][y] = true; maze[x][y] = blank; maze[(cur.x + x) / 2][(cur.y + y) / 2] = blank; //移除當(dāng)前格與下一個之間的墻壁 cur = next;//當(dāng)前格等于下一格 } } } /** * 判斷節(jié)點是否都被訪問 * @param ns * @return */ boolean allVisited(Node[] ns) { for(Node n : ns) { if(!visit[n.x][n.y]) return false; } return true; } /** * 尋找可訪問的鄰接格,這里可以優(yōu)化,不用list * @param node * @return */ Node[] notVisitedAdj(Node node) { List<Node> list = new ArrayList<Node>(); for(int i = 0; i < adj.length; i++) { int x = node.x + adj[i][0]; int y = node.y + adj[i][1]; if( x >= 0 && x < len && y >= 0 && y < wid) { if(!visit[x][y]) list.add(new Node(x,y)); } } Node[] a = new Node[list.size()]; for(int i = 0; i < list.size(); i++) { a[i] = list.get(i); } return a; } /** * 入口方法 * @param args */ public static void main(String[] args) { Maze m = new Maze(); m.init(); m.makeMaze(); m.printMaze(); } }
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接
相關(guān)文章
深入學(xué)習(xí)Java單元測試(Junit+Mock+代碼覆蓋率)
在做單元測試時,代碼覆蓋率常常被拿來作為衡量測試好壞的指標(biāo),甚至,用代碼覆蓋率來考核測試任務(wù)完成情況,比如,代碼覆蓋率必須達到80%或 90%。下面我們就來詳細學(xué)習(xí)下java單元測試吧2019-06-06Java for循環(huán)常見優(yōu)化方法案例詳解
這篇文章主要介紹了Java for循環(huán)常見優(yōu)化方法案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-08-08SpringCloud?Gateway詳細分析實現(xiàn)負載均衡與熔斷和限流
這篇文章主要介紹了SpringCloud?Gateway實現(xiàn)路由轉(zhuǎn)發(fā),負載均衡,熔斷和限流,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07spring+hibernate 兩種整合方式配置文件的方法
本篇文章主要介紹了spring+hibernate 兩種整合方式配置文件的方法,主要有兩種方式 1、注解方式 2、xml方式實現(xiàn),有興趣的可以了解一下。2017-04-04Java中Dijkstra算法求解最短路徑的實現(xiàn)
Dijkstra算法是一種解決最短路徑問題的常用算法,本文主要介紹了Java中Dijkstra算法求解最短路徑的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2023-09-09java為什么使用BlockingQueue解決競態(tài)條件問題面試精講
這篇文章主要為大家介紹了java為什么使用BlockingQueue解決競態(tài)條件問題面試精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-10-10Java Elastic Job動態(tài)添加任務(wù)實現(xiàn)過程解析
這篇文章主要介紹了Java Elastic Job動態(tài)添加任務(wù)實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-08-08