基于另一个列表修改列表的问题?

时间:2014-11-29 10:44:30

标签: python list flood-fill minesweeper

您好我是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

1 个答案:

答案 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