我目前正在使用prim算法在Unity中生成随机迷宫。
如果我运行游戏,这就是迷宫的样子。
这就是我想要迷宫的样子。
不同之处在于,第一个角落的白色方块接触,而第二个角落的白色方块之间始终有空间。
这是控制迷宫视觉创作的代码:
void FindNext(){
//We create an empty Transform variable
// to store the next cell in.
Transform next;
//List for the current cell's adjacents
List<Transform> curAdjacents;
//List for an element's adjacents
List<Transform> eleAdjacents;
//Number variable for while loop
int num = 1;
//Perform this loop
// While:
// The proposed next gameObject's AdjacentsOpened
// is less than or equal to 2.
// This is to ensure the maze-like structure.
do{
//We'll initially assume that each sub-list of AdjSet is empty
// and try to prove that assumption false in the for loop.
// This boolean value will keep track.
bool empty = true;
//We'll also take a note of which list is the Lowest,
// and store it in this variable.
int lowestList = 0;
for(int i = 0; i < 10; i++){
//We loop through each sub-list in the AdjSet list of
// lists, until we find one with a count of more than 0.
// If there are more than 0 items in the sub-list,
// it is not empty.
//We then stop the loop by using the break keyword;
// We've found the lowest sub-list, so there is no need
// to continue searching.
lowestList = i;
if(AdjSet[i].Count > 0){
empty = false;
break;
}
}
//There is a chance that none of the sub-lists of AdjSet will
// have any items in them.
//If this happens, then we have no more cells to open, and
// are done with the maze production.
if(empty){
//If we finish, as stated and determined above,
// display a message to the DebugConsole
// that includes how many seconds it took to finish.
Debug.Log("We're Done, "+Time.timeSinceLevelLoad+" seconds taken");
//Then, cancel our recursive invokes of the FindNext function,
// as we're done with the maze.
//If we allowed the invokes to keep going, we will receive an error.
CancelInvoke("FindNext");
//Set.Count-1 is the index of the last element in Set,
// or the last cell we opened.
//This will be marked as the end of our maze, and so
// we mark it red.
Set[Set.Count-1].renderer.material.color = Color.red;
//Every cell in the grid that is not in the set
// will be moved one unit up and turned black.
// (I changed the default color from black to clear earlier).
// If you instantiate a FirstPersonController in the maze now,
// you can actually try walking through it.
// It's really hard.
foreach(Transform cell in Grid){
if(!Set.Contains(cell)){
cell.Translate(Vector3.up);
cell.renderer.material.color = Color.black;
}
}
return;
}
//If we did not finish, then:
// 1. Use the smallest sub-list in AdjSet
// as found earlier with the lowestList
// variable.
// 2. With that smallest sub-list, take the first
// element in that list, and use it as the 'next'.
next = AdjSet[lowestList][0];
curAdjacents = next.GetComponent<CellScript>().Adjacents;
//Since we do not want the same cell in both AdjSet and Set,
// remove this 'next' variable from AdjSet.
AdjSet[lowestList].Remove(next);
//This is code I'm trying to use to solve the issue
//When I run it though it makes all but the first and last,
//square white. It is supposed to NOT break if one of the current,
//cell's adjacents cells has an adjacent cell that has already,
//been made white. I don't know what's wrong with this code.
//foreach(Transform element in curAdjacents){
//eleAdjacents = element.GetComponent<CellScript>().Adjacents;
//foreach(Transform elem in eleAdjacents){
//if(Set.Contains(elem)){
//continue;
//}
//else{
//Debug.Log("BREAK!");
//num = 0;
//break;
//}
//}
//}
}while(next.GetComponent<CellScript>().AdjacentsOpened >= 2 && num == 1);
//The 'next' transform's material color becomes white.
next.renderer.material.color = Color.white;
//We add this 'next' transform to the Set our function.
AddToSet(next);
//Recursively call this function as soon as this function
// finishes.
Invoke("FindNext", 0);
}
欢迎任何解决方案,无论是小的更改还是对所有代码的完全重做。如果您不知道如何修复代码,但是您知道如何按照我希望使用prim算法的方式制作迷宫,请分享它。
答案 0 :(得分:0)
事实上,我猜你几乎就在那里,你只需要在节点之间加入人工空间。我想如果你在像
这样的图表上操作ooo
ooo
ooo
其中o
表示节点,迷宫中实际生成的路径应该看起来像
o-o-o
| | |
o-o-o
| | |
o-o-o
这意味着实际迷宫中必须包含更多空间。
答案 1 :(得分:0)
好的,我会尝试使用一堆ascii图片来解释这个逻辑,因为我的文字并不那么热。
假设您从一个类似于:
的迷宫开始...X..
.X.X.X
X....X
X.X.X.
X.X...
...XXX
其中&#34;。&#34; s是可行驶的道路,&#34; X&#34; s是墙壁。 假设你的起始迷宫是一个数组,为了获得一个很好的分离的迷宫,你可以“逐块”地构建“超级块”并将它们插入一个更大的数组中。 在此示例中,左上角的块将查看,向上,向下,向左和向右以查看其邻居可移动的位置。然后构建一个“超级块”,如:
XXX
X..
X.X
假设“角落”将成为墙壁。在构造之后,它将自身插入较大阵列的左上部分。 同样,第二个块将构造如下:
XXX
...
XXX
然后将其自身插入左上角的第二个位置。根据您希望它的运行方式,它可以将第一个块重叠一个空格以保持拉伸。此时,您的较大数组看起来像(其中[]为空/未分配):
XXXXXX[][][][][]
X.....[][][][][]
X.XXXX[][][][][]
[][][][][][][][]
[][][][][][][][]
接下来,每个块都会自行查看,制作一个超级块,然后将自己设置为大型数组,直到得到类似的内容:
XXXXXXXXXXXXXXXXXX
X.......XXXXX.....
X.XXXXX.XXXXX.XXXX
XXXXXXX.XXXXX.XXXX
XXXX..........XXXX
XXXX.XXXXX.XXXXXXX
XXXX.XXXXX.XXXXXXX
XXXX.XXXXX.XXXXX.X
XXXX.XXXXX.XXXXX.X
XXXX.XXXXX.XXXXX.X
XXXX.XXXXX.......X
XXXX.XXXXXXXXXXXXX
XXXX.XXXXXXXXXXXXX
........XXXXXXXXXX
XXXXXXXXXXXXXXXXXX