0

所以我在python中开始了一个简单的roguelike游戏项目,但是我在编辑一个重复列表时遇到了问题。代码如下:

charx = 1
chary = 1
level = [["#","#","#","#","#","#","#"],["#",".",".",".",".",".","#"],["#",".","#",".",".",".","#"],["#","#","#","#","#","#","#"]]
while True:
    move = raw_input("u,d,l or r: ")
    if move=="u":
        if level[chary-1][charx]!="#":
            chary-=1
    elif move=="d":
        if level[chary+1][charx]!="#":
            chary+=1
    elif move=="r":
        if level[chary][charx+1]!="#":
            charx+=1
    elif move=="l":
        if level[chary][charx-1]!="#":
            charx-=1
    display_level=level
    display_level[chary][charx]="@"
    for row in display_level:
        print "".join(row)
    for row2 in level:
        print ",".join(row2)

如您所见,我创建了名为 level 的列表,其中列表中的每个列表都是一行。说明了字符的起始行和列位置。

然后循环询问您是否要向上、向左或向右移动。它会检查路上是否有墙(# 字符)并做出相应的反应。

如您所见,它复制了名为 display_level 的关卡,然后将“@”作为字符放到显示关卡上。然而,问题是改变 display_level 也会无缘无故地改变 level,即使它们是分开的,并且每次循环运行时都会使 display_level=level。

display_level 和 level 然后分别打印,它显示 level 正在沿 display_level 一侧进行编辑,这是不应该发生的。

所以我想知道的是为什么更改 display_level 的一部分会更改级别以及如何修复它。

非常感激

4

3 回答 3

4

没有创建level. 您所做的只是创建对同一列表的另一个引用。

要创建列表的副本,您可以从头到尾对其进行切片:

display_level = level[:]

但对于你的情况,这还不够。您需要复制嵌套列表。在这种情况下,列表推导是最简单的:

display_level = [l[:] for l in level]

更全面的解决方案是使用该copy.deepcopy()函数绝对确保顶级对象和所有包含的对象都是副本:

import copy

# ...

display_level = copy.deepcopy(level)
于 2013-07-17T15:34:23.660 回答
1

将变量分配给另一个变量是引用而不是重复。改为使用copy()

>>> l = range(10)                    # assign original list
>>> l                                # display list (l)   
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a = l                            # assign a to l
>>> a                                # display list (a)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a.remove(4)                      # remove '4' item from a
>>> a                                # display list (a)
[0, 1, 2, 3, 5, 6, 7, 8, 9]          # notice that '4' is gone   
>>> l                                # display list (l)
[0, 1, 2, 3, 5, 6, 7, 8, 9]          # notice that '4' is *also* gone   
>>> import copy                      # import the copy module
>>> b = copy.deepcopy(l)             # create a deepcopy of l called b
>>> b                                # display list (b)
[0, 1, 2, 3, 5, 6, 7, 8, 9]          # notice, '4' is still gone.
>>> l                                # display list (l)
[0, 1, 2, 3, 5, 6, 7, 8, 9]          
>>> b.remove(3)                      # remove '3' item from b
>>> b                                # display list (b)   
[0, 1, 2, 5, 6, 7, 8, 9]             # notice, '3' is gone. 
>>> l                                # display list (l)
[0, 1, 2, 3, 5, 6, 7, 8, 9]          # notice, '3' is still there.

注意:有一些“更简单”的方法或“快捷方式”来复制Martijn 的答案中详述的列表

于 2013-07-17T15:32:27.653 回答
1

您应该通过执行以下操作制作列表列表的新副本:

display_level=[l[:] for l in level]

而不是这个:

display_level=level

否则,您对同一个列表有两个引用,而不是两个单独的列表。

于 2013-07-17T15:33:55.570 回答