在Python中为7x7板制作撤销函数
我目前正在尝试编写一个名为Pah Tum的游戏。游戏包括一个7x7的棋盘。对于board,我刚刚创建了一个包含7个列表的列表,每个列表包含7个元素,基本上我只是将每一行做成一个列表,并将它们合并成一个大列表:在Python中为7x7板制作撤销函数,python,list,append,undo,Python,List,Append,Undo,我目前正在尝试编写一个名为Pah Tum的游戏。游戏包括一个7x7的棋盘。对于board,我刚刚创建了一个包含7个列表的列表,每个列表包含7个元素,基本上我只是将每一行做成一个列表,并将它们合并成一个大列表: board = [[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0
board = [[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0]]
游戏应该有一个撤销功能,使玩家能够返回一步。我想我可以把整个板添加到一个单独的列表中,然后用它返回一步
if input == 'u' or input == 'U':
board = board_list[-1]
del board_list[-1]
在此之前,它是有效的,但由于某种原因,board_列表(我将当前board添加到的列表)始终作为一个整体更新,这意味着每个元素都会发生变化并成为新的board
如果我有
#board = [[0, 'B'], [0, 0]]
board_list.append(board)
.
.
.
#board = [[0, 'B'], [0, 'B']]
board_list.append(board)
在第一次追加之后,我得到
board_list = [[[0, 'B'], [0, 0]]]
第二个留给我的是
board_list = [[[0, 'B'], [0, 'B']], [[0, 'B'], [0, 'B']]]
我不知道为什么会这样。我搜索了类似的问题,但我只看到画布的撤消功能,我不确定是否可以在这种情况下使用它们。当您将
图板
附加到图板列表
时,您正在添加对原始图板
的引用。也许更好的选择是在移动时为更改的单元格添加上一个状态:
moves.append([x, y, board[x][y]])
然后,当您撤消时,将重新应用该状态:
undo_move = moves[-1]
board[undo_move[0]][undo_move[1]] = undo_move[2]
del moves[-1]
或者更像蟒蛇:
x, y, board[x][y] = moves.pop()
或者,您可以制作整个电路板的副本并将其存储在列表中。当您将
电路板
附加到电路板列表
时,您正在添加对原始电路板的引用。也许更好的选择是在移动时为更改的单元格添加上一个状态:
moves.append([x, y, board[x][y]])
然后,当您撤消时,将重新应用该状态:
undo_move = moves[-1]
board[undo_move[0]][undo_move[1]] = undo_move[2]
del moves[-1]
或者更像蟒蛇:
x, y, board[x][y] = moves.pop()
或者,您可以制作整个线路板的副本,并将其存储在列表中。为了创建线路板副本列表,您需要为您的线路板类实现深度复制方法。否则,您所要做的就是一遍又一遍地复制同一个指针。Python通过引用传递,这就是问题的根源。
实现一个新方法,创建一个与当前板具有相同字段的新板,并从该方法返回指向该板的指针。
我建议你读一些关于浅层和深层副本的书。您可以找到更多详细信息。为了创建线路板副本列表,您需要为线路板类实现深度复制方法。否则,您所要做的就是一遍又一遍地复制同一个指针。Python通过引用传递,这就是问题的根源。
实现一个新方法,创建一个与当前板具有相同字段的新板,并从该方法返回指向该板的指针。
我建议你读一些关于浅层和深层副本的书。您可以找到更多详细信息。您正在将对原始板的引用添加到板列表中,而不是板的副本,但我在更改“0”时使用了相同的变量“board”,创建新的板变量是否有帮助?您正在将对原始板的引用添加到板列表中
,不是Board的副本,但我在更改“0”时使用了相同的变量“Board”,制作一个新的Board变量会有帮助吗?好的,我将尝试实现它。这应该不是问题,谢谢你的快速回答!好的,我尝试使用deepcopy,它确实起了作用,但我认为实施您的方法会更好,因为这样会使“移动”列表没有那么大,而且可以工作。再次感谢您。您可以简单地执行x,y,board[x][y]=moves.pop()
@StefanPochmann-Bah,而不是这三行撤销操作。当然,您可以,很好的一点,我认为在执行类似操作时,所有的更改都同时发生,因此,执行此操作时,x
和y
将在board[x][y]
部分中未定义,尽管在测试之后,它们确实是在board[x][y]
设置为最后一个之前设置的value@NickA是的,我认为这是一个特别好的“把戏”用法。很高兴您选择了正确的存储顺序:-)好的,我将尝试实现这一点。这应该不是问题,谢谢你的快速回答!好的,我尝试使用deepcopy,它确实起了作用,但我认为实施您的方法会更好,因为这样会使“移动”列表没有那么大,而且可以工作。再次感谢您。您可以简单地执行x,y,board[x][y]=moves.pop()
@StefanPochmann-Bah,而不是这三行撤销操作。当然,您可以,很好的一点,我认为在执行类似操作时,所有的更改都同时发生,因此,执行此操作时,x
和y
将在board[x][y]
部分中未定义,尽管在测试之后,它们确实是在board[x][y]
设置为最后一个之前设置的value@NickA是的,我认为这是一个特别好的“把戏”用法。我很高兴您选择了正确的存储顺序:-)除非board类正在做一些不寻常的事情,否则它们根本不需要实现方法copy.deepcopy
将“正常工作”。的确,它也应该^^^感谢您的快速回答,我尝试了实现它,它成功了,我对此表示感谢!我的荣幸:)请记住,在向外部用户提供对象副本时,应始终考虑深度/浅层复制对象。否则,他们可以使用你给他们的指针来修改你的对象,而无需使用APIcopy.deepcopy
将“正常工作”。的确,它也应该^^^感谢您的快速回答,我尝试了实现它,它成功了,我对此表示感谢!我的荣幸:)请记住,在向外部用户提供对象副本时,应始终考虑深度/浅层复制对象。否则,他们可以使用您给他们的指针来修改对象,而无需使用API。