c# - 如何随机创建一个迷宫
问题描述
我目前有代码可以打开我的预制件上的所有门,用于不在我随机生成的地图边缘的房间/瓷砖。我想修改这段代码,以便不是所有的门都打开,它更像是一个随机生成的迷宫。我希望每个房间都可以进入,并且可以有不止一条穿过迷宫/游戏世界的路径。如何更改我的代码,使其以这种方式工作?以下是我要修改的当前代码。
using UnityEngine;
public class Room : MonoBehaviour {
public GameObject doorNorth;
public GameObject doorSouth;
public GameObject doorEast;
public GameObject doorWest;
}
using UnityEngine;
using System;
public class mapGenerator : MonoBehaviour {
public int rows;
public int cols;
public GameObject[] gridPrefabs;
private float roomWidth = 50.0f;
private float roomHeight = 50.0f;
public Room[,] grid;//used to keep track of rooms created ,uses two numbers to refer to it in memory
public bool isMapOfDay;
public bool isRandomMap;
public int chosenSeed;
// Use this for initialization
void Start () {
chosenSeed = GameManager.instance.mapSeed;
rows = GameManager.instance.mapRows;
cols = GameManager.instance.mapColumns;
isMapOfDay = GameManager.instance.useMapOfDay;
isRandomMap = GameManager.instance.useRandomMap;
gridPrefabs = GameManager.instance.mapTiles;
}
public GameObject RandomRoomPrefab()//Returns a random room
{
return gridPrefabs [UnityEngine.Random.Range (0, gridPrefabs.Length)];
}
public void GenerateGrid()//used to generate map grid
{
if (isRandomMap == true && isMapOfDay == false) {//sets map to random map based on time
UnityEngine.Random.InitState(DateToInt(DateTime.Now));//sets "random" seed to current time
} else if (isRandomMap == false && isMapOfDay == true) {//sets map to map of day based on numbers in day
UnityEngine.Random.InitState(DateToInt (DateTime.Now.Date));
} else {//if both are selected just use random map
UnityEngine.Random.InitState(DateToInt (DateTime.Now));
}
if (chosenSeed != 0) {//if a specific seed is entered in game manager use this instead
UnityEngine.Random.InitState(chosenSeed);
}
//Clear out the grid
grid = new Room[cols, rows];
GameManager.instance.mapGrid = grid;
//For each grid row...
for (int i=0; i<rows; i++)
{
//for each column in that row
for (int j=0; j<cols; j++)
{
//Figure out the location
float xPosition = roomWidth * j;
float zPosition = roomHeight * i;
Vector3 newPosition = new Vector3 (xPosition, 0.0f, zPosition);
//create a new grid at appropiate location
GameObject tempRoomObj = Instantiate (RandomRoomPrefab (), newPosition, Quaternion.identity)as GameObject;
//set its parent
tempRoomObj.transform.parent = this.transform;
//give the temp room a meaningful name
tempRoomObj.name = "Room_" + j + "," + i;
//Get the room object
Room tempRoom = tempRoomObj.GetComponent<Room> ();
//open doors as needed
if (i == 0) {
//open north doors if on bottom row
tempRoom.doorNorth.SetActive (false);
} else if (i == rows - 1) {
//Otherwise, if doors are on the top row open south doors
tempRoom.doorSouth.SetActive (false);
} else {
//otherwise, this row is in the middle so both north and south open
tempRoom.doorNorth.SetActive (false);
tempRoom.doorSouth.SetActive (false);
}
if (j == 0) {
//if first column then east doors are opened
tempRoom.doorEast.SetActive (false);
} else if (j == cols - 1) {
//Otheriwse, if one last column row open west doors
tempRoom.doorWest.SetActive (false);
} else {
//otherwise, we are in middle so both west and east are opened
tempRoom.doorEast.SetActive (false);
tempRoom.doorWest.SetActive (false);
}
//save it to the grid array
grid [j, i] = tempRoom;//
GameManager.instance.mapGrid=grid;
}
}
}
public int DateToInt(DateTime dateToUse)//adds date and time up and returns it as an int
{
int dateToReturn = dateToUse.Year + dateToUse.Month + dateToUse.Day + dateToUse.Hour +dateToUse.Minute + dateToUse.Second + dateToUse.Millisecond;
return dateToReturn;
}
public void clear()//clears grid
{
for (int c=0; c<GameManager.instance.mapGrid.GetLength(0); c++) {
for (int r=0; r<GameManager.instance.mapGrid.GetLength(1); r++) {
if(GameManager.instance.mapGrid[c,r]!=null)//if not null destroy
{
Destroy(GameManager.instance.mapGrid[c,r].gameObject);
}
}
}
}
}
我相信改变需要在我的 else 语句中发生,但我不确定如何去做,因为我以前从未做过迷宫。谢谢您的帮助!
解决方案
查看此博客,它也许可以帮助您了解 Unity 中的程序生成迷宫。
https://www.raywenderlich.com/82-procedural-generation-of-mazes-with-unity
但本质上你可以使用递归回溯算法。实现起来相对简单。
将您的起点标记为已访问并选择一个未访问的随机邻居。
在该起点随机选择一个格子,并刻出一条通往近格子的通道(仅当尚未访问近格子时。它将是新的格子
仅当所有附近的网格都处于访问状态时,才返回具有未雕刻墙的最后一个网格并重复。
当进程一直备份到起点时,算法结束。
我希望你能澄清一下你在找什么。