我正在制作一个小行星生成器,该生成器将创建bool
s的2D数组。
生成器采用int
参数size
,该参数应确定2D数组中将有多少True
个像元。
如何保证输出数组中没有孔并且True
的单元格数量正确?
我看到了问题Randomly Generating Clusters in a 2d Array,但是我想不出一种将其应用于用例的方法,因为我需要知道必须生成的切片数量。
在下面的代码中,我随机放置了图块,然后使用细胞自动机进行平滑处理并确保没有孔,但是问题是要保留正确数量的True
个单元,尤其是因为取出随机的{{ 1}}大小正确的单元可能会产生孔。
True
该功能通常def create_shape(size, seed):
# init rng with seed
rng = random.Random(seed)
# initial grid values empty and full mass left
# make the grid size by size so any shape could fit
grid = [[False for x in range(size)] for y in range(size)]
mass_remaining = size
# guarantee the center is something
center = size // 2
grid[center][center] = True
mass_remaining -= 1 # remember to reduce available mass
# generate random values
for x in range(size):
for y in range(size):
# skip the already filled in center
if x == y == center:
continue
# assign random value
value = bool(rng.randint(0, 1))
grid[y][x] = value
# remember to reduce mass
if value:
mass_remaining -= 1
# smoothen things out with cellular automata neighbor checking
for x in range(size):
for y in range(size):
# skip the center
if x == y == center:
continue
# get neighbors
# set neighbors is the count of neighbors set to True
set_neighbors = 0
for i in range(-1, 2):
for j in range(-1, 2):
# skip counting self
if i == j == 0:
continue
nx, ny = x + i, y + j
if 0 <= nx < size and 0 <= ny < size:
# only get in-range cells
if grid[ny][nx]:
set_neighbors += 1
# more than 3 -> become True, less than 3 -> become False
if set_neighbors > 3:
grid[y][x] = True
mass_remaining -= 1
elif set_neighbors < 3:
grid[y][x] = False
mass_remaining += 1
else:
# otherwise leave it the same
pass
# find out how well the mass is staying "in-budget"
print(mass_remaining)
return grid
会产生整个范围的不同剩余质量,例如,使print
处于“债务”状态或多于-14
。如果该功能正常运行,我希望输出为42
。
例如,这样的输出...
0
...很坚固,但是设置的磁贴太多。
答案 0 :(得分:2)
对于您的问题,没有一个唯一的肯定答案,特别是因为基本任务(“生成2D小行星形状”)的规格不足且从根本上讲是主观的。当然,原则上您总是可以生成 N 瓷砖实体形状,例如通过从左上角开始并从左到右并自上而下添加磁贴,直到其中有 N 个,但所得形状可能不是一个非常逼真的或“漂亮”的小行星。
因此,除了详细描述单个算法之外,我只建议一些可行的方法,让您选择最合适的方法:
从单个中心磁贴开始,并随机添加与现有磁贴相邻的新磁贴。在添加每个磁贴之前,请检查添加是否没有在小行星内部留下任何孔;如果可以的话,请选择另一个图块。 (连接检查可能是该算法最昂贵的部分,尽管有多种方法可以对其进行优化。特别是,您可以首先检查新图块的现有直接邻居;如果它们都是连续的,则新的图块无法桥接边缘的两个独立部分。)
与上述相同,但是将连接检查延迟到最后。如果发现任何孔,请将小行星边缘的瓷砖移到内部以填充它们。
将midpoint displacement算法应用于圆。也就是说,使用该算法生成半径的随机数组(两端的半径相同),然后将这些半径用作从任意选择的中心点到小行星表面的距离,就像绘制一个radar graph。这不会为您提供 N 个图块的确切区域,但是您始终可以按比例放大或缩小半径,直到获得所需的大小为止。产生的形状将始终为star-convex,因此没有孔。 (这对于较大的 N 可能是最好的。这种方案的一个优势是,它也将以一种相当简单有效的方式推广到3D形状:只需从随机多面体开始并应用中点到面部的位移。)
使用任何会通常生成无孔小行星的算法。然后检查是否有孔,如果有,请重新启动。只要重启的概率足够低,此rejection sampling方法就将非常有效。
答案 1 :(得分:0)
自上而下的技术是: