如何解决Python列表未按值传递导致井字棋AI递归计算时棋盘被修改的问题
解决井字棋AI递归中棋盘被意外修改的问题
你遇到的问题根源是浅拷贝导致的!咱们来看你的代码:当你用t = list(board)复制棋盘时,这个操作只是创建了一个新的外层列表,但里面的每一行(子列表)还是引用原board里的行对象。所以当你执行t[i][j] = letter时,其实是直接修改了原board对应行里的元素,这就导致递归过程中原棋盘被意外改动了。
解决方案:实现深拷贝
要让每个递归调用里的棋盘都是完全独立的副本,你需要对嵌套列表做深拷贝,有两种简单的方式:
方法1:手动逐行复制
用列表推导式复制每一行,这样每个子列表都是全新的对象:
import sys def calc(board : list, turn : bool): game_over = True letter = "o" if turn else "x" for i in range(len(board)): for j in range(len(board)): if board[i][j] == "": # 手动深拷贝:复制每一行 t = [list(row) for row in board] t[i][j] = letter game_over = False calc(t, not turn) if game_over: print(board) def main(): sys.setrecursionlimit(50000) board = [["", "", ""],["", "", ""],["", "", ""]] calc(board, True) if __name__ == '__main__': main()
方法2:使用copy模块的deepcopy
如果棋盘结构更复杂(比如多层嵌套),用copy.deepcopy()会更省心,它会递归复制所有嵌套的对象:
import sys import copy def calc(board : list, turn : bool): game_over = True letter = "o" if turn else "x" for i in range(len(board)): for j in range(len(board)): if board[i][j] == "": # 深拷贝整个棋盘 t = copy.deepcopy(board) t[i][j] = letter game_over = False calc(t, not turn) if game_over: print(board) def main(): sys.setrecursionlimit(50000) board = [["", "", ""],["", "", ""],["", "", ""]] calc(board, True) if __name__ == '__main__': main()
为什么这样能解决问题?
不管用哪种方法,新创建的t都是一个完全独立于原board的嵌套列表,修改t的任何元素都不会影响到原棋盘,这样递归过程中每个分支的棋盘状态都是独立的,你就能正确评估所有可能的走法了。
内容的提问来源于stack exchange,提问作者Andreas Sandberg
相关产品推荐
相关产品推荐

