我想生成一个如下所示的迷宫:
也就是说,它由一个方向上的路径组成,然后连接起来。我已经找到了一种算法来生成像这样的迷宫而没有成功。
具体来说,我不想要这样的迷宫:
因为它不会只在一个方向“运行”。
此外,如果这个迷宫的解决方案要求玩家“回溯” - 即不是一直向上移动,那将是很好的。
答案 0 :(得分:4)
答案 1 :(得分:4)
这很有趣!完整的ASCII艺术输出我提出...
█ ██████ █████████████████████ █
█ █ █ █
█ █ █ █
█ █ ██████████████████████████ █
█ █
█ █
██████ ██████ ███████████ ██████
█ █ █ █ █ █
█ █ █ █ █ █
███████████████████████████████ ██████
█ █
█ █
██████ █████████████████████ ██████
█ █ █
█ █ █
██████ ███████████ ███████████ █
█ █ █ █
█ █ █ █
█████████████████████ ██████ ██████
█ █ █ █
█ █ █ █
███████████████████████████████ ██████
█ █
█ █
private struct Cell
{
public bool visited;
public bool right;
public bool top;
}
static void Main(string[] args)
{
Random Rand = new Random();
int size = 8;
var maze = new Cell[size,size];
for (int x = 0; x < size; x++)
for (int y = 0; y < size; y++)
{
maze[x, y] = new Cell() { right = true, top = true, visited = false };
}
int count = size * size;
int positionX = Rand.Next(size);
// mark space below (outside matrix)
for (int y = 0; y < size; y++)
{
maze[positionX, y].top = false; maze[positionX, y].visited = true;
count--;
// move left or right n spaces
int n = Rand.Next(size); // random left or right by an amount n
int direction = (Rand.Next(2) == 0) ? 1 : -1;
while (positionX + direction > 0 && positionX + direction < size -1 && n-- > 0)
{
// moving sideways
if (direction == -1)
{
positionX += direction;
maze[positionX, y].right = false;
maze[positionX, y].visited = true;
count--;
}
else
{
maze[positionX, y].right=false;
positionX += direction;
maze[positionX, y].visited = true;
count--;
}
}
}
// Now pick a random place we have visited and extend into new territory
while (count > 0)
{
int x = Rand.Next(size);
int y = Rand.Next(size);
if (!maze[x, y].visited) continue; // not visited yet
// We are on a visited node, where can we go from here?
// Pick a direction to break down a wall - favor left right
if (Rand.Next(4) > 0)
{
if (Rand.Next(2) == 1 && x < size-1 && !maze[x+1,y].visited )
{ maze[x,y].right = false; maze[x+1,y].visited = true; count--;}
else if (x > 0 && !maze[x-1,y].visited)
{maze[x-1,y].right = false; maze[x-1,y].visited = true; count--;}
}
else
{
if (Rand.Next(2) == 1 && y < size - 1 && !maze[x, y + 1].visited)
{ maze[x, y].top = false; maze[x, y+1].visited = true; count--; }
else if (y > 0 && !maze[x, y-1].visited)
{ maze[x, y-1].top = false; maze[x,y-1].visited = true; count--; }
}
}
// Dump the maze
for (int y = 0; y < size; y++)
{
Console.Write("█");
for (int x = 0; x < size; x++)
Console.Write((maze[x, y].top) ? "█████" : " █");
Console.WriteLine();
for (int repeat = 0; repeat < 2; repeat++)
{
Console.Write("█");
for (int x = 0; x < size; x++)
{
Console.Write(maze[x, y].right ? " █" : " ");
}
Console.WriteLine();
}
}
答案 2 :(得分:0)
只需使用A *搜索确保您始终可以找到到达终点的路径,然后为每行添加20个随机放置的墙。如果在放下新行后A *无法到达终点,则使用回溯来重新生成一组新的墙,直到它工作为止。也许不是最有效的方法,但我认为它在大多数时候都会运作得相当好。
答案 3 :(得分:0)
这是另一个:
答案 4 :(得分:0)
如果我理解正确,你想让你的解决方案永远不要失败(当入口在底部并且出口在顶部时)。
我认为一种简单的方法是首先生成一个简单的水平贴图,在每一层中选择一个随机孔,如下所示:
+--------------- +
+ +
+--- ------------+
+ +
+-------------- -+
+ +
+-------- -------+
+ +
+ ---------------+
您现在已经定义了解决方案路径的位置。现在只做一些混乱:在某处移除一个随机的水平边缘,然后添加一个阻止其使用的垂直边缘,在新孔上方或下方的行上,在孔和真实解决方案之间随机选择。 (您需要确保不删除解决方案路径的两个部分之间的水平边缘。)
我认为这会很好用。但是,它可能不会太容易生成大(多行)错误路径。
答案 5 :(得分:0)
使用Eller's algorithm并在水平方向引入偏差。