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

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

算法思路

这里介绍的是基于深度优先遍历(DFS)的随机迷宫生成算法。该算法的基本思路是,从起点开始,每次选择一个相邻且未被访问过的节点作为下一个遍历的节点,直到到达终点,期间可以任意回溯。在此基础上加入了随机化操作,即在选择相邻节点时随机打乱遍历顺序,以此生成"随机"的迷宫。

实现步骤

  1. 首先,我们需要定义一个Maze类表示迷宫,并初始化地图。可以采用二维数组来表示地图,用数字0表示可通行的路径,1表示障碍(不可通行的墙壁)。
public class Maze {
    private int[][] map;  //地图
    private int height;  //迷宫高度
    private int width;  //迷宫宽度

    //构造函数,初始化地图
    public Maze(int height, int width) {
        this.height = height;
        this.width = width;
        this.map = new int[height][width];
        //初始化地图,全部设置为墙壁
        for(int i=0; i<height; i++) {
            for(int j=0; j<width; j++) {
                map[i][j] = 1;
            }
        }
        //生成起点
        int startX = 1 + (int)(Math.random()*(height-2));
        int startY = 1 + (int)(Math.random()*(width-2));
        map[startX][startY] = 0;
    }
}
  1. 接着,定义一个枚举类型(或者整数常量)表示方向,用于表示向上、向下、向左、向右四个方向。方便后面使用时的标识和操作。
public enum Direction {
    UP, DOWN, LEFT, RIGHT;
}
  1. 然后,定义一个方法用于遍历地图。遍历的过程需要借助深度优先遍历算法,在每个节点处延伸四个方向,如果在当前可探索的路径上,随机选择一个未走过的方向前进;如果当前已经无法前进,就返回上一层继续遍历,直到找到终点。
public void generateMaze() {
    //从起点开始遍历
    dfs(1, 1);
}

private void dfs(int x, int y) {
    //标记当前节点已经访问过
    map[x][y] = 0;
    //获取当前节点的所有邻居
    List<Direction> neighbors = getNeighbors(x, y);
    //随机打乱邻居集合的顺序
    Collections.shuffle(neighbors);
    //遍历所有邻居节点
    for(Direction direction : neighbors) {
        switch (direction) {
            case UP:
                //判断邻居是否可走
                if(x-2 > 0 && map[x-2][y] == 1) {
                    //将中间节点也标记为可走的路径
                    map[x-1][y] = 0;
                    dfs(x-2, y);
                }
                break;
            case DOWN:
                if(x+2 < height-1 && map[x+2][y] == 1) {
                    map[x+1][y] = 0;
                    dfs(x+2, y);
                }
                break;
            case LEFT:
                if(y-2 > 0 && map[x][y-2] == 1) {
                    map[x][y-1] = 0;
                    dfs(x, y-2);
                }
                break;
            case RIGHT:
                if(y+2 < width-1 && map[x][y+2] == 1) {
                    map[x][y+1] = 0;
                    dfs(x, y+2);
                }
                break;
        }
    }
}

//获取某个节点的所有邻居,即上下左右四个方向分别相距一个节点的位置
private List<Direction> getNeighbors(int x, int y) {
    List<Direction> neighbors = new ArrayList<>();
    if(x-2 > 0) {
        neighbors.add(Direction.UP);
    }
    if(x+2 < height-1) {
        neighbors.add(Direction.DOWN);
    }
    if(y-2 > 0) {
        neighbors.add(Direction.LEFT);
    }
    if(y+2 < width-1) {
        neighbors.add(Direction.RIGHT);
    }
    return neighbors;
}
  1. 最后,运行generateMaze方法即可生成迷宫。

示例说明

以下是两个生成迷宫的示例说明。

示例一

//生成20x20的迷宫
Maze maze = new Maze(20, 20);
//生成迷宫
maze.generateMaze();
//输出迷宫地图
for(int i=0; i<maze.getHeight(); i++) {
    for(int j=0; j<maze.getWidth(); j++) {
        if(maze.getMap(i, j) == 0) {
            System.out.print(" ");
        } else {
            System.out.print("#");
        }
    }
    System.out.println();
}

运行结果:

# # # # # # # # # # # # # # # # # # # 
#                   #         #     # 
#   # # # # # # #   #   # # # #   # 
#   #           #   #   #         # 
#   #   #   #   #   #   #   # # # # 
#   #   #   #   #       #   #     # 
#   #       #   #   #   #   #   # # 
#   #   #       #   #   #       # # 
#   #   # # #   #   #   #   #   #   
#   #       #       #   #   #   #   
#   #   #   #   # # # # # #   # #   
#   #   #       # # # # # # #     # 
#   #   #   #   #             #   # 
#       #   #   #   #   #     #   # 
#   # # # # # #   #   #   #   #   # 
#   #             #   #       #   # 
#   # # # # # # # #   #   #   #   # 
#               #     #       #   # 
# # # # # # #   # #   #   #   #   # 
#               #         # # # # # 

