Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中为7x7板制作撤销函数_Python_List_Append_Undo - Fatal编程技术网

在Python中为7x7板制作撤销函数

在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

我目前正在尝试编写一个名为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, 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
将“正常工作”。的确,它也应该^^^感谢您的快速回答,我尝试了实现它,它成功了,我对此表示感谢!我的荣幸:)请记住,在向外部用户提供对象副本时,应始终考虑深度/浅层复制对象。否则,他们可以使用你给他们的指针来修改你的对象,而无需使用API
copy.deepcopy
将“正常工作”。的确,它也应该^^^感谢您的快速回答,我尝试了实现它,它成功了,我对此表示感谢!我的荣幸:)请记住,在向外部用户提供对象副本时,应始终考虑深度/浅层复制对象。否则,他们可以使用您给他们的指针来修改对象,而无需使用API。