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

总结

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

(0)

相关推荐

  • Java实现的数字签名算法RSA完整示例

    本文实例讲述了Java实现的数字签名算法RSA.分享给大家供大家参考,具体如下: 一 背景介绍 数字签名:带有密钥(公钥.私钥)的消息摘要算法. 验证数据完整性.认证数据来源.抗否认. 私钥签名.公钥验证. 常用算法:RSA.DSA.ECDSA 二 RSA介绍 包括MD和SHA两类 三 Java代码实现 package com.imooc.security.rsa2; import java.security.KeyFactory; import java.security.KeyPair; i

  • Java实现二叉树的深度优先遍历和广度优先遍历算法示例

    本文实例讲述了Java实现二叉树的深度优先遍历和广度优先遍历算法.分享给大家供大家参考,具体如下: 1. 分析 二叉树的深度优先遍历的非递归的通用做法是采用栈,广度优先遍历的非递归的通用做法是采用队列. 深度优先遍历:对每一个可能的分支路径深入到不能再深入为止,而且每个结点只能访问一次.要特别注意的是,二叉树的深度优先遍历比较特殊,可以细分为先序遍历.中序遍历.后序遍历.具体说明如下: 先序遍历:对任一子树,先访问根,然后遍历其左子树,最后遍历其右子树. 中序遍历:对任一子树,先遍历其左子树,然

  • java 中模式匹配算法-KMP算法实例详解

    java 中模式匹配算法-KMP算法实例详解 朴素模式匹配算法的最大问题就是太低效了.于是三位前辈发表了一种KMP算法,其中三个字母分别是这三个人名的首字母大写. 简单的说,KMP算法的对于主串的当前位置不回溯.也就是说,如果主串某次比较时,当前下标为i,i之前的字符和子串对应的字符匹配,那么不要再像朴素算法那样将主串的下标回溯,比如主串为"abcababcabcabcabcabc",子串为"abcabx".第一次匹配的时候,主串1,2,3,4,5字符都和子串相应的

  • JAVA实现KMP算法理论和示例代码

    一.理论准备KMP算法为什么比传统的字符串匹配算法快?KMP算法是通过分析模式串,预先计算每个位置发生不匹配的时候,可以省去重新匹配的的字符个数.整理出来发到一个next数组, 然后进行比较,这样可以避免字串的回溯,模式串中部分结果还可以复用,减少了循环次数,提高匹配效率.通俗的说就是KMP算法主要利用模式串某些字符与模式串开头位置的字符一样避免这些位置的重复比较的.例如 主串: abcabcabcabed ,模式串:abcabed.当比较到模式串'e'字符时不同的时候完全没有必要从模式串开始位

  • java短网址服务(TinyURL)生成算法

    前不久做了一个优惠劵的分享功能,其中一个功能就是生成一个优惠劵分享短链接.生成的短链接要求每个链接都是唯一的,并且长度尽可能短.在网上查了一下相关的思路,发现了一个不错的算法.这个算法的思路就是用[a-zA-Z0-9]建立一个长度为62的矩阵,然后把矩阵打乱,再生成一个全局唯一的数字,再把这个数字用矩阵内的元素表示转换成62进制,生成的链接长度最大才11位.所以短链接的生成关键点就变成了如何生成一个全局唯一的数字和实现进制的转换. 1.生成全局唯一的数字 这本质是一个分布式ID的问题.如果简单处

  • Java求质数的几种常用算法分析

    本文实例讲述了Java求质数的几种常用算法.分享给大家供大家参考,具体如下: 1.根据质数的定义求 质数定义:只能被1或者自身整除的自然数(不包括1),称为质数. 利用它的定义可以循环判断该数除以比它小的每个自然数(大于1),如果有能被它整除的,则它就不是质数. 对应代码是: void printPrime(int n){//判断n是否是质数 boolean isPrime=true;//是否是质数的标志 for(int i=n-1;i>1;i-){//n除以每个比n小比1大的自然数 if(n%

  • 如何通过Java代码实现KMP算法

    这篇文章主要介绍了如何通过Java代码实现KMP算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特--莫里斯--普拉特操作(简称KMP算法).KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的.具体实现就是实现一个next()函数, 函数本身包含了模式串的局部匹配信息.时间复

  • Java获得一个数组的指定长度排列组合算法示例

    本文实例讲述了Java获得一个数组的指定长度排列组合算法.分享给大家供大家参考,具体如下: package demo; import java.util.Stack; /** * JAVA获得一个数组的指定长度的排列组合.<br> * * @author JAVA世纪网(java2000.net, laozizhu.com) */ public class TestSequenceAll { public static void main(String[] args) { TestSequen

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

    这两天因为要做一个随机的地图生成系统,所以一直在研究随机迷宫生成算法,好吧,算是有一点小小的成果. 随机迷宫生成我自己的理解简而言之分为以下几步: 1.建立一张地图,我用的二维数组表示,地图上全是障碍物.然后再创建一个用来表示每个格子是否被访问过的二维数组.再创建一个用来表示路径的栈结构. 2.随机选择地图上的一点,呃为了方便我初始点直接取的是左上角即坐标表示为0,0的格子.终点的话因为不涉及到交互就暂时没有. 3.查找当前格子的邻接格(注意,这里的邻接格子都是还未被访问的,下面的代码里有写).

  • 详解Java利用深度优先遍历解决迷宫问题

    目录 什么是深度优先 一个简单的例子 程序实现 什么是深度优先 什么是深度,即向下,深度优先,即向下优先,一口气走到底,走到底发现没路再往回走. 在算法实现上来讲,深度优先可以考虑是递归的代名词,深度优先搜索必然需要使用到递归的思路. 有的人可能会说了,我可以用栈来实现,以迭代的方式,那么问题来了,栈这种数据结构,同学们认为是否也囊括了递归呢?Java语言的方法区本身也是实现在一个栈空间上的. 一个简单的例子 我们以一个简单的迷宫为例,以1代表墙,0代表路径,我们构造一个具有出入口的迷宫. 1

  • Flutter随机迷宫生成和解迷宫小游戏功能的源码

    此博客旨在帮助大家更好的了解图的遍历算法,通过Flutter移动端平台将图的遍历算法运用在迷宫生成和解迷宫上,让算法变成可视化且可以进行交互,最终做成一个可进行随机迷宫生成和解迷宫的APP小游戏.本人是应届毕业生,希望能与大家一起讨论和学习- 注:由于这是本人第一次写博客,难免排版或用词上有所欠缺,请大家多多包涵. 注:如需转载文章,请注明出处,谢谢. 一.项目介绍: 1.概述 项目名:方块迷宫 作者:沫小亮. 编程框架与语言:Flutter&Dart 开发环境:Android Studio 3

  • 超简洁java实现双色球若干注随机号码生成(实例代码)

    Mavan pom文件引用依赖 <!-- hutool工具类--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.3.6</version> </dependency> <!-- google java类库--> <dependency> <

  • java图的深度优先遍历实现随机生成迷宫

    最近经常在机房看同学在玩一个走迷宫的游戏,比较有趣,自己也用java写一个实现随机生成迷宫的算法,其实就是一个图的深度优先遍历算法.基本思想就是,迷宫中的每个点都有四面墙,然后呢. 1.从任意一点开始访问(我的算法中固定是从(0,0)点开始),往四个方向中的随机一个访问(每访问到一个可访问的点,就去掉该点的那个方向的墙),被访问点继续以这种方识向下进行访问. 2.对每个被访问的点都被标识为已访问,当一个点对某个方向进行访问时我们首先会判断被访问点是否已被访问,或者触到边界.如果该点四个方向皆已访

  • Java编程实现深度优先遍历与连通分量代码示例

    深度优先遍历 深度优先遍历类似于一个人走迷宫: 如图所示,从起点开始选择一条边走到下一个顶点,没到一个顶点便标记此顶点已到达. 当来到一个标记过的顶点时回退到上一个顶点,再选择一条没有到达过的顶点. 当回退到的路口已没有可走的通道时继续回退. 而连通分量,看概念:无向图G的极大连通子图称为G的连通分量( Connected Component).任何连通图的连通分量只有一个,即是其自身,非连通的无向图有多个连通分量. 下面看看具体实例: package com.dataStructure.gra

  • Java实现走迷宫回溯算法

    以一个M×N的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍.设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论. (1) 根据二维数组,输出迷宫的图形. (2) 探索迷宫的四个方向:RIGHT为向右,DOWN向下,LEFT向左,UP向上,输出从入口到出口的行走路径. 例子: 左上角(1,1)为入口,右下角(8,9)为出口. 可使用回溯方法,即从入口出发,顺着某一个方向进行探索,若能走通,则继续往前进:否则沿着原路退回,换一个方向继续探索,直至出口位置,求得一条通

  • C++基于prim实现迷宫生成

    本文实例为大家分享了C++实现迷宫生成的具体代码,供大家参考,具体内容如下 只用到了c++中的vector,其余的和纯C差别不大,纯C可能需要手动弄一个vector太繁琐了不太想弄. 看了迷宫的一些算法,prim还是比较好看的,网上的代码python c#居多,而且不太容易搞懂,那我在这里用C++(大部分C)实现了这个目的 prim算法:随机Prim算法生成的迷宫岔路较多,整体上较为自然而又复杂,算法核心为(根据维基百科). 1.让迷宫全是墙. 2.选一个单元格作为迷宫的通路(我一般选择起点),

  • Java 基于雪花算法生成分布式id

    SnowFlake算法原理介绍 在分布式系统中会将一个业务的系统部署到多台服务器上,用户随机访问其中一台,而之所以引入分布式系统就是为了让整个系统能够承载更大的访问量.诸如订单号这些我们需要它是全局唯一的,同时我们基本上都会将它作为查询条件:出于系统安全考虑不应当让其它人轻易的就猜出我们的订单号,同时也要防止公司的竞争对手直接通过订单号猜测出公司业务体量:为了保证系统的快速响应那么生成算法不能太耗时.而雪花算法正好解决了这些问题. SnowFlake 算法(雪花算法), 是Twitter开源的分

随机推荐