六角图查找是否某些网格被包围算法

时间:2018-12-21 02:33:15

标签: algorithm unity3d

我正在通过Unity创建一个简单的六角形数学游戏。确实与Unity无关。

我从Image借来了https://catlikecoding.com/unity/tutorials/,以说明问题,它很大,因此将其放在链接中。


背景

与提供的链接中的教程相同,我使用一个数组来保存数据,以简化它,就像:

[      0, 0, 0, 0,    
        0, 0, 0, 0,
       0, 0, 0, 0,
        0, 0, 0, 0,
       0, 0, 0, 0      ]

我的目标是

  

检查一个或多个网格是否被另一种类型的网格包围。

定义

  

环绕意味着对于一个网格或一组连接的网格,所有邻居都处于不同的标记中。

例如,

[      0, 1, 1, 0,    
        1, 0, 1, 0,
       0, 1, 1, 0,
        0, 0, 0, 0,
       0, 0, 0, 0       ]

//Should become

[      0, 1, 1, 0,    
        1, 1, 1, 0,
       0, 1, 1, 0,
        0, 0, 0, 0,
       0, 0, 0, 0       ]

在这种情况下,我什至不需要算法,这很容易,因为我可以参照其邻居创建网格,例如

class grid{
    grid[] neighbor;
    int flag; //0 or 1
}

因此,当我需要检查网格是否被包围时,我只需要循环其neighbor


问题

但是,在以下情况下,这种方法很繁琐

[      0, 1, 1, 1,     
        1, 0, 0, 1,
       0, 1, 1, 1,
        0, 0, 0, 0,
       0, 0, 0, 0       ]

所以,我现在还需要检查其邻居的邻居,例如

foreach (grid i in neighbor){
   bool is_surrounded = false;
   if (grid.flag == 1) {
       //Good
   } else {
       //Check its neighbor, if every neighbor except i is 1, then return True. 
   }
}

它对于2正常工作,但是如果有3个空白网格怎么办。递归不可行,例如当网格没有被包围时

[      0, 1, 1, 1,     
        1, 0, 0, 1,
       0, 1, 0, 1,
        0, 0, 0, 0,
       0, 0, 0, 0       ]

然后我将循环遍历整个地图,以进行大约8 ^ n次检查。


问题

我认为有一种我没有意识到的聪明方法,我欢迎任何种类/语言的答案,甚至只是一个想法。可以肯定的是,我会慷慨解囊并提供解释。

谢谢。

2 个答案:

答案 0 :(得分:1)

首先,您必须进行严格的定义-什么区域称为“周围”。也许可行的方法是-单元格无法自由到达外部地图边缘。

要以这种方式进行检查-使用任何简单的遍历算法-例如DFS(路径查找算法在这里看起来过分杀伤-他们需要终点)

关于递归-您需要标记可见的单元格以避免重新检查。有floodfill个算法没有递归且具有很好的复杂性。

答案 1 :(得分:0)

您将对此倒退。您的编码逻辑看起来不错,但逻辑却相反。

对于每个存在的1,检查其周围是否可能存在其他1。如果您通过第一个1(从第一个1(返回)到第一个1)的任何路径返回,则您发现了一个闭环。找到返回路径来自的方向以重新调谐到第一个1,然后该方向就是循环内部的位置。然后,如果您对任何更深层次的循环都不感兴趣,请将该循环内的所有内容(包括1和0)标记为不再搜索。完成搜索,然后在搜索完成之后,并且只有在搜索完成之后,才将循环中的所有内部标记为1(如果这是您想要的)。这样,如果循环之外还有循环,那么您将不会一遍又一遍地重新启动。

对于子循环:将全1视为循环的可能起点。如果返回到先前的1,则找到来自哪个方向(在返回路径中),并考虑到循环的内部。

完成所有这些操作之后,您已经找到了循环,然后进行更改。不必担心循环的内部位置是否为零,因为0是有效大小,只需根据需要更改循环的所有可能内部即可。

谢谢。

B精益