随机瓷砖布局

发布于 2024-09-06 15:34:37 字数 318 浏览 7 评论 0原文

我需要以一种看起来有机且随机的方式将瓷砖放置在从中心点辐射的大网格上。新的图块需要在网格上找到一个至少接触其他 1 个图块的开放空间。

谁能指出我正确的方向,以解决任何可能对此有所帮助的事情? 或者我可以读到一些类似的基本概念?

例如,在这张图片中,已经创建了一个形状(黄色),我可能会收到一个新的图块,可能是 1x1、2x2 或 3x3。尝试找到一种好方法来找出可以放置新图块的位置,以便它能够接触最大数量的当前图块。

图片: 替代文本 http://osomer.com/grid.JPG

I need to place tiles on a large grid radiating from a central point in a way that looks organic and random. New tiles will need to find an open space on the grid that is touching at least 1 other tile.

Can anyone point me in the right to direction to anything that might help with this?
Or some basic concepts I can read up on that are in this vein?

For example, in this picture, there is a shape already created (yellow) and I may be receiving a new tile, that may be 1x1, 2x2, or 3x3. Trying to find a good way to figure out where I can place the new tile so that it will be touching the maximum amount of current tiles.

Picture:
alt text http://osomer.com/grid.JPG

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一口甜 2024-09-13 15:34:37

或者,您可以通过黄色瓷砖“侵蚀”蓝色/背景来解决此问题。为此,在每一步中,让一个黄色图块将一个固定数字添加到在基本方向上与其相邻的所有背景图块的“侵蚀总和”E(也许可能是该值的一小部分)到对角相邻的背景瓷砖)。

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

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

您可以通过让侵蚀总和在每次迭代中持续存在来节省重新计算侵蚀总和的时间,仅当您添加新图块时,增加其周围的侵蚀总和(简单的 +=)。在这一点上,它与另一个建议的答案本质上是相同的,尽管具有不同的观点/哲学。

侵蚀总和E的示例网格,直接基数邻居为+4,对角邻居为+1:

侵蚀总和 http://img199.imageshack.us/img199/4766/erosion.png

具有较高 E 的最有可能被“侵蚀”掉;例如,在这个例子中,西面和南面的两个小海湾最有可能被黄色侵蚀掉,其次是北面和东面的较小海湾。最不可能的是那些几乎一角触及黄色的球。您可以通过为每个图块分配从 0 到 E 的随机数并侵蚀具有最高随机数的那个来决定哪一个,或者进行简单的加权随机选择,或者通过您的任何决策方法选择。

Alternatively, you could approach this problem as the yellow tiles "eroding" away at the blue/background. To do this, at every step, have a yellow tile add a fixed number to the "erosion sum" E of all of the background tiles neighboring it in a cardinal direction (and perhaps maybe a fraction of that to the background tiles neighboring it diagonally).

Then, when it comes time to place a new tile, you can, for each background tile, pick a random number from 0 to E; the greatest one is "eroded" away. Alternatively, you could do a simple weighted random choice, with E being their weights.

For 2x2 or 3x3 tiles, you can pick only from tiles that suitably "fit" a 2x2 or 3x3 square in it (that is, a 2x2 or 3x3 the eroded tile on its edge, so that it doesn't cause overlap with already-placed tiles). But really, you're never going to get something looking as natural as one-by-one erosion/tile placement.

You can save time recalculating erosion sums by having them persist with each iteration, only, when you add a new tile, up the erosion sums of the ones around it (a simple +=). At this point, it is essentially the same as another answer suggested, albeit with a different perspective/philosophy.

A sample grid of Erosion Sums E, with direct cardinal neighbors being +4, and diagonal neighbors being +1:

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

The ones with a higher E are most likely to be "eroded" away; for example, in this one, the two little inlets on the west and south faces are most likely to be eroded away by the yellow, followed by the smaller bays on the north and east faces. Least likely are the ones barely touching the yellow by one corner. You can decide which one either by assigning a random number from 0 to E for each tile and eroding the one with the highest random number, or doing a simple weighted random selection, or by any decision method of your choice.

梦幻的心爱 2024-09-13 15:34:37

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

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

为了避免在图块网格中创建孔,请增加根据已填充的相邻图块数量选择网格位置的概率(因此,如果只有一个相邻图块已被填充,则其可能性较低。如果它们都已填充) ,它的概率非常高)。

在伪代码中:

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);
}

For purely random, you start with an empty grid and a "candidate" list (also empty).

Place the first tile in the centre of the grid, then add each adjacent tile to the one you just placed into the "candidate" list. Then, each turn, choose a random entry in the "candidate" list and place a tile there. Look at each adjancent grid location next to where you just placed the tile, and for each one that is also empty, put it on the "candidate" list for the next time around (if not already there).

To avoid creating holes in your tile grid, increase the probability of selecting a grid location based on the number of adjacent tiles that are already filled (so if only one adjacent tile is already filled, it has low probably. If they're all filled, it'll have a very high probability).

In pseudo code:

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);
}
折戟 2024-09-13 15:34:37

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

  • 生成随机分形地形的链接(查看“多云天空”部分并想象一下你把它变成黑白,或者在你的情况下变成黄色/背景)。
  • 模拟侵蚀(查看“侵蚀”下的图像)

上面的两个示例是“有机和对我来说是随机的,但你可能对这些不满意。所以,我认为你必须更好地定义什么是“有机和随机”。

现在,我将采用您对添加新图块的指导规则的定义(但认为这不一定是同一个问题),我将其解读为:

给定两个形状(假设是位图)
找到相对位置
形状使得数量
接触侧面最多

我还将假设

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

在这种情况下,您需要测试的解决方案少于xy在每个你需要的
- 如果有重叠则丢弃它
- 如果它们不接触就丢弃它
- 如果它们接触,则计算公共边的数量
通过扫描所有黄色图块(数量为 konst
x*y),上述所有三个测试都可以在恒定时间内完成。

因此,上述可以在 O(n^4) 内轻松完成,是这样对你来说够好吗?

The problem with your question is that 'organic and random' can be many different things.
Let me show two links

  • generating random fractal terrain (look at section 'Cloudy Skies' and imagine that you turn it to b/w, or in your case yellow/background).
  • simulating erosion (look at the image under 'erode')

The two above samples are 'organic and random' to me, but you might not be satisfied with those. So, I think you will have to better define what is 'organic and random'.

For now, I'll take your definition of the guiding rule for adding new tiles (but don't think it is necessarily the same problem), which I read as:

Given two shapes (assuming bitmaps)
find the relative position of the
shapes such that the number of
touching sides is maximum

I will also assume

  • overlap is not allowed
  • you can leave holes inside the resulting, merged shape
  • you can not rotate shapes

Under such conditions you need to test less then xy solutions and in each you need to
- discard it if there is an overlap
- discard it if they do not touch
- if they touch then count the number of edges that are common
All three of the above tests can be done in constant time by scanning all the yellow tiles (number of which is konst
x*y)

So, the above can be easily done in O(n^4), is that good enough for you?

玻璃人 2024-09-13 15:34:37

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

Compute a random spanning tree for the dual graph, that is, the grid whose vertices are the centers of your cells. For that, start at the center of the grid and do a random depth-first search. Then plot cells fro increasing tree distance from the center.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文