如何在现有井字棋Mini Max代码中实现Alpha-Beta剪枝,无需重新开发?
解答
首先明确:不需要完全重写代码,也不需要另外开新项目。Alpha-beta剪枝是MiniMax算法的剪枝优化,只需要在你现有MiniMax逻辑的基础上新增少量剪枝判断逻辑即可,改动量不足20行。
另外你现有的MiniMax实现存在两处逻辑错误,修改剪枝的同时可以一并修正:
- 最小化玩家分支下,你错误的赋值了bot的棋子,应该赋值玩家的棋子
player - 最小化玩家分支下递归调用MiniMax时,
isMaximizing参数应该传True,而非False
具体修改步骤
- 给
miniMax函数新增两个入参alpha和beta,默认值分别设置为-1000、1000(和你当前的评分上下限对齐) - 最大化玩家(Bot)逻辑中,每次计算得到当前位置的评分后,同步更新
alpha为max(alpha, score),如果满足alpha >= beta,直接终止遍历剩余空位,完成剪枝 - 最小化玩家(人类)逻辑中,每次计算得到当前位置的评分后,同步更新
beta为min(beta, score),如果满足beta <= alpha,直接终止遍历剩余空位,完成剪枝 - 修改所有调用
miniMax的位置,传入对应的alpha和beta值
修改后的完整代码
# 井字棋棋盘初始化 board = {1: ' ', 2: ' ', 3: ' ', 4: ' ', 5: ' ', 6: ' ', 7: ' ', 8: ' ', 9: ' '} def printBoard(board): print(board[1] + ' | ' + board[2] + '| ' + board[3]) print("--+--+--") print(board[4] + ' | ' + board[5] + '| ' + board[6]) print("--+--+--") print(board[7] + ' | ' + board[8] + '| ' + board[9]) print("--+--+--") print("\n") def spaceIsFree(position): return board[position] == ' ' def positionsAvaliable(board): for key in board.keys(): if board[key] == ' ': return key return False def insertLetter(letter, position): if spaceIsFree(position): board[position] = letter printBoard(board) if checkDraw(): print("It's a draw!") exit() if checkForWin(): if letter == 'X': print("Bot wins.") exit() else: print("player wins") exit() return else: print("Can't insert letter there") position = int(input("Enter a new position: ")) insertLetter(letter, position) return def checkForWin(): if (board[1] == board[2] and board[1] == board[3] and board[1] != ' '): return True elif (board[4] == board[5] and board[4] == board[6] and board[4] != ' '): return True elif (board[7] == board[8] and board[7] == board[9] and board[7] != ' '): return True elif (board[1] == board[4] and board[1] == board[7] and board[1] != ' '): return True elif (board[2] == board[5] and board[2] == board[8] and board[2] != ' '): return True elif (board[3] == board[6] and board[3] == board[9] and board[3] != ' '): return True elif (board[1] == board[5] and board[1] == board[9] and board[1] != ' '): return True elif (board[7] == board[5] and board[7] == board[3] and board[7] != ' '): return True else: return False def checkWhichMarkWon(mark): if board[1] == board[2] and board[1] == board[3] and board[1] == mark: return True elif (board[4] == board[5] and board[4] == board[6] and board[4] == mark): return True elif (board[7] == board[8] and board[7] == board[9] and board[7] == mark): return True elif (board[1] == board[4] and board[1] == board[7] and board[1] == mark): return True elif (board[2] == board[5] and board[2] == board[8] and board[2] == mark): return True elif (board[3] == board[6] and board[3] == board[9] and board[3] == mark): return True elif (board[1] == board[5] and board[1] == board[9] and board[1] == mark): return True elif (board[7] == board[5] and board[7] == board[3] and board[7] == mark): return True else: return False def checkDraw(): for key in board.keys(): if board[key] == ' ': return False return True player = 'O' bot = 'X' def playerMove(): position = int(input("Enter the position for O: ")) insertLetter(player, position) return def botMove(): bestScore = -1000 bestMove = 0 for key in board.keys(): if board[key] == ' ': board[key] = bot # 调用带alpha-beta剪枝的minimax,初始alpha=-1000,beta=1000 score = miniMax(board, 0, False, -1000, 1000) board[key] = ' ' if score > bestScore: bestScore = score bestMove = key insertLetter(bot, bestMove) return # 新增alpha、beta参数,默认值对齐评分边界 def miniMax(board, depth, isMaximizing, alpha=-1000, beta=1000): # 终止状态判断和原有逻辑一致 if checkWhichMarkWon(bot): return 100 elif checkWhichMarkWon(player): return -100 elif checkDraw(): return 0 if isMaximizing: bestScore = -1000 for key in board.keys(): if board[key] == ' ': board[key] = bot score = miniMax(board, depth + 1, False, alpha, beta) board[key] = ' ' bestScore = max(score, bestScore) # 更新alpha值 alpha = max(alpha, score) # 剪枝判断:alpha >= beta时剩余节点无需遍历 if alpha >= beta: break return bestScore else: bestScore = 1000 for key in board.keys(): if board[key] == ' ': # 修正原有bug:最小化玩家落子为player而非bot board[key] = player # 修正原有bug:递归后进入最大化玩家逻辑,isMaximizing传True score = miniMax(board, depth + 1, True, alpha, beta) board[key] = ' ' bestScore = min(score, bestScore) # 更新beta值 beta = min(beta, score) # 剪枝判断:beta <= alpha时剩余节点无需遍历 if beta <= alpha: break return bestScore while not checkForWin(): botMove() playerMove()
效果说明
修改后的代码运行逻辑和原有MiniMax完全一致,不会改变最终的落子决策结果,但会跳过大量不必要的分支搜索,运行速度会有明显提升,井字棋场景下搜索效率可以提升4-5倍。
内容的提问来源于stack exchange,提问作者couttssyy
相关产品推荐
相关产品推荐

