洪水填充2d网格

时间:2014-10-03 06:39:38

标签: python flood-fill

作为游戏的一部分,我正在构建一个2d网格,我需要找出网格上的两个项目是否已连接。例如有阻挡方式的陷阱和墙壁基本上我最终得到网格的独立部分被墙壁和陷阱分开,所以我从网格上的点P开始填充网格以找出哪些点属于与P相同的部分。

以下是代码的基本功能:

1)根据输入文件(作品)构建网格

2)找到起点P(有效)

3)从P(不工作)填充洪水

4)打印网格以检查它是否正确(正常)

网格构建得很好,也可以找到起点,但是填充功能不起作用。有什么想法吗?

示例输入文件:

7 9
#######
#..#G.#
#...TG#
#.....#
#...G.#
#...#.#
###.P.#
#G#.TG#
#######

(更新,现在运行正常)运行代码打印以下内容:

Start point at: [4, 6] (i.e. in grid[6][4])
[0, '#'][2, '#'][2, '#'][0, '#'][2, '#'][2, '#'][0, '#']
[2, '#'][1, '.'][1, '.'][2, '#'][1, 'G'][1, '.'][2, '#']
[2, '#'][1, '.'][1, '.'][1, '.'][2, 'T'][1, 'G'][2, '#']
[2, '#'][1, '.'][1, '.'][1, '.'][1, '.'][1, '.'][2, '#']
[2, '#'][1, '.'][1, '.'][1, '.'][1, 'G'][1, '.'][2, '#']
[2, '#'][1, '.'][1, '.'][1, '.'][2, '#'][1, '.'][2, '#']
[0, '#'][2, '#'][2, '#'][1, '.'][1, 'P'][1, '.'][2, '#']
[0, '#'][0, 'G'][2, '#'][1, '.'][2, 'T'][1, 'G'][2, '#']
[0, '#'][0, '#'][0, '#'][2, '#'][0, '#'][2, '#'][0, '#']

(更新,工作正常)以下是代码本身:

if __name__ == "__main__":

  class Node:
    UNEXPLORED = 0
    CONNECTED = 1
    VISITED = 2

    def __init__(self, x, y, value):
      self.x = x
      self.y = y
      self.state = Node.UNEXPLORED
      self.value = value

    def neighbor_with(self, node):
      x_dist = abs(self.x - node.x)
      y_dist = abs(self.y - node.y)
      if x_dist == 1 and y_dist == 0:
        return True
      elif x_dist == 0 and y_dist == 1:
        return True
      else:
        return False

    def trap_or_wall(self):
      if self.value == "T" or self.value == "#":
        return True
      else:
        return False

    def __str__(self):
      return str([self.state,self.value])



  with open('in1.txt', 'r') as f:

    row = f.readline()
    dimensions = row.split(" ")
    w = int(dimensions[0])
    h = int(dimensions[1])

    grid = [[Node(j,i, None) for i in range(w)] for j in range(h)]

    #set grid
    for i in range(h):
      row = f.readline()
      for j in range(w):
        grid[i][j].value = row[j]

    #find P
    p = []
    for i in range(h):
      for j in range(w):
        if grid[i][j].value == "P":
          p = [grid[i][j].y, grid[i][j].x]
    print("Start point at: {:} (i.e. in grid[{:}][{:}])".format(p,p[1],p[0]))

    #define function to flood fill the connected part
    def fill_connected(matrix, node):
      if node.state == Node.UNEXPLORED:
        node.state = Node.VISITED
        if not node.trap_or_wall():
          node.state = Node.CONNECTED
          #recursively for neighbors
          for i in range(h):
            for j in range(w):
              if matrix[i][j].neighbor_with(node):
                fill_connected(matrix, grid[i][j])

    #flood fill from P
    fill_connected(grid, grid[p[1]][p[0]])

    #check grid, i.e. print it
    for i in range(h):
      for j in range(w):
        print(grid[i][j], end="")
      print("\n", end="")
    print()

修改

我更新了代码,以便按照坐标的顺序来解决,x = 4和y = 6现在应该是grid [6] [4]。之后我修正了其他错误,但我仍然不明白一件事:在洪水填充函数定义的最后一行,为什么它必须是grid [i] [j]而不是grid [j] [i ]?后者产生超出范围的错误。

1 个答案:

答案 0 :(得分:2)

你搞砸了坐标的顺序。除填充函数外,几乎在任何地方都使用网格(Y,X)。看初始调用:在x = 4 y = 6时找到P,即i = 6 j = 4。然后你调用fill_connected(4,6)。这是右墙上的一个点。

如果没有合理的额外坐标原因,我只会处理列表索引。