示例二

//生成30x15的迷宫
Maze maze = new Maze(30, 15);
//生成迷宫
maze.generateMaze();
//输出迷宫地图
for(int i=0; i<maze.getHeight(); i++) {
    for(int j=0; j<maze.getWidth(); j++) {
        if(maze.getMap(i, j) == 0) {
            System.out.print(" ");
        } else {
            System.out.print("#");
        }
    }
    System.out.println();
}

运行结果:

# # # # # # # # # # # # # # 
#     #           #     # 
# # # #   # # #   #   # # 
#     #   #   #       # 
# #   #   #   #   #   # 
#     #   #       #      
# # # # # #   # # # # # 
#         #   #     #   # 
#   # # # # # # # # # # 
#               #     # 
# # # # #   #   #   # # 
#         #   #          
# # # # # # #   # # # # 
#     #           #     # 
# #   #   # # #   # # #  
#     #               # 
# # # # # #   # # # # # 
#     #   #           # 
# # # #   #   # # #   # 
#         #       #   # 
# # # # # # #   # # # # 
#         #     #     # 
# # # # #   # # # # # # 
#     #           #      
# #   #   # # #   #   # 
#       #       #   #   
# # # # # # # # # # # # 

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java基于深度优先遍历的随机迷宫生成算法 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • Java的Struts框架中标签的使用方法

    下面是详细讲解Java Struts框架中<results>标签的使用方法的攻略。 Struts框架中的results标签 在Struts框架中,标签用于指定Action执行后的返回结果。results标签位于Action的配置文件中。它定义了Action的返回结果并将结果映射到JSP或其他视图组件或响应类型。 一个Struts Action可以…

    Java 2023年5月20日
    00
  • Java Runtime的使用详解

    Java Runtime的使用详解 什么是Java Runtime? Java Runtime是一个Java程序执行的环境。当一个Java程序需要运行时,Java Runtime会负责加载Java类和其他的资源,然后执行程序。 Java Runtime由Java Development Kit(JDK)提供, JDK包含JRE(Java Runtime En…

    Java 2023年5月20日
    00
  • Java中的三种校验注解的使用(@Valid,@Validated和@PathVariable)

    在 Java 中,校验注解的作用是为了验证数据的有效性,保证数据的准确性和安全性。其中 @Valid、@Validated 和 @PathVariable 是三种常用的校验注解,下面让我们来深入了解一下它们的使用方法和区别。 @Valid @Valid 注解基于 JSR-303 规范,需要结合 Hibernate Validator 等校验框架实现。主要用于…

    Java 2023年5月20日
    00
  • JSP一句话木马代码

    首先,需要注意的是,编写和传播木马代码是违法的,本文仅用于学习和研究用途。 JSP一句话木马是一种常见的web后门,可以通过在服务器上运行的JSP文件中注入一段恶意代码的方式,让攻击者可以远程控制服务器,获取敏感信息等。以下是攻击过程的详细说明: 扫描漏洞:攻击者扫描要攻击的目标服务器,尤其是针对常见的web应用程序,如JavaWeb开发中常用的Tomcat…

    Java 2023年6月15日
    00
  • IDEA快速搭建spring boot项目教程(Spring initializr)

    IDEA快速搭建Spring Boot项目教程(Spring Initializr) Spring Initializr是一个快速创建Spring Boot项目的工具,它可以帮助我们快速搭建一个基础的Spring Boot项目。本文将详细介绍如何使用IDEA快速搭建Spring Boot项目的方法,包括创建项目、添加依赖、运行项目等。 1. 创建项目 首先,…

    Java 2023年5月14日
    00
  • 利用Springboot+vue实现图片上传至数据库并显示的全过程

    下面是利用Spring Boot和Vue实现图片上传至数据库并显示的全过程。 前置准备 技术栈 Spring Boot Vue.js axios ElementUI MySQL MyBatis 下载代码 可以从GitHub上下载示例代码:https://github.com/KevinPang2019/springboot-vue-image-upload …

    Java 2023年6月1日
    00
  • Java CAS底层实现原理实例详解

    Java CAS底层实现原理实例详解 什么是CAS CAS是Compare And Swap(比较并交换)的缩写。它是一种并发操作,常用于多线程环境下。CAS操作包含3个操作数——内存位置(V)、预期原值(A)和新值(B)。操作仅在当前内存值等于预期原值时,将内存值修改为所需的新值。CAS是原子操作,保证了操作的原子性。 实现CAS需要硬件的支持。Java中…

    Java 2023年5月18日
    00
  • Java中的Random()函数及两种构造方法

    Java中的Random()函数及两种构造方法 在Java中,java.util.Random是一个用于生成伪随机数的类。它有两种构造方法,可以实现不同用途的随机数生成。 1. Random()函数 Random()函数是java.util.Random类的默认构造方法。该构造方法将当前时间戳作为种子,可以生成一个伪随机数: import java.util…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部