【问题标题】:Issue with my algorithm for checking if something is adjacent to a point我的用于检查某物是否与某个点相邻的算法存在问题
【发布时间】:2016-09-04 12:35:19
【问题描述】:

作为我正在进行的项目的一部分,我想将含水的瓷砖划分为“海洋”和“湖泊”。这是通过首先找到地图边缘的所有水瓦,并将它们指定为“海”瓦来完成的。所有与海瓦相邻(无对角线)的水瓦也是海瓦。所有其他水瓷砖都是“湖”瓷砖。

我找到第一块海瓦(在木板边缘)的方法没有缺陷。然而,我寻找其他海瓦的方法通常会遗漏应该是海的大矩形区域。代码如下:(seed 是一个布尔数组,其中true 是陆地,false 是水,seas 是另一个布尔数组,其中true 是海瓦,false 不是)

for (int x = 0; x < length; x++)
{
    for (int y = 0; y < height; y++)
    {
        if (!seed[x, y])
        {
            if (x + 1 < length && seas[x + 1, y])
                seas[x, y] = true;
            else if (x - 1 >= 0 && seas[x - 1, y])
                seas[x, y] = true;
            else if (y + 1 < height && seas[x, y + 1])
                seas[x, y] = true;
            else if (y - 1 >= 0 && seas[x, y - 1])
                seas[x, y] = true;
        }
    }
}

我这辈子都找不到这段代码的错别字,也许换一双眼睛会有所帮助?

我的代码的下一步是找到所有不是海瓦的水瓦,并将它们指定为湖瓦。这是通过以下 sn-p 完成的:(seasseed 与上面相同,lakes 是一个布尔数组,其中 true 是湖瓷砖,false 不是)

for (int x = 0; x < length; x++)
{
    for (int y = 0; y < height; y++)
    {
        if (!seed[x, y] && !seas[x, y])
        {
            lakes[x, y] = true;
        }
    }
}

这是另一个可能的错误来源,但我又一次不知道它是如何被破坏的。

附加的是根据生成的三个布尔数组生成的图像。绿色是陆地板块,蓝色是海洋板块,浅蓝色(或浅蓝色)是湖板块。如您所见,有大片水域与海瓦相邻,应该也是海瓦,但实际上是湖瓦。

提前谢谢你。

【问题讨论】:

  • 通常,我看到这种检查是通过递归洪水填充完成的。现在更深入地研究您的代码。
  • 问题是您的代码以给定的顺序检查图块(从上到下,然后从左到右)并且未知的图块有 sea[x,y]=false。因此,如果您有一块邻居都是陆地且未知的图块,即使它是海,您也会将其标记为湖。如前所述,您必须使用洪水填充或 BFS 算法。

标签: c# algorithm multidimensional-array


【解决方案1】:

作为一个复杂的数学解决方案,您可以重复第一个代码块 N 次(其中 N 等于您的 length 变量可能 N-1 次,因为您第一次进行 +-1 检查)。原因是您可能会跳过一些其邻居尚未标记但稍后会标记的瓷砖。所以你必须稍后再回来检查它的邻居是否被标记。显然有更多的优化方法需要更少的过程。

for (int z=0;z < length; z++){

for (int x = 0; x < length; x++)
{
    for (int y = 0; y < height; y++)
    {
        if (!seed[x, y])
        {
            if (x + 1 < length && seas[x + 1, y])
                seas[x, y] = true;
            else if (x - 1 >= 0 && seas[x - 1, y])
                seas[x, y] = true;
            else if (y + 1 < height && seas[x, y + 1])
                seas[x, y] = true;
            else if (y - 1 >= 0 && seas[x, y - 1])
                seas[x, y] = true;
        }
    }
}
}

【讨论】:

  • 打败我。同样,一个好的递归洪水填充可能会更优雅。虽然对于您的回答,我想知道是否只需扫描整个地图两次就足够了 - 或者可能只有在值实际发生变化的情况下。
  • 感谢您介绍洪水填充。在我建议的方法中,N-1 时间递归是强制性的,因为邻居效应正在被一一传播。一个简单的例子是一个垂直的列,它从底部开始,在到达地图顶部之前结束。
  • 谢谢。我最终使用了与此类似的方法。我想避免递归,因为我希望能够创建大型 (1000+ x 1000+) 映射而不用担心内存使用。
猜你喜欢
  • 2012-04-30
  • 1970-01-01
  • 2023-04-04
  • 2016-05-19
  • 2021-01-12
  • 2013-05-27
  • 1970-01-01
  • 1970-01-01
  • 2012-06-30
相关资源
最近更新 更多