确定网格上的一组拼贴是否形成封闭的形状


10

给定网格上的一组图块,我想确定:

  • 如果瓷砖是一个封闭的图形
  • 如果将板的侧面算作图形的边缘时,这些瓷砖形成一个封闭的图形
  • 如果前两个陈述中的任何一个为真,则附加图块中的其他图块将形成初始图块。

玩家将首先按下一个图块,然后将其手指拖动到其他图块以创建一串相同颜色的图块。我将检查下一个磁贴是否有效。例如 如果玩家在红瓦开始,他们唯一的下一个有效的行动是到邻近的红瓦(对角线计数)。当用户抬起手指时,我需要能够检查上述3个项目。

所以我最初的想法是,由于我每次走时都要检查链条的有效性,所以当玩家抬起手指时,我可以检查第一个和最后一个瓷砖是否相邻。(我已经知道它们是相同的颜色。)如果它们相邻,我会预感会做出一个封闭的图形,然后我要来这里尝试看看我是否丢失了一些大东西,并得到某种逻辑/数学证明,我的直觉是正确的(或一个例子证明它是错误的。)

但是那时候我想到了项目2:我还必须考虑使用木板边缘作为封闭图形侧面的链条。在这种情况下,链中的第一个项目和最后一个项目不会相邻,但是我仍然会附上一个数字。所以现在我回到正题。

我应该如何处理这一系列的网格坐标,以确定它们是否包含封闭的图形?有一次我知道我有一个封闭的身影,那是什么让那个属于其范围内的所有瓷砖的附加列表的最佳方式?

在此处输入图片说明

在此处输入图片说明

上面我画了我期望该测试有4种可能结果的图片。

  1. 链没有附上数字。

  2. 链确实有一个封闭的数字。

  3. 如果将板的侧面算作图形的边缘(或一个以上的边缘),则链条会形成一个封闭的图形。

  4. 该链的确制作了一个封闭的图形,但是有一些额外的数据点(用户已有效选择作为链的一部分),这些数据点不属于所创建图形的一部分。

情况4是最棘手的,因为您必须提取“额外”链节以找到封闭的图形和落入其中的零件(但不能围绕“未封闭”的区域)。

所以...有人想办法解决这个问题,还是对我来说只是一个起点?在这一点上,我有点转圈,可以使用另一组眼睛。


1
像图8或五角星这样的相交路径呢?您会假设填充规则为非零还是奇数?
Anko 2014年

情况4也可以与情况3合并:使用板子的侧面围起来,并附带其他信息
ChargingPun 2014年

如果您有一条垂直线从上边缘到底部沿电路板的中心向下延伸,那么电路板的哪一侧被“封闭”?
史蒂文·斯塔德尼克

