随机平铺布局

时间:2010-06-25 04:58:37

标签: algorithm math layout grid tiles

我需要将瓷砖放在从中心点辐射的大网格上,看起来是有机和随机的。新的瓷砖需要在网格上找到至少接触另一个瓷砖的开放空间。

有人能指出我有权指导任何可能对此有所帮助的事情吗? 或者我能读到的一些基本概念就是这样吗?

例如,在此图片中,已经创建了一个形状(黄色),我可能正在接收新的图块,可能是1x1,2x2或3x3。试图找到一个很好的方法来确定我可以放置新瓷砖的位置,以便它将触及最大量的当前瓷砖。

照片: alt text http://osomer.com/grid.JPG

4 个答案:

答案 0 :(得分:3)

或者,你可以解决这个问题,因为黄色瓷砖在蓝色/背景上“侵蚀”了。要做到这一点,在每一步,都有一个黄色的瓷砖添加一个固定的数字到主要方向相邻的所有背景瓷砖的“侵蚀和” E (也许可能只是一小部分对角线邻近的背景砖。)

然后,当需要放置新的图块时,您可以为每个背景图块选择一个从0到 E 的随机数;最伟大的一个被“侵蚀”了。或者,你可以做一个简单的加权随机选择, E 是他们的权重。

对于2x2或3x3瓷砖,您只能从适合“适合”2x2或3x3方形的瓷砖中选择(即,边缘上的2x2或3x3侵蚀瓷砖,这样它不会导致重叠已经放置的瓷砖)。但实际上,你永远不会得到像一对一的侵蚀/瓷砖放置一样自然的东西。

您可以通过让每次迭代持久化来重新计算侵蚀总和,节省时间,只有当您添加新图块时,才会增加周围环境的侵蚀总和(简单+=)。在这一点上,它与提出的另一个答案基本相同,尽管有不同的观点/哲学。

侵蚀和的样本网格 E ,直接主要邻居为+4,对角线邻居为+1:

Erosion Sums http://img199.imageshack.us/img199/4766/erosion.png

E 较高的人最有可能被“侵蚀”;例如,在这一个中,西面和南面的两个小入口最有可能被黄色侵蚀掉,接着是北面和东面的较小海湾。最不可能的是那些几乎没有碰到黄色的角落。你可以通过为每个磁贴分配一个从0到 E 的随机数并侵蚀具有最高随机数的随机数,或者做一个简单的加权随机选择,或者通过你的任何决策方法来决定哪一个选择。

答案 1 :(得分:2)

对于纯随机,你从一个空网格和一个“候选”列表(也是空的)开始。

将第一个图块放在网格的中心,然后将每个相邻图块添加到刚放入“候选”列表中的图块。然后,每回合,在“候选”列表中选择一个随机条目并在那里放置一个图块。查看您刚放置磁贴的位置旁边的每个相邻网格位置,并且对于每个也为空的网格位置,将其放在下一次“候选”列表中(如果尚未存在)。

为避免在拼贴网格中创建孔,请根据已填充的相邻拼贴的数量增加选择网格位置的概率(因此,如果只填充了一个相邻拼贴,则可能很低。如果它们'一切都填满了,它的概率非常高。)

在伪代码中:

grid = new array[width,height];
candidates = new list();

function place_tile(x,y) {
   // place the tile at the given location
   grid[x,y] = 1;

   // loop through all the adjacent grid locations around the one
   // we just placed
   for(y1 = y - 1; y1 < y + 1; y1++) {
       for(x1 = x - 1; x1 < x + 1; x1++) {
           // if this location doesn't have a tile and isn't already in
           // the candidate list, add it
           if (grid[x,y] != 1 && !candidates.contains(x1,y1)) {
               candidates.add(x1,y1);
           }
       }
   }
}

// place the first tile in the centre
place_tile(width/2, height/2);

while (!finished) {
   // choose a random tile from the candidate list
   int index = rand(0, candidates.length - 1);

   // place a tile at that location (remove the entry from
   // the candidate list)
   x, y = candidates[index];
   candidates.remove(index);
   place_tile(x, y);
}

答案 2 :(得分:1)

你的问题是“有机和随机”可能有很多不同的东西。 让我展示两个链接

  • 生成random fractal terrain(查看“多云天空”部分并想象您将其转为黑白,或者在您的情况下为黄色/背景)。
  • 模拟erosion(查看'erode'下的图片)

以上两个样本对我来说是“有机和随机的”,但您可能对此不满意。所以,我认为你必须更好地定义什么是'有机和随机'。

现在,我将按照您对添加新磁贴的指导规则的定义(但不要认为它必然是同一个问题),我将其读作:

  

给出两个形状(假设位图)   找到相对的位置   形状如此数量   触摸边是最大的

我也会假设

  • 不允许重叠
  • 您可以在生成的合并形状中留下洞穴
  • 您可以旋转形状

在这种情况下,您需要测试少于x y的解决方案,并且需要在每个解决方案中进行测试   - 如果有重叠,请将其丢弃   - 如果他们不接触,请丢弃它   - 如果他们触摸,则计算常见的边数 通过扫描所有黄色瓷砖(其数量为konst x * y),可以在恒定时间内完成上述三个测试。

所以,上面的O(n ^ 4)很容易完成,对你来说还不错吗?

答案 3 :(得分:0)

计算双图的随机生成树,即顶点为单元格中心的网格。为此,从网格的中心开始并进行随机深度优先搜索。然后绘制细胞以增加距离中心的树距离。