您好我是python的新手,我目前正在尝试构建一个扫雷游戏。我制作了2个列表,1个显示给玩家(字段),1个包含地雷(雷区)。我要求玩家选择坐标,然后程序检查周围是否有地雷,并使用以下代码在地雷周围填充地图:
def floodfill(field, minefield, x, y)
list1 = [(x, y)]
while True:
a, b = list1.pop()
field[b][a] = 'W'
list2 = [(a, b - 1), (a, b + 1), (a - 1, b), (a + 1, b)]
for element in list2:
x2 = element[0]
y2 = element[1]
if y2 >= len(field) or x2 >= len(field[0]) or y2 < 0 or x2 < 0:
continue
if minefield[y2][x2] == 'O':
list1.append(element)
if not list1:
break
return field
所以基本上我试图通过查看“雷区”来检查所选坐标周围是否有地雷。列出然后修改&#39;字段&#39;根据&#39; minefield&#39;列出名单。如果在给定坐标周围有任何非防雷块,程序会阻塞我的问题。
例如,当我运行它时,没有任何事情发生。
minefield = [['O', 'O'], ['x', 'x']] # field is the same without xs
x = 0
y = 0
但是有了这些:
minefield = [['O', 'x'], ['x', 'x']] # field is the same without xs
x = 0
y = 0
它返回:
field = [['W', 'O'], ['O', 'O']] # Os are covered mines
答案 0 :(得分:1)
问题似乎在
if minefield[y2][x2] == 'O':
因为你不会在循环中修改雷区数组,所以它总是会有一个&#39; O&#39;在每个for循环中,一个坐标将附加到list1。 您可以在(y2,x2)处检查雷区和字段的值,如果两者都是&#39; O&#39;然后将它附加到list1:
if minefield[y2][x2] == 'O' and field[y2][x2] == 'O':
运行带有上述修改的代码和此数据后:
field = [['O', 'O'], ['O', 'O']]
minefield = [['O', 'O'], ['x', 'x']]
x = 0
y = 0
print floodfill(field, minefield, x, y)
它返回:
[['W', 'W'], ['O', 'O']]
这样做非常危险
while True:
...
因为,如所观察到的,程序可以进入无限循环。应该有某种迭代限制器,当然足够大,算法可以进行正确的计算,并且足够小,以至于如果代码中存在错误,它将在一段时间后完成。因此,在这种情况下,限制应设置为至少与整个雷场的大小一样大的值(如果整个矿场中没有地雷的情况)。如果超出迭代限制,可能会打印出适当的警告 - 调试和信息目的。
def floodfill(field, minefield, x, y):
list1 = [(x, y)]
max_iters = 100 # it should be at least as big as the size of whole minefield
# or more dynamic/generic approach based on actual minefield size:
# max_iters = len(minefield) * len(minefield[0])
while True and max_iters > 0:
max_iters -=1
a, b = list1.pop()
field[b][a] = 'W'
list2 = [(a, b - 1), (a, b + 1), (a - 1, b), (a + 1, b)]
for element in list2:
x2 = element[0]
y2 = element[1]
if y2 >= len(field) or x2 >= len(field[0]) or y2 < 0 or x2 < 0:
continue
if minefield[y2][x2] == 'O' and field[y2][x2] == 'O':
list1.append(element)
if not list1:
break
if max_iters <= 0:
print "Iterations limit exceeded"
return field