我认为我们应该假设目前已封闭了最小的空间。除非OP另有规定。
汤姆(Tom'Blue)Piddock,2014年

Answers:


3

1.检测瓷砖循环

该问题似乎与检测图中的周期(循环)相似,请参见此处此处

  • V图的节点集G=(V, E)是图块,
  • e = (v1, v2)如果图块是直接邻居或对角邻居,则在两个不同节点之间存在一条边

2.处理屏幕边框

屏幕边框由那些假想的图块组成,这些图块将在可见图块的屏幕周围形成一个图块宽的边框。

根据您的规范,屏幕边框的一部分将形成闭环的隐式部分。只要检测到闭环,这将是足够的扩展图形G的图形G'通过表彰通过此规则的连接:

  • 如果两个图块均直接位于屏幕边框附近,则任何两个不同的节点之间都存在另一条边

因此(0,0)和(1,0)处的图块将与“边界图块”(-1,0),(-1,-1),(0,-1)一起成为闭环的一部分,(1,-1)。

3.环形区域的内部

我将向类似的方向介绍用户Arthur Wulf White的建议:

限制图块集必须通过循环图块的边界框来检查。

然后,使用泛洪填充选择边界框内封闭环外部或内部的所有图块。它只能是这两种情况之一。之后我们必须找出哪一个。

在每个方向上用一个图块扩展边界框也是一个好主意,产生extbb,因此,如果我们开始使用外图块进行洪水填充,我们最终将得到一组连接的外部点。

有了洪水填充区域后,我们还将计算其边界框ffbb。如果我们从外部瓷砖开始,它应该与扩展循环边界框相同。

ffbb == extbb

如果我们从内部磁贴开始,它将产生一个明显更小的边界框,因为循环磁贴必须夹在两个边界框之间。

ffbb < extbb

洪水填充的初始起始图块可以是其中的任意图块,extbb其中任何图块都是免费图块。也许随机选择一个是最好的方法。

如果我之前知道内部要小于外部,那么我将从绕点的质心开始,该点位于许多区域的内部(反例:C形区域),否则位于的边界extbb。但我不知道如何估算。

结束语

通常,我会说,从某个图块开始并进行访问的图块列表的简单步行就足以检测一个周期,但是该屏幕边界条件可能会生成更复杂的图,因此使用图算法应该是安全的。

下面是一个内部未连接的示例,另一方面,在这种情况下,循环检测应找到两个回路,一个回路应丢弃。

某些情况下


1

您可以通过以下方法解决此问题:

  1. 找到该形状的边界框。
  2. 在每个方向上将其大小增加1。
  3. 遍历新的略微扩大的边界框的框架并应用洪水填充。
  4. 如果您没有在该链上标记任何未用洪水填充标记的图块,则将其封闭。我想根据您的定义,如果有封闭的瓷砖,则形状是封闭的图形。

要做到一个,迭代链上的所有瓷砖和找到自己minXminYmaxXmaxY那就是你的边界框或AABB。

二是琐碎的。

在框架上进行迭代很简单,只需确保不要在网格外部填充即可。您可以在Wikipedia中学习如何填充。

对于第四个,您可以仅通过检查与链相邻的图块开始。您可以从发现的未标记的任何图块中进行填充,以查找更多图块。


0

您的直觉是正确的,假设链条在用户尝试选择他们已经选择的图块后立即结束。在这种情况下,图片中的形状通常看起来像套索(4)。如果他们可以继续刷卡,那么他们会画出很多循环,事情会变得更加复杂。您要做的是回答多边形中的问题。

首先,我们需要定义问题。我将假设情况看起来像(2),即,任何尾巴都被剥去,并且末端连接回到起点,因此每个图块在链中只有一个“前任”和一个“后任” (其中图块X的后继者始终是图块X)。此外,如果您对“继任者”的关注时间足够长,那么您最终将回到起点。您可以使用Gurgadurgen的建议来检测循环是否在任何时候实际上在自身上交叉。假设您结束了用户的输入,它将看起来像是一行中的一系列节点,然后是一个循环。您可以删除该行以获得循环。

现在,对于每一行,请执行以下操作:

  1. 从左边缘开始,并跟踪每个图块的布尔值,该布尔值告诉我们是IN还是OUT。开始。
  2. 如果当前图块是链的一部分,则同时查看后继对象和前继对象(必须相邻)。如果其中一个严格位于上方(即当前图块的北,东北或西北),则将当前图块的状态设置为与图块左侧相反的状态。否则,将其设置为与左侧的图块相同。转到4。
  3. 如果当前图块不是链的一部分,则将图块设置为标题左侧的状态。转到4。
  4. 右边的图块现在是当前图块。转到2。

现在,将所有处于IN的图块,添加边框上的图块(包括一条尾巴(如果您较早剥离或未剥离,则选择),然后将该区域称为该区域。

如果要允许用户使用边框,请记住,这并没有在板上定义和IN / OUT,而只是将其分为两部分。例如,您可以选择较小的区域,或者要求用户使用两个相邻的侧面(即,左侧和底部,但不能同时使用顶部/底部或左侧/右侧)。

一种优化是,您只需要执行其中带有任何边框的行(如果您不能使用侧面)。我认为您的电路板足够小,即使在最弱的移动系统上,也可以在每个图块上进行迭代并进行非常简单的计算,这不是问题。(毕竟,您必须渲染它们,这比任务复杂得多)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.