是否有生成 3 维迷宫的算法?本质上与2D迷宫相同,但Z深度轴可以遍历?这个想法仍然是一样的,从头到尾。还可以使用回溯吗?
我应该使用哪种算法来生成 3D 迷宫?
见这里。我的意思是你也可以进入立方体,而不仅仅是迭代它的面。
几年前,我在这里使用 Kruskal 算法制作了 2d 迷宫。没有理由这不能与您描述的 3d 案例一起使用。基本上,您会将一个单元格视为一个立方体,并且有一个大型阵列,该阵列(对于每个单元格)在 +/- x、y 和 z 方向上有 6 个墙。该算法最初从所有墙壁开始,然后随机使墙壁消失,直到迷宫中的每个单元都连接起来。
我有在 RPGLE 中生成 2D 迷宫的代码(我在学习语言时做了一些自我练习)。由于我编写它的方式,一般算法所需的唯一更改是将 Z 维度添加为附加维度......
整个内容有 20 页长(尽管这包括输入/输出),所以这里有一些代码。你应该能够将它翻译成你需要的任何语言:我从意大利面条代码 BASIC 翻译它(goto
在这里过度使用了,是的。但这是一个有趣的练习)。
//set out maximum maze size
maximumMazeSquareCounter = mazeHorizontalSize * mazeVerticalSize + 1;
// generate a starting horizontal positiongetRandomNumber(seed : randomNumber);
currentHorizontalPosition = %inth(randomNumber * (mazeHorizontalSize - 1)) + 1;
currentVerticalPosition = 1;
mazeSquareCounter = 1;
// generate the top row of the maze (with entrance)
mazeTopRow = generateEntrance(currentHorizontalPosition);
//write to the printer file
writeMazeDataLine(mazeTopRow);
mazeSquareCounter += 1;
//set the first position in the maze(the entry square
setPathPoint(currentHorizontalPosition : currentVerticalPosition);
//do until we've reached every square in the maze
dou mazeSquareCounter >= maximumMazeSquareCounter;
//get the next available random direction
mazeDirection = getNextRandomDirection(getNextAvailableDirection(currentHorizontalPosition : currentVerticalPosition));
//select what to do by the returned results
select;
//when FALSE is returned - when the maze is trapped
when mazeDirection = FALSE;
//if not at the horizontal end of the maze
if currentHorizontalPosition <> mazeHorizontalSize;
//add one to the position
currentHorizontalPosition += 1;
//else if not at the vertical end of the maze
elseif currentVerticalPosition <> mazeVerticalSize;
//reset the horizontal position
currentHorizontalPosition = 1;
//increment the vertical position
currentVerticalPosition += 1;
//otherwise
else;
//reset both positions
currentHorizontalPosition = 1;
currentVerticalPosition = 1;
endif;
//when 'N' is returned - going up (other directions removed)
when mazeDirection = GOING_NORTH;
//set the point above current as visited
setPathPoint(currentHorizontalPosition : currentVerticalPosition - 1);
//set the wall point to allow passage
setWallDirection(currentHorizontalPosition : currentVerticalPosition : GOING_NORTH);
//change the position variable to reflect change
currentVerticalPosition -= 1;
//increment square counter
mazeSquareCounter += 1;
endsl;
enddo;
//generate a random exit
// get a random number
getRandomNumber(seed : randomNumber);
// set to the horzontal position
currentHorizontalPosition = %inth(randomNumber * (mazeHorizontalSize - 1)) + 1;
//set the vertical position
currentVerticalPosition = mazeVerticalSize;
//set wall to allow for exit
setWallDirection(currentHorizontalPosition : currentVerticalPosition : GOING_SOUTH);
整个事情由两个二维数组(好吧,相当于RPG)支持:一个用于占据“广场”的墙壁,另一个用于该广场是否已被访问。迷宫是在每个广场被访问后创建的。保证只有一条路径,蠕虫转向迷宫。
为了使这个三维,使它使用三维数组,并添加必要的维度索引。
前段时间我为方形网格上的 2D 迷宫设计了一个算法,没有理由为什么这不适用于立方网格上的 3D 迷宫。
从最初充满壁单元的 3D 网格开始。
...
在网格边缘启动一个代理,代理在 X、Y、Z、-X、-Y 或 -Z 方向沿直线行进,并在她行进时清空墙壁。
动作“N”每一步发生的可能性很小。
当代理前面的单元格是墙壁并且前面的单元格是空的时,会发生动作“M”。
'N' 是一个随机选择:
'M' 是一个随机选择:
迷宫与众不同,通过调整“M”的触发器(与有效路口有关)以及调整 1 到 8 出现的机会,它们的特性非常灵活。您可能想要删除一两个动作,或引入您自己的动作,例如做一个小清理或回避一步。
“N”的触发器也可以是另一种随机性,例如下面的示例可用于创建仍然有一些长直部分的相当多枝的迷宫。
float n = 1;
while (random_0_to_1 > 0.15)
{
n *= 1.2;
}
return (int)n;
从我的简单描述中将需要一些小的调整,例如动作“M”的触发器将需要检查与它检查的单元格相邻的单元格,这取决于需要什么样的连接点。
迷宫包含循环需要 5 或 6,并且迷宫包含死端需要至少一个替代 5 和 6 的“M”动作。
一些机会/动作和“M”触发器的选择往往会导致迷宫不起作用,例如无法解决或充满空或壁单元,但许多会产生始终如一的好结果。