我在使用类时遇到了意外的列表赋值语句。

huangapple go评论64阅读模式
英文:

I'm having unintended list assignment statements when I use classes

问题

class Board():
    """Tic Tac Toe游戏的Board类。Board可以是3x3、4x4或5x5。"""
    def __init__(self, size):
        # 偏移1以使索引更容易
        self.board = [None]
        self.board_size = size
    
    def create_board(self):
        """创建一个具有board_size参数维度的空白棋盘。"""
        row = [None] + ([' '] * self.board_size)
        for i in range(self.board_size):
            self.board.append(row)
    
    def draw_mark(self, choice, player_mark):
        """如果空间未被占用,则在玩家选择的位置上绘制x或o。
        
           Choice是包含要放置标记的空间坐标的列表[row, column]。
           
           如果移动有效,则返回True,否则返回False。
        """
        row = choice[0]
        column = choice[1]
        if self.board[row][column] == ' ':
            self.board[row][column] = player_mark
            return True
        else:
            return False
    
oBoard = Board(3)
oBoard.create_board()
oBoard.draw_mark([1, 1], 'x')
print(oBoard.board)

当我实例化一个board对象并在该对象上调用draw_mark方法时,我期望以下输出:

[None, [None, 'x', ' ', ' '], [None, ' ', ' ', ' '], [None, ' ', ' ', ' ']]

但是代码产生以下输出:

[None, ['x', ' ', ' ', ' '], ['x', ' ', ' ', ' '], ['x', ' ', ' ', ' ']]

我尝试在Python shell中将网格创建为全局变量,然后尝试直接赋值,这样会产生期望的结果。

我的问题是,我的类实现中有什么原因导致发生这些额外的赋值?

英文:
class Board():
    """Board class for Tic Tac Toe game. Board can be 3x3, 4x4, or 5x5."""
    def __init__(self, size):
        # offset by 1 to make indexing easier
        self.board = [None]
        self.board_size = size
    def create_board(self):
        """Create an empty board with dimensions of board_size argument."""
        row = [None] + ([' '] * self.board_size)
        for i in range(self.board_size):
            self.board.append(row)
    def draw_mark(self, choice, player_mark):
        """Draw an x or o on the space chosen by the player if the space is
           unoccupied.
        
           Choice is a list containing the coordinates of the space to place a
           mark [row, column].
           
           Return True if move was valid, return False if not.
        """
        row = choice[0]
        column = choice[1]
        if self.board[row][column] == ' ':
            self.board[row][column] = player_mark
            return True
        else:
            return False
    
oBoard = Board(3)
oBoard.create_board()
oBoard.draw_mark([1, 1], 'x')
print(oBoard.board)

When I instantiate an board object and call the draw_mark method on that object I expect this as the output:

[None, [None, 'x', ' ', ' '], [None, ' ', ' ', ' '], [None, ' ', ' ', ' ']]

However the code produces this output:

[None, ['x', ' ', ' ', ' '], ['x', ' ', ' ', ' '], ['x', ' ', ' ', ' ']]

I tried creating the grid as a global variable in the python shell and attempting the assignment directly and that produced the desired result.

My question is what is it about my implementation of classes that is causing these extra assignments to happen?

答案1

得分: 0

你创建了一行,然后通过多次附加相同的单行来构建表格。对一行的更改会影响所有行,因为它们都是相同的底层列表。你应该为表格中的每一行创建一个新的列表。更改在 create_board 方法中。

class Board():
    """Tic Tac Toe游戏的Board类。板可以是3x3、4x4或5x5。"""
    def __init__(self, size):
        # 通过加1来进行偏移,以使索引更容易
        self.board = [None]
        self.board_size = size

    def create_board(self):
        """创建具有board_size参数维度的空白板。"""
        for i in range(self.board_size):
            self.board.append([None] + ([' '] * self.board_size))

    def draw_mark(self, choice, player_mark):
        """如果空格未被占用,则在玩家选择的空格上绘制x或o。
        
           Choice是包含要放置标记的空格的坐标的列表 [row, column]。
           
           如果移动有效,则返回True,否则返回False。
        """
        row = choice[0]
        column = choice[1]
        if self.board[row][column] == ' ':
            self.board[row][column] = player_mark
            return True
        else:
            return False

oBoard = Board(3)
oBoard.create_board()
oBoard.draw_mark([1, 1], 'x')
print(oBoard.board)

输出

[None, [None, 'x', ' ', ' '], [None, ' ', ' ', ' '], [None, ' ', ' ', ' ']]
英文:

You create a single row and then build the table by appending that same single row many times. A change to one row is seen by all rows because they are the same underlying list. You should create a new list for each row in the table. The change is in the create_board method.

class Board():
    """Board class for Tic Tac Toe game. Board can be 3x3, 4x4, or 5x5."""
    def __init__(self, size):
        # offset by 1 to make indexing easier
        self.board = [None]
        self.board_size = size
    def create_board(self):
        """Create an empty board with dimensions of board_size argument."""
        for i in range(self.board_size):
            self.board.append([None] + ([' '] * self.board_size))
    def draw_mark(self, choice, player_mark):
        """Draw an x or o on the space chosen by the player if the space is
           unoccupied.
        
           Choice is a list containing the coordinates of the space to place a
           mark [row, column].
           
           Return True if move was valid, return False if not.
        """
        row = choice[0]
        column = choice[1]
        if self.board[row][column] == ' ':
            self.board[row][column] = player_mark
            return True
        else:
            return False
    
oBoard = Board(3)
oBoard.create_board()
oBoard.draw_mark([1, 1], 'x')
print(oBoard.board)

Output

[None, [None, 'x', ' ', ' '], [None, ' ', ' ', ' '], [None, ' ', ' ', ' ']]

huangapple
  • 本文由 发表于 2023年6月19日 05:36:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76502618.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定