0

使用 Python 和类,我正在尝试制作像战舰这样的游戏,主要用于练习。所以我做了一个游戏板对象,你“看到”它,然后“改变”它。(稍后我会将“create”与 init 合并)

但是在我的“更改”应用于每一行的地方发生了一些奇怪的事情......这是代码:

class Board:
    'Game Board'
    topMarkers = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
    sideMarkers = list(range(0, 26))


    def __init__(self,h,w): #Makes the map
        self.height = h
        self.width = w


    def create(self): #Makes a map for displaying
        wave = '~'
        self.row = []
        self.column = []
        #self.column = wave * self.width # If width is 4, column is now '~~~~'

        for c in range(self.width):
            self.column.append(wave)


        raw_input(self.column)

        for r in range(self.height): #
            self.row.append(self.column)

        raw_input(self.row)

    def showGrid(self):

        print self.row

    def changeRow(self, y, x):
        self.row[1][2] = "Test"







yourShipsMap = Board(4,3)

theirShipsMap = Board(4,7)


theirShipsMap.create()

theirShipsMap.changeRow(2,2)
theirShipsMap.showGrid()

当我运行它时,它不仅在第一个列表,第二个索引,而且在每个列表,第二个索引中写入“测试”。知道为什么要这样做吗?

我讨厌当我停止一起编程一个月并忘记一切时。

4

2 回答 2

3

您只创建一列,然后将其附加到您的行中。将列表附加到另一个列表不会生成新副本,而是会一遍又一遍地重复使用相同的列表。

通过使用[:]切片语法或list()调用来附加副本:

for r in range(self.height): #
    self.row.append(self.column[:])

以下是发生在您身上的示例:

>>> column = [1, 2]
>>> row = []
>>> row.append(column)
>>> row.append(column)
>>> column[0] = 'foobar'
>>> row
[['foobar', 2], ['foobar', 2]]

另一方面,如果我们使用副本,则当我们更改原件时,副本不会更改:

>>> row = []
>>> row.append(list(column))
>>> row.append(column[:])
>>> row
[['foobar', 2], ['foobar', 2]]
>>> column[0] = 1
>>> row
[['foobar', 2], ['foobar', 2]]

在上面的示例中,我使用了两种方法来创建原始列列表的(浅)副本。如果您需要创建深层副本(包含其他可变项的列表,例如列表或字典),请改用该copy.deepcopy实用程序

于 2012-07-27T09:14:10.193 回答
2
for r in range(self.height): #
    self.row.append(self.column)

您继续附加相同的列表对象,如果更新为一个,则将在每一行中看到。

试试这个:

self.row = [['~'] * self.width for r in xrange(self.height)]

这将创建一个列表列表,其中所有元素相互独立。

于 2012-07-27T09:13:16.200 回答