Python 二维网格上的洪水填充

Python 二维网格上的洪水填充,python,flood-fill,Python,Flood Fill,作为游戏的一部分,我正在构建一个2d网格,在这里我需要找出网格上的两个项目是否连接。例如,陷阱和墙壁挡住了去路,所以基本上我最终得到了网格中被墙壁和陷阱分开的部分,所以我从网格上的点P开始填充网格,以找出哪些点属于与P相同的部分 下面是代码的基本功能: 1) 基于输入文件构建网格(works) 2) 找到起点p(工作) 3) 来自p的洪水填充(不工作) 4) 打印网格以检查其是否正确(有效) 网格构建得很好,也找到了起点,但洪水填充功能不起作用。有什么想法吗 输入文件示例: 7 9 ######

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

下面是代码的基本功能:

1) 基于输入文件构建网格(works)

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]?后一种方法会产生超出范围的错误。

你弄乱了坐标的顺序。除了fill函数外,几乎所有地方都使用grid(Y,X)。参见初始调用:在x=4y=6处找到P,即i=6j=4。然后调用fill_connected(4,6)。这是右边墙上的一个点


如果没有充分的理由需要额外的坐标,我只会处理列表索引。

谢谢你的想法,我确实把这些搞砸了。我已经更新了代码(希望)在这个意义上是正确的。但是我现在得到了一个超出范围的错误,你介意再看一下更新的代码吗?谢谢。我在一行上交换了索引(fill_connected的递归调用),现在它可以工作了。但为什么那里的情况与其他地方不同呢?当它工作时,它现在在那里。嗨!首先,您总是使用网格[heightIndex][widthIndex],在这里,我总是代表heightIndex,而j代表widthIndex。在编写“grid=[[Node(i,j,None)…”时,您将i(height)分配给x(width)等,这就是您的问题。现在,您编写了“grid=[[Node(j,i,None)…”,这使得xy与ij相同。因此,您再次遇到了问题,将p[]作为第二条注释,用于分隔:旧代码,调用fill_connected()四次使用x,y+/-1要优雅得多。另外,在其他代码中定义函数也不太好。最后一个建议是,如前所述:我会忘记x和y,只处理I和j。