Python井字棋Minimax算法无法选择最优落子问题排查求助
你的Minimax算法问题排查与修复
我仔细看了你的井字棋代码,发现几个关键问题导致Bot无法选出最优解,尤其是你说的无法阻止你走1-5-9获胜的情况。咱们一步步来解决:
核心问题1:平局判断完全错误
你的checkdraw函数逻辑搞反了!当前它是当有玩家获胜时返回True,但平局的定义是「棋盘已满且没有任何人获胜」。这个错误会导致Minimax算法在平局时无法正确返回0分,进而让评分逻辑混乱,Bot无法做出正确的决策。
修复后的checkdraw应该是这样:
def checkdraw(board): # 先检查有没有人赢,有赢的就不是平局 if checkForWin2(): return False # 再检查棋盘是否还有空位 for key in board.keys(): if board[key] == ' ': return False # 没人赢且棋盘满了,就是平局 return True
核心问题2:Minimax里多余的打印干扰(非逻辑错误但影响调试)
在minimax函数的最大化玩家分支里,你加了一个printboard(),这会在递归过程中疯狂打印棋盘,不仅看不清正常输出,还会拖慢算法。把这行删掉就行。
次要问题:冗余参数导致混淆
botgo函数的possibles参数完全没被用到(函数里直接遍历了board.keys()),可以删掉这个参数,让代码更清晰:
def botgo(mark): # 移除possibles参数 bestscore = -800 bestmove = 0 for key in board.keys(): if (board[key] == ' '): board[key] = mark score = minimax(board,0,False) board[key] = ' ' if(score > bestscore): bestscore = score bestmove = key insert(bestmove,mark='O') return
同时记得修改start函数里的调用:botgo(mark='O')
修复后的完整代码
board = {1: ' ', 2: ' ', 3: ' ', 4: ' ', 5: ' ', 6: ' ', 7: ' ', 8: ' ', 9: ' '} win = False turn = 1 depth = 1 nodeindex = 0 possibles= [] moves = [] depth = 0 targetdepth = 3 movesdone = [] def checkForWin(mark): if board[1] == board[2] == board[3] == mark: return True elif board[4] == board[5] == board[6] == mark: return True elif board[7] == board[8] == board[9] == mark: return True elif board[1] == board[4] == board[7] == mark: return True elif board[2] == board[5] == board[8] == mark: return True elif board[3] == board[6] == board[9] == mark: return True elif board[1] == board[5] == board[9] == mark: return True elif board[7] == board[5] == board[3] == mark: return True else: return False def checkForWin2(): if board[1] == board[2] == board[3] != ' ': return True elif board[4] == board[5] == board[6] != ' ': return True elif board[7] == board[8] == board[9] != ' ': return True elif board[1] == board[4] == board[7] != ' ': return True elif board[2] == board[5] == board[8] != ' ': return True elif board[3] == board[6] == board[9] != ' ': return True elif board[1] == board[5] == board[9] != ' ': return True elif board[7] == board[5] == board[3] != ' ': return True else: return False def possiblemoves(board): possibles.clear() for i in board: if board[i] == " ": possibles.append(i) return possibles def botgo(mark): bestscore = -800 bestmove = 0 for key in board.keys(): if board[key] == ' ': board[key] = mark score = minimax(board, 0, False) board[key] = ' ' if score > bestscore: bestscore = score bestmove = key insert(bestmove, mark='O') return def printboard(): print(board[1] + '|' + board[2] + '|' + board[3]) print('-----') print(board[4] + '|' + board[5] + '|' + board[6]) print('-----') print(board[7] + '|' + board[8] + '|' + board[9]) def start(): turn = 1 count = 0 while count != 9: humango() printboard() possiblemoves(board) botgo(mark='O') printboard() count += 1 def spacefree(space): return board[space] == ' ' def insert(space, mark): if spacefree(space): board[space] = mark if checkForWin(mark): printboard() print("human win" if mark == 'X' else "BOT WIN") exit() else: print("cannot insert there!!!") space = int(input("Enter position")) insert(space, mark) def checkdraw(board): if checkForWin2(): return False for key in board.keys(): if board[key] == ' ': return False return True def humango(): global turn space = int(input("Enter position")) insert(space, mark='X') turn += 1 printboard() def minimax(board, depth, ismax): if checkForWin(mark='O'): return 1 elif checkForWin(mark='X'): return -1 elif checkdraw(board): return 0 if ismax: bestscore = -800 for key in board.keys(): if board[key] == ' ': board[key] = 'O' score = minimax(board, depth + 1, False) board[key] = ' ' if score > bestscore: bestscore = score return bestscore else: bestscore = 800 for key in board.keys(): if board[key] == ' ': board[key] = 'X' score = minimax(board, depth + 1, True) board[key] = ' ' if score < bestscore: bestscore = score return bestscore start()
额外优化建议
- 我简化了一些条件判断(比如
board[1] == board[2] and board[1] == board[3]改成board[1] == board[2] == board[3]),让代码更简洁。 spacefree函数可以直接返回表达式,不用if-else,更简洁。- 全局变量太多了,比如
possibles、depth这些其实很多没用到,可以考虑重构,把需要的变量作为参数传递,避免全局变量带来的潜在问题。
现在你再测试一下,Bot应该能正确阻止你走1-5-9的获胜路线了!
内容的提问来源于stack exchange,提问作者RotatingConsistency
相关产品推荐
相关产品推荐

