【问题标题】:Fill holes on cave generated by cellular automata填充由元胞自动机生成的洞穴
【发布时间】:2026-02-11 11:45:01
【问题描述】:

我正在为游戏生成洞穴。洞穴是由元胞自动机构建的 50x50 矩阵,其中 0(紫色)是墙壁,1(黄色)是空白空间(玩家可以移动的地方)。Here is an example of my output

我用红色圆圈指出了我的问题。墙上有玩家无法触及的“洞”。我试图填补这个漏洞,但我做不到。基本上我想把被0包围的1变成0。

我曾尝试通过这种方法使用 Floodfill 来做到这一点:

首先,我计算从起点 x,y 开始使用填充填充的单元格数量。如果这个计数小于 16 且大于 1,那么我实际上会绘制单元格。

for x in range(0, WIDTH - 1):
    for y in range(0, HEIGHT - 1):
        number_cells_paint = floodfill_count(cellmap, x, y, number_cells_paint)
        if 16 > len(number_cells_paint) > 1:
            floodfill(cellmap, x, y)

        number_cells_paint = []

number_cells_paint 是一个数组,我在 floodfill_count 中添加我访问的每个单元格。这就是我认为在递归算法中计数的方式,可能是我的错误所在。

这是 floodfill_count:

def floodfill_count(cellmap, x, y, number_cells_paint):
  cellmap_aux = cellmap
  if len(number_cells_paint) > 16:
      return number_cells_paint

  if cellmap_aux[x, y] == 1:
      cellmap_aux[x, y] = 0
      number_cells_paint.append(cellmap[x, y])

      if x > 0 and cellmap[x - 1, y] == 1:
          floodfill_count(cellmap_aux, x - 1, y, number_cells_paint)

      if x < WIDTH - 1 and cellmap[x + 1, y] == 1:
          floodfill_count(cellmap_aux, x + 1, y, number_cells_paint)

      if y > 0 and cellmap[x, y - 1] == 1:
          floodfill_count(cellmap_aux, x, y - 1, number_cells_paint)

      if y < HEIGHT - 1 and cellmap[x, y + 1] == 1:
          floodfill_count(cellmap_aux, x, y + 1, number_cells_paint)

      if x < WIDTH - 1 and y < HEIGHT - 1 and cellmap[x + 1, y + 1] == 1:
          floodfill_count(cellmap_aux, x + 1, y + 1, number_cells_paint)

      if x > 0 and y < HEIGHT - 1 and cellmap[x - 1, y + 1] == 1:
          floodfill_count(cellmap_aux, x - 1, y + 1, number_cells_paint)

      if x < WIDTH - 1 and y < HEIGHT - 1 and cellmap[x + 1, y - 1] == 1:
          floodfill_count(cellmap_aux, x + 1, y - 1, number_cells_paint)

      if x > 0 and y < HEIGHT - 1 and cellmap[x - 1, y - 1] == 1:
          floodfill_count(cellmap_aux, x - 1, y - 1, number_cells_paint)


  return number_cells_paint

和洪水填充:

def floodfill(cellmap, x, y):

  if cellmap[x, y] == 1:
      cellmap[x, y] = 0

      if x > 0 and cellmap[x - 1, y] == 1:
          floodfill(cellmap, x - 1, y)

      if x < WIDTH - 1 and cellmap[x + 1, y] == 1:
          floodfill(cellmap, x + 1, y)

      if y > 0 and cellmap[x, y - 1] == 1:
          floodfill(cellmap, x, y - 1)

      if y < HEIGHT - 1 and cellmap[x, y + 1] == 1:
          floodfill(cellmap, x, y + 1)

      if x < WIDTH - 1 and y < HEIGHT - 1 and cellmap[x + 1, y + 1] == 1:
          floodfill(cellmap, x + 1, y + 1)

      if x > 0 and y < HEIGHT - 1 and cellmap[x - 1, y + 1] == 1:
          floodfill(cellmap, x - 1, y + 1)

      if x < WIDTH - 1 and y < HEIGHT - 1 and cellmap[x + 1, y - 1] == 1:
          floodfill(cellmap, x + 1, y - 1)

      if x > 0 and y < HEIGHT - 1 and cellmap[x - 1, y - 1] == 1:
          floodfill(cellmap, x - 1, y - 1)


  return cellmap

这种 Floodfill 实现有效,我之前尝试过,所以我的问题在于 Floodfill_count。

有了这个代码我有this final output

【问题讨论】:

  • 小于 16 大于 1 是我选择的数字。如果我不限制绘制的单元格数量,它将绘制所有地图,我不想要这个。
  • 我们为什么不在坐标 (25,25) 处填充 "hole"
  • 我只是指出了一些漏洞作为这个特定输出的示例,不是全部,但是是的,我也想填补那个漏洞。
  • 什么是 floodfill_mine? (在给定的代码示例中没有定义)
  • 对不起,我的错误。这是较旧的函数名称。现在已经解决了,谢谢。

标签: python algorithm flood-fill cellular-automata


【解决方案1】:

问题出在cellmap_aux = cellmap这行代码。 Python 指定列表作为参考,因此对cellmap_aux 的任何更改都将是cellmap 中的更改(因此floodfill_count 绘制了所有字段)。应该改用cellmap_aux = cellmap.copy()

【讨论】: