类以撒的结合的房间生成算法

类以撒的结合的房间生成算法

原链接
翻译版本

目前本人只实现了房间大小都一样的情况,没有什么2x2,L型,2x1之类的房间

放个效果图
在这里插入图片描述

算法需要注意的

房间选择

  • 对于当前位置是否有设置房间(是否被占位)
  • 当前房间位置是否越界(超出限定范围)
  • 当前位置的周围4方向的房间量是否大于1个(为什么是1而不是0,因为那一个1是父节点,可以排除掉)
  • 随机一个概率要是以上都满足可以设定一个概率是否抛弃

以下代码是基于在Unity上实现的,也有注释,应该很好理解

using System.Collections.Generic;
using UnityEngine;
//************************************
//创建人:一个人心
//功能说明:地牢生成
//************************************
public class DungeonGeneration : MonoBehaviour {
	public GameObject RoomPref;
	public Transform RoomParent;
	private SpriteRenderer[] Rooms = new SpriteRenderer[100];
	private int[] floorplan = new int[100];

	private Queue<int> cellQueue = new Queue<int>();    // 所有已放置的房间
	private Queue<int> endRoom = new Queue<int>();      // 末尾房间
	private int startRoom = 35;

	public int level = 1;
	public int currentfloorPlan;
	public int maxfloorPlan;

	private void Awake() {
		// 初始化地图
		for (int i = 0; i < Rooms.Length; i++) {
			floorplan[i] = 0;
			var go = Instantiate(RoomPref, RoomParent);
			go.transform.localPosition = new Vector3(i % 10, i / 10, 0);
			Rooms[i] = go.GetComponent<SpriteRenderer>();
			Rooms[i].color = Color.black;
		}

	}

	[ContextMenu("生成地牢")]
	private void BuildRangeRoom() {

		// 初始化
		currentfloorPlan = 0;
		maxfloorPlan = (int)(Random.Range(0, 2) + 5 + level * 2.6);
		cellQueue.Clear();
		endRoom.Clear();
		for (int i = 0; i < Rooms.Length; i++) {
			floorplan[i] = 0;
			Rooms[i].color = Color.black;		// 设置黑色表示是墙 or 空位置
		}

		// 将开始房间入
		visit(startRoom);
		Rooms[startRoom].color = Color.yellow;
		while (cellQueue.Count > 0) {
			int i = cellQueue.Dequeue();
			int x = i % 10;

			bool create = false;		// 标记当前房间是否有扩展出来的房间
			if (x > 1) create = create | visit(i - 1);
			if (x < 9) create = create | visit(i + 1);
			if (i >= 10) create = create | visit(i - 10);
			if (i < 90) create = create | visit(i + 10);

			// 如果当前房间周围都不放置(i房间是末尾房)
			// 末尾房可以设置一些特殊房间,因为末尾房是离起点远的房间
			if (!create && i != startRoom) {
				endRoom.Enqueue(i);
				Rooms[i].color = Color.red;		
			}

			// 当生成的房间数量大于一定时,可以将起点重写传回去
			// 可以激励中心不会那么零散
			if (currentfloorPlan > 16) {
				if (Random.value < 0.25) {
					Debug.Log("startRoom");
					cellQueue.Enqueue(startRoom);
				}
			}
		}

		// 不合法
		if (currentfloorPlan == 1) BuildRangeRoom();
	}

	/// <summary>
	/// 检测是否可行
	/// </summary>
	/// <param name="i"></param>
	/// <returns></returns>
	private bool visit(int i) {
		// 检测当前放置的房间是否已经超出了
		if (currentfloorPlan >= maxfloorPlan) return false;
		// 检测是否被占用
		if (floorplan[i] != 0) return false;
		// 50%舍去
		if (Random.value < 0.5 && i != startRoom) return false;
		// 如果邻居数量大于1,因为1是之前的
		if (nCount(i) > 1) return false;

		// 可行
		cellQueue.Enqueue(i);   // 添加到已放置队列
		floorplan[i] = 1;       // 标记占用
		currentfloorPlan++;     // 总数++
		Rooms[i].color = Color.white;

		return true;
	}

	/// <summary>
	/// 检测周围邻居数
	/// </summary>
	/// <param name="i"></param>
	/// <returns></returns>
	private int nCount(int i) {
		int sum = 0;
		if (i + 10 < 100) sum += floorplan[i + 10];
		if (i - 10 >= 0) sum += floorplan[i - 10];
		if (i % 10 + 1 <= 9) sum += floorplan[i + 1];
		if (i % 10 - 1 >= 0) sum += floorplan[i - 1];
		return sum;
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个人心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值