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

 更新时间:2019年02月20日 14:25:38   作者:严洋羽  
今天小编就为大家分享一篇关于Java基于深度优先遍历的随机迷宫生成算法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

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

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

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();
 }
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接

相关文章

  • 深入学习Java单元测试(Junit+Mock+代码覆盖率)

    深入学习Java单元测试(Junit+Mock+代码覆盖率)

    在做单元测试时,代码覆盖率常常被拿来作为衡量测试好坏的指标,甚至,用代码覆盖率来考核测试任务完成情况,比如,代码覆盖率必须达到80%或 90%。下面我们就来详细学习下java单元测试吧
    2019-06-06
  • Java for循环常见优化方法案例详解

    Java for循环常见优化方法案例详解

    这篇文章主要介绍了Java for循环常见优化方法案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • SpringBoot项目启动报错踩坑实战记录

    SpringBoot项目启动报错踩坑实战记录

    这篇文章主要给大家介绍了关于SpringBoot项目启动报错踩坑的相关资料,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2023-02-02
  • java9在interface中定义私有方法详解

    java9在interface中定义私有方法详解

    在本篇内容里小编给大家整理的是一篇关于java9在interface中定义私有方法,有兴趣的朋友们可以学习下。
    2020-10-10
  • SpringCloud Gateway详细分析实现负载均衡与熔断和限流

    SpringCloud Gateway详细分析实现负载均衡与熔断和限流

    这篇文章主要介绍了SpringCloud Gateway实现路由转发,负载均衡,熔断和限流,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • spring+hibernate 两种整合方式配置文件的方法

    spring+hibernate 两种整合方式配置文件的方法

    本篇文章主要介绍了spring+hibernate 两种整合方式配置文件的方法,主要有两种方式 1、注解方式 2、xml方式实现,有兴趣的可以了解一下。
    2017-04-04
  • Java中Dijkstra算法求解最短路径的实现

    Java中Dijkstra算法求解最短路径的实现

    Dijkstra算法是一种解决最短路径问题的常用算法,本文主要介绍了Java中Dijkstra算法求解最短路径的实现,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • Spring通过配置文件管理Bean对象的方法

    Spring通过配置文件管理Bean对象的方法

    这篇文章主要介绍了Spring通过配置文件管理Bean对象的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • java为什么使用BlockingQueue解决竞态条件问题面试精讲

    java为什么使用BlockingQueue解决竞态条件问题面试精讲

    这篇文章主要为大家介绍了java为什么使用BlockingQueue解决竞态条件问题面试精讲,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • Java Elastic Job动态添加任务实现过程解析

    Java Elastic Job动态添加任务实现过程解析

    这篇文章主要介绍了Java Elastic Job动态添加任务实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08

最新评论