将网格(2D阵列)划分为随机形状的部分?

时间:2010-08-03 15:17:44

标签: algorithm language-agnostic grid computational-geometry multidimensional-array

问题
我想将网格(2D数组)划分为随机形状的部分(想想earth's tectonic plates)。

标准是:

  • 用户输入网格大小(程序应该缩放,因为这可能非常大)。
  • 用户输入网格划分因子(多少部分)。
  • 网格是矩形六角形网格,顶部和底部封顶,左右环绕。
  • 零件没有碎片。
  • 其他部分内没有任何部件。
  • 没有小件或超大件。
  • 随机形状的部分,不是完美的圆形,或是蜿蜒的蛇形。

我的解决方案:

  • 创建一个可以访问/操作相邻单元格的方法。
  • 随机确定每个部分的大小(所有部分的总和等于整个2D阵列的大小)。
  • 使用最后一部分的ID号填充整个2D数组。
  • 除了最后一个部分之外的每个部分:
  • 在2D阵列的随机单元格中种植当前部件ID号。
  • 遍历整个阵列,并将每个单元的地址存储在已经使用当前部件ID号播种的任何单元旁边。
  • 提取其中一个存储的地址,并使用当前的板ID编号填充该单元格(因此部件开始形成)。
  • 重复此操作直至达到零件尺寸。

请注意,为了避免在其内部长出“臂”或大孔的部件,我创建了两个存储阵列:一个用于相邻的单元  对于只有一个具有当前部件ID号的单元,而另一个单元用于与多个单元相邻的单元,那么我在前者之前将后者用尽。

运行我的解决方案提供以下内容:
网格尺寸:200
宽度:20
身高:10
零件:7

66633333111114444466
00033331111114444466
00003331111114444466
00003331111144444660
00000333111164444660
00000336111664422600
00000336615522222200
00006655555522222200
00006655555552222220
00066655555552222220

部件号:0
零件尺寸:47

部件号:1
零件尺寸:30

部件号:2
零件尺寸:26

部件号:3
零件尺寸:22

部件号:4
零件尺寸:26

部件号:5
零件尺寸:22

部件号:6
零件尺寸:27

我的解决方案存在问题:

  • 最后一部分总是支离破碎 - 在上面的例子中,有三个独立的六人组。
  • 当部件形成于死胡同并且没有足够的空间可以增长到完整尺寸时,算法会停止(算法不允许在其他部分上形成部件,除非它是最后一部分,这是放下的在开始的整个2D阵列上)。
  • 如果我没有在形成2d阵列​​之前指定零件尺寸,只需要指定零件数量并随意生成零件尺寸,这就留下了形成微小零件的可能性,也许根本不存在,特别是当2D阵列非常大时。我目前的零件尺寸方法将零件尺寸限制在2D阵列总尺寸的10%到40%之间。如果有一些超级优雅的方法可以做到这一点,我可能没有指定零件尺寸 - 用户将拥有的唯一控件是二维阵列尺寸和零件数量。

其他想法:

  • 以完美对齐的方块形成零件,然后在2D阵列上运行并随机允许每个零件侵占其他零件,将它们翘曲成随机形状。
  • 在网格上绘制蛇形线并填入所创建的空格,可能使用这样的数学运算:http://mathworld.wolfram.com/PlaneDivisionbyLines.html

结论:
所以这就是问题:我是一名初学程序员,不确定我是否以正确的方式解决了这个问题。我可以创建一些更多的“补丁”方法,将碎片部分移动到一起,并允许形成部分“跳出”死胡同,如果它们卡在其中,但它感觉很乱。

你会如何解决这个问题?我可以用一些性感的数学来简化一些事情吗?

THX

3 个答案:

答案 0 :(得分:4)

几个月前,我为一款游戏做了类似的事情,虽然它是一个矩形网格而不是十六进制网格。尽管如此,理论是相同的,它提出了大致相同大小的漂亮的连续区域 - 一些更大,一些更小,但没有一个太小或太大。 YMMV。

  1. 创建一个指向网格中所有空格的指针数组。随机播放阵列。
  2. 分配前N个ID - 1,2,3等
  3. 直到数组指向没有没有ID的空格
  4. 遍历数组,查找没有ID的空格
  5. 如果空间在网格中具有DO具有ID的邻居,则分配空间   来自其邻居ID的加权随机选择的ID。
  6. 如果没有带ID的邻居,请跳到下一个。
  7. 一旦没有非空格,你的地图就会有足够的空白区域。

答案 1 :(得分:3)

这是我要做的:使用Voronoi算法。首先放置一些随机点,然后让Voronoi算法生成零件。要了解它的外观,请咨询:this applet

答案 2 :(得分:1)

正如Rekin所建议的那样,Voronoi图加上一些随机扰动通常会做得很好,而且在像你一样的离散空间上,相对容易实现。

我只想提出一些关于如何进行随机扰动的想法。如果你在最终分辨率下进行,那么要么花费很长时间,要么花费很少。您可以尝试进行多分辨率扰动。因此,从一个相当小的网格开始,随机播种,计算Voronoi图。然后随机扰动边界 - 类似于,对于具有不同区域的每对相邻单元,以某种方式推动该区域。您可能需要运行后期处理以确保您没有小岛屿。简单的填充将起作用。

然后创建一个两倍大小(每个方向)的网格,并复制您的区域。你可以使用最近的邻居。然后再次扰乱边框,并重复直到达到所需的分辨率。