Python如何在类中存储数据实现推箱子游戏的重启与撤销功能
问题根因
你遇到的多变量同步更新问题是Python可变对象的引用传递特性导致的:二维列表属于嵌套可变对象,直接赋值、浅拷贝都只会传递内存引用,修改任意一个引用指向的内容,所有关联变量都会同步变化。
解决思路
- 用深拷贝(
copy.deepcopy)完成嵌套列表的独立复制,切断不同变量之间的内存关联 - 用栈结构存储每一步操作前的棋盘状态,支持撤销和重启功能
- 调整
restart方法逻辑,直接修改当前实例的属性,不需要返回新实例(原有逻辑返回的新实例没有被main函数接收,会导致重启不生效)
完整修改代码
import copy class Sokoban: """Your code here""" def __init__(self, board): # 深拷贝初始棋盘,避免和外部传入的列表共享引用 self.__board = copy.deepcopy(board) # 深拷贝存储初始棋盘,供重启使用 self.__original_board = copy.deepcopy(board) self.__steps = 0 # 历史状态栈,存储每一步操作前的棋盘状态 self.__history = [] # 初始化玩家位置 self.__position = self.find_player() # 你已实现的方法示例,保留原有逻辑即可 def find_player(self): for row_idx, row in enumerate(self.__board): if 'P' in row: return (row_idx, row.index('P')) return (0,0) def complete(self): # 原有实现不变,判断所有箱子是否都在目标点 for row in self.__board: if '#' in row: return False return True def get_steps(self): return self.__steps def move(self, direction): # 先把当前状态压入历史栈,再执行移动逻辑 self.__history.append(copy.deepcopy(self.__board)) # ------------------- # 原有移动逻辑保留即可 # ------------------- self.__steps += 1 self.__position = self.find_player() def restart(self): # 直接重置当前实例属性,不需要返回新对象 self.__board = copy.deepcopy(self.__original_board) self.__steps = 0 self.__history.clear() self.__position = self.find_player() def undo(self): # 历史栈为空时不执行撤销 if not self.__history: return # 弹出最近一次状态覆盖当前棋盘 self.__board = self.__history.pop() self.__steps -= 1 self.__position = self.find_player() def __str__(self): # 实现打印棋盘的魔法方法,原有逻辑保留即可 return '\n'.join(''.join(row) for row in self.__board) + '\n' def main(board): game = Sokoban(board) message = 'Press w/a/s/d to move, r to restart, or u to undo' print(message) while not game.complete(): print(game) move = input('Move: ').lower() while move not in ('w', 'a', 's', 'd', 'r', 'u'): print('Invalid move.', message) move = input('Move: ').lower() if move == 'r': game.restart() elif move == 'u': game.undo() else: game.move(move) print(game) print(f'Game won in {game.get_steps()} steps!') test_board = [ ['*', '*', '*', '*', '*', '*', '*', '*'], ['*', ' ', ' ', ' ', ' ', ' ', ' ', '*'], ['*', 'P', ' ', '#', ' ', ' ', ' ', '*'], ['*', '*', '*', '*', '*', ' ', '#', '*'], ['*', 'o', ' ', ' ', ' ', ' ', ' ', '*'], ['*', ' ', ' ', ' ', ' ', ' ', 'o', '*'], ['*', '*', '*', '*', '*', '*', '*', '*'] ] main(test_board)
内容的提问来源于stack exchange,提问作者ame
相关产品推荐
相关产品推荐

