清除岛屿
我之前在一款游戏中已经做过这类事情。要摆脱外围岛屿,流程基本上是:
- 首先,必须确保地图的中心将始终属于主要陆地,并且每个像素开始时都是“土地”或“水”(即不同的颜色)。
- 然后,从地图的中心开始进行四方向的洪水填充,并扩散到所有“土地”图块中。将此泛洪填充访问的每个像素标记为不同的类型,例如“ MainLand”。
- 最后遍历整个地图,并将所有剩余的“土地”像素转换为“水”,以摆脱其他岛屿。
消除湖泊
至于摆脱岛上的洞(或湖泊),您可以执行类似的过程,但要从地图的各个角落开始,然后通过“水”图块展开。这将使您可以将“海洋”与其他水瓦片区分开,然后就可以摆脱它们,就像之前摆脱岛屿一样。
例
让我来研究一下我在这里某处的洪水填充的实现方式(免责声明,我并不关心效率,因此,我确定有很多更有效的方法来实现它):
private void GenerateSea()
{
// Initialize visited tiles list
visited.Clear();
// Start generating sea from the four corners
GenerateSeaRecursive(new Point(0, 0));
GenerateSeaRecursive(new Point(size.Width - 1, 0));
GenerateSeaRecursive(new Point(0, size.Height - 1));
GenerateSeaRecursive(new Point(size.Width - 1, size.Height - 1));
}
private void GenerateSeaRecursive(Point point)
{
// End recursion if point is outside bounds
if (!WithinBounds(point)) return;
// End recursion if the current spot is a land
if (tiles[point.X, point.Y].Land) return;
// End recursion if this spot has already been visited
if (visited.Contains(point)) return;
// Add point to visited points list
visited.Add(point);
// Calculate neighboring tiles coordinates
Point right = new Point(point.X + 1, point.Y);
Point left = new Point(point.X - 1, point.Y);
Point up = new Point(point.X, point.Y - 1);
Point down = new Point(point.X, point.Y + 1);
// Mark neighbouring tiles as Sea if they're not Land
if (WithinBounds(right) && tiles[right.X, right.Y].Empty)
tiles[right.X, right.Y].Sea = true;
if (WithinBounds(left) && tiles[left.X, left.Y].Empty)
tiles[left.X, left.Y].Sea = true;
if (WithinBounds(up) && tiles[up.X, up.Y].Empty)
tiles[up.X, up.Y].Sea = true;
if (WithinBounds(down) && tiles[down.X, down.Y].Empty)
tiles[down.X, down.Y].Sea = true;
// Call the function recursively for the neighboring tiles
GenerateSeaRecursive(right);
GenerateSeaRecursive(left);
GenerateSeaRecursive(up);
GenerateSeaRecursive(down);
}
我将其作为摆脱游戏中湖泊的第一步。打电话之后,我要做的只是:
private void RemoveLakes()
{
// Now that sea is generated, any empty tile should be removed
for (int j = 0; j != size.Height; j++)
for (int i = 0; i != size.Width; i++)
if (tiles[i, j].Empty) tiles[i, j].Land = true;
}
编辑
根据评论添加一些额外的信息。如果您的搜索空间太大,则在使用递归版本的算法时可能会遇到堆栈溢出的情况。这是关于stackoverflow 的链接(双关语意为:-))到算法的非递归版本,使用a Stack<T>
代替(也在C#中匹配我的答案,但应该易于适应其他语言,并且在此还有其他实现)链接)。