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