【发布时间】:2015-03-30 09:16:02
【问题描述】:
我有一个为我生成迷宫的基本回溯算法。但有时它不会“访问”所有图块/单元格。我想知道出了什么问题,该算法确实可以正确回溯,它应该检查每个图块/单元格上的所有方向,但“未访问”的图块/单元格根本没有被触及。
这是回溯算法:
void GenerateMaze(Coordinate tilePos)
{
//Mark the current position visited
tileMap[tilePos.x, tilePos.y].visited = true;
//Randomize directions
Shuffle<Coordinate>(directions);
foreach(Coordinate d in directions)
{
//Check if the new position is within bounds
if (tilePos.x + d.x >= 0 && tilePos.x + d.x < mapWidth && tilePos.y + d.y >= 0 && tilePos.y + d.y < mapHeight)
{
//Check if the tile is already visited
if (!tileMap[tilePos.x + d.x, tilePos.y + d.y].visited)
{
//Carve through walls from this tile to next
Carve(tilePos, d);
//Recursively call this method on the next tile
GenerateMaze(new Coordinate(tilePos.x + d.x, tilePos.y + d.y));
}
}
}
}
如果您有兴趣,这是Carve 方法:
private void Carve(Coordinate position, Coordinate direction)
{
if (direction.Equals(new Coordinate(-1, 0)))
{
Debug.Log("Carving West from: ");
tileMap[position.x, position.y].west = true;
tileMap[position.x + direction.x, position.y + direction.y].east = true;
}
else if (direction.Equals(new Coordinate(1, 0)))
{
tileMap[position.x, position.y].east = true;
tileMap[position.x + direction.x, position.y + direction.y].west = true;
}
else if (direction.Equals(new Coordinate(0, -1)))
{
tileMap[position.x, position.y].south = true;
tileMap[position.x + direction.x, position.y + direction.y].north = true;
}
else if (direction.Equals(new Coordinate(0, 1)))
{
tileMap[position.x, position.y].north = true;
tileMap[position.x + direction.x, position.y + direction.y].south = true;
}
}
它只是根据算法前进的方向将正确的墙壁标志设置为真。
在下图中,您可以看到迷宫有 3 个“未访问”的图块。这主要发生在角落。
在这里它保留了一块未触及的瓷砖,但这次不是在侧面。
在 10x10 的迷宫中,这似乎会发生大约 1/10 次。问题瓦片未被访问,因此算法根本不处理它们。但是,由于它经过他们并且邻居的每个方向都经过测试,他们真的应该加入迷宫。那么有什么问题呢?
【问题讨论】:
-
ehm .... 在我看来,您只会访问您的(伪)随机游走将您带到的图块 - 所以如果您不能回到一个单元格,因为它周围的一切都已经访问过你不会访问它... backtrack 不会帮助你,因为你访问过的标志是全局的,所以一个分支中的操作在回溯之后仍然存在(请不要使用 global-state带递归函数)
-
@CarstenKönig 不确定您的意思。它应该访问每个单元格并检查每个单元格的所有方向。如果找到有效的移动/方向,它最终应该总是回来检查其他方向。这是一个 ruby 实现:weblog.jamisbuck.org/2010/12/27/…
-
@CarstenKönig 如果我只是在未连接的单元格上执行
GenerateMaze(new Coordinate(x + 1, y));,它可以解决问题。但是为什么它没有在回归的路上修复它呢?应该检查每个方向,以便它应该捕获未访问的单元格。 -
我完全支持 @CarstenKönig 这张支票
if (!tileMap[tilePos.x + d.x, tilePos.y + d.y].visited)没有出现在 buckblog 源代码中,并且在网页上观看算法的运行似乎没有问题重新访问已经雕刻出来的节点,直到所有节点被访问。 -
可以分享
directions的内容是什么吗?
标签: c# algorithm recursion unity3d maze