java递归分割生成随机迷宫

递归分割生成迷宫

运行效果

在这里插入图片描述

实现代码

package cn.edu.Maze;

import java.util.Random;
import java.util.Scanner;

/**
 * 输入迷宫的大小和高度打印出迷宫
 * @author SongErrors
 *
 */
public class Text {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		System.out.println("Enter the width and height :");
		int width = in.nextInt(), height = in.nextInt();
		RecursiveDivision maze = new RecursiveDivision(width, height);
		maze.printMaze(maze.createMazeData());
		in.close();
	}

}

/**
 * 递归分割生成迷宫
 * @author SongErrors
 *
 */
class RecursiveDivision {

	private int[][] mazeData;//迷宫数据

	private final int WALL = 0;// 墙

	private final int ROUND = 1;// 路

	private int width;// 迷宫的宽度

	private int height;// 迷宫的高度

	/**
	 * 生成自定义大小的迷宫
	 * 
	 * @param width
	 * @param height
	 */
	public RecursiveDivision(int width, int height) {
		this.width = width % 2 + 1 == 0 ? width : width + 1;
		this.height = height % 2 + 1 == 0 ? height : height + 1;
	}

	/**
	 * 自动生成迷宫
	 * 
	 * @return
	 */
	public int[][] createMazeData() {

		mazeData = new int[height][width];
		// 初始化迷宫,给迷宫添加一圈外墙
		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				if (x == 0 || x == width - 1 || y == 0 || y == height - 1)
					mazeData[y][x] = WALL;
				else
					mazeData[y][x] = ROUND;
			}
		}
		division(1, 1, width - 2, height - 2);
		// 设置起点和终点
		mazeData[1][0] = ROUND;
		mazeData[height - 2][width - 1] = ROUND;
		return mazeData;
	}

	/**
	 * 递归分割画迷宫
	 *
	 * @param startX:迷宫的起点横坐标
	 * @param startY:迷宫的起点纵坐标
	 * @param endX:迷宫的终点横坐标
	 * @param endY:迷宫的终点纵坐标
	 */
	private void division(int startX, int startY, int endX, int endY) {

		Random random = new Random();

		// 如果迷宫的宽度或者高度小于2了就不能再分割了
		if (endX - startX < 2 || endY - startY < 2)
			return;

		// x,y只能是偶数
		int posX = startX + 1 + random.nextInt((endX - startX) / 2) * 2;// 纵向分割分割线的横坐标
		int posY = startY + 1 + random.nextInt((endY - startY) / 2) * 2;// 横向分割线的纵坐标
		for (int i = startX; i <= endX; i++) // 横向分割
			mazeData[posY][i] = WALL;
		for (int i = startY; i <= endY; i++) // 纵向分割
			mazeData[i][posX] = WALL;

		division(startX, startY, posX - 1, posY - 1);// 左下区域
		division(startX, posY + 1, posX - 1, endY);// 左上区域
		division(posX + 1, posY + 1, endX, endY);// 右上区域
		division(posX + 1, startY, endX, posY - 1);// 右下区域

		// 随机打开三扇门
		switch (random.nextInt(4)) {
		case 0:
			openDoor(startX, posY, posX - 1, posY); // 开左边的墙
			openDoor(posX, posY + 1, posX, endY); // 开上方的墙
			openDoor(posX + 1, posY, endX, posY); // 开右边的墙
			break;
		case 1:
			openDoor(posX, posY + 1, posX, endY); // 开上方的墙
			openDoor(posX + 1, posY, endX, posY); // 开右边的墙
			openDoor(posX, startY, posX, posY - 1);// 开下面的墙
			break;
		case 2:
			openDoor(posX + 1, posY, endX, posY); // 开右边的墙
			openDoor(posX, startY, posX, posY - 1);// 开下面的墙
			openDoor(startX, posY, posX - 1, posY); // 开左边的墙
			break;
		case 3:
			openDoor(posX, startY, posX, posY - 1);// 开下面的墙
			openDoor(startX, posY, posX - 1, posY); // 开左边的墙
			openDoor(posX, posY + 1, posX, endY); // 开上方的墙
			break;
		}
	}

	/**
	 * 在指定的一面墙上开一个随机的门
	 *
	 * @param startX:迷宫开始的横坐标
	 * @param startY:迷宫开始的纵坐标
	 * @param endX:迷宫结束的横坐标
	 * @param endY:迷宫结束的纵坐标
	 */
	private void openDoor(int startX, int startY, int endX, int endY) {
		Random random = new Random();
		int x;// 开门的横坐标
		int y;// 开门的纵坐标

		// 墙是横着的
		if (startY == endY) {
			x = startX + random.nextInt((endX - startX) / 2 + 1) * 2;
			mazeData[startY][x] = ROUND;
		}
		// 墙是竖着的
		if (startX == endX) {
			y = startY + random.nextInt((endY - startY) / 2 + 1) * 2;// 在奇数墙上开门
			mazeData[y][startX] = ROUND;
		}
	}

	public void setWidth(int width) {
		this.width = width % 2 + 1 == 0 ? width : width + 1;
	}

	public void setHeight(int height) {
		this.height = height % 2 + 1 == 0 ? height : height + 1;
	}

	/**
	 * 打印迷宫
	 * 
	 * @param data
	 */
	public static void printMaze(int[][] data) {
		for (int i = 0; i < data.length; i++) {
			for (int j = 0; j < data[0].length; j++) {
				if (data[i][j] == 0)
					System.out.print("[]");
				else
					System.out.print("  ");
			}
			System.out.println();
		}
	}
}


  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值