2

我目前正在使用 prim 算法在 Unity 中生成一个随机迷宫。

如果我运行游戏,这就是迷宫的样子。

http://i1.ytimg.com/vi/ucWX34Vrel8/maxresdefault.jpg

这就是我想要迷宫的样子。

http://upload.wikimedia.org/wikipedia/commons/thumb/b/b1/MAZE_30x20_Prim.ogv/220px--MAZE_30x20_Prim.ogv.jpg

不同之处在于,第一个具有接触的白色方块的角,而第二个始终在白色方块之间留有空间。

这是控制迷宫视觉创建的代码:

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 算法按照我想要的方式制作迷宫,请分享。

4

2 回答 2

0

事实上,我猜你差不多了,你只需要在节点之间包含人工空间。我猜如果你在像这样的图表上操作

ooo
ooo
ooo

其中o代表节点,迷宫中实际生成的路径应如下所示

o-o-o
| | |
o-o-o
| | |
o-o-o

这意味着实际迷宫中必须包含更多空间。

于 2014-07-10T18:07:39.353 回答
0

好的,我将尝试使用一堆 ascii 图片来解释这个逻辑,因为我对文字不太感兴趣。

假设你从一个看起来像这样的迷宫开始:

...X..
.X.X.X
X....X
X.X.X.
X.X...
...XXX

其中“.”是可通行的路径,“X”是墙壁。假设你的起始迷宫是一个数组,要到达一个可以很好分离的迷宫,你需要“逐块”构建“超级块”并将它们放入一个更大的数组中。在此示例中,左上角的块将向上、向下、向左和向右看,以查看其邻居可行驶的位置。然后它构造一个“超级块”,如:

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
于 2016-01-08T20:01:32.807 回答