基于深度优先遍历的随机迷宫算法

       这两天因为要做一个随机的地图生成系统,所以一直在研究随机迷宫生成算法,好吧,算是有一点小小的成果。

随机迷宫生成我自己的理解简而言之分为以下几步:

1、建立一张地图,我用的二维数组表示,地图上全是障碍物。然后再创建一个用来表示每个格子是否被访问过的二维数组。再创建一个用来表示路径的栈结构。

2、随机选择地图上的一点,呃为了方便我初始点直接取的是左上角即坐标表示为0,0的格子。终点的话因为不涉及到交互就暂时没有。

3、查找当前格子的邻接格(注意,这里的邻接格子都是还未被访问的,下面的代码里有写)。随机选择一个邻接格子为下一格,当前格移动到下一格,标记当前格为已访问,将当前格压入路径栈中。一直重复第三步操作。

4、在第三步操作中,如果当前格子不存在可访问的邻接格,则将栈顶的元素弹出,即退回上一步操作,如果栈为空,则结束程序,打印结果。

附上结果和源码,这是基于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; //用来标记某一格是否被访问过
	
	Node start = new Node(0,0); //开始节点
	Node exit = new Node(len - 1, wid - 1); //出口,其实现在也没什么用,因为没有交互只是生成了一个迷宫而已
	Node cur; //当前格
	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 + "]";
		}
		
	}

	/**
	 * 初始化,初始化迷宫参数
	 */
	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; //将当前格标记为开始格
	}
	
	/**
	 * 打印结果
	 */
	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); //将当前格压入栈
		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;
			
			//如果该节点被访问过,则回到上一步继续寻找
			if(visit[x][y])
			{
				cur = path.pop();
			}
			else//否则将当前格压入栈,标记当前格为已访问,并且在迷宫地图上移除障碍物
			{
				path.push(next);
				visit[x][y] = true;
				maze[x][y] = blank;
				maze[(cur.x + x) / 2][(cur.y + y) / 2] = blank; //移除当前格与下一个之间的墙壁
				cur = next;//当前格等于下一格
			}
		}
	}
	
	/**
	 * 判断节点是否都被访问
	 * @param ns
	 * @return
	 */
	boolean allVisited(Node[] ns)
	{
		for(Node n : ns)
		{
			if(!visit[n.x][n.y])
				return false;
		}
		return true;
	}
	
	/**
	 * 寻找可访问的邻接格,这里可以优化,不用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();
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值