Java基于深度優(yōu)先遍歷的隨機(jī)迷宮生成算法
這兩天因?yàn)橐鲆粋€隨機(jī)的地圖生成系統(tǒng),所以一直在研究隨機(jī)迷宮生成算法,好吧,算是有一點(diǎn)小小的成果。
隨機(jī)迷宮生成我自己的理解簡而言之分為以下幾步:
1、建立一張地圖,我用的二維數(shù)組表示,地圖上全是障礙物。然后再創(chuàng)建一個用來表示每個格子是否被訪問過的二維數(shù)組。再創(chuàng)建一個用來表示路徑的棧結(jié)構(gòu)。
2、隨機(jī)選擇地圖上的一點(diǎn),呃為了方便我初始點(diǎn)直接取的是左上角即坐標(biāo)表示為0,0的格子。終點(diǎn)的話因?yàn)椴簧婕暗浇换ゾ蜁簳r沒有。
3、查找當(dāng)前格子的鄰接格(注意,這里的鄰接格子都是還未被訪問的,下面的代碼里有寫)。隨機(jī)選擇一個鄰接格子為下一格,當(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é)點(diǎn)
Node exit = new Node(len - 1, wid - 1); //出口,其實(shí)現(xiàn)在也沒什么用,因?yà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)]; //隨機(jī)選取一個鄰接格
int x = next.x;
int y = next.y;
//如果該節(jié)點(diǎn)被訪問過,則回到上一步繼續(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é)點(diǎn)是否都被訪問
* @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ù)完成情況,比如,代碼覆蓋率必須達(dá)到80%或 90%。下面我們就來詳細(xì)學(xué)習(xí)下java單元測試吧2019-06-06
Java for循環(huán)常見優(yōu)化方法案例詳解
這篇文章主要介紹了Java for循環(huán)常見優(yōu)化方法案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
SpringBoot項(xiàng)目啟動報錯踩坑實(shí)戰(zhàn)記錄
這篇文章主要給大家介紹了關(guān)于SpringBoot項(xiàng)目啟動報錯踩坑的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2023-02-02
SpringCloud?Gateway詳細(xì)分析實(shí)現(xiàn)負(fù)載均衡與熔斷和限流
這篇文章主要介紹了SpringCloud?Gateway實(shí)現(xiàn)路由轉(zhuǎn)發(fā),負(fù)載均衡,熔斷和限流,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07
spring+hibernate 兩種整合方式配置文件的方法
本篇文章主要介紹了spring+hibernate 兩種整合方式配置文件的方法,主要有兩種方式 1、注解方式 2、xml方式實(shí)現(xiàn),有興趣的可以了解一下。2017-04-04
Java中Dijkstra算法求解最短路徑的實(shí)現(xiàn)
Dijkstra算法是一種解決最短路徑問題的常用算法,本文主要介紹了Java中Dijkstra算法求解最短路徑的實(shí)現(xiàn),具有一定的參考價值,感興趣的可以了解一下2023-09-09
java為什么使用BlockingQueue解決競態(tài)條件問題面試精講
這篇文章主要為大家介紹了java為什么使用BlockingQueue解決競態(tài)條件問題面試精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10
Java Elastic Job動態(tài)添加任務(wù)實(shí)現(xiàn)過程解析
這篇文章主要介紹了Java Elastic Job動態(tài)添加任務(wù)實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-08-08

