井字棋AI运行报错:move not in the set,请求修复指导
Tic Tac Toe AI代码修复方案
问题重现
运行代码时触发以下错误:
Traceback (most recent call last):
File "C:\Users\Dell\Downloads\tictactoe\tictactoe\runner.py", line 116, in
board = ttt.result(board, move)
File "C:\Users\Dell\Downloads\tictactoe\tictactoe\tictactoe.py", line 66, in result
raise Exception("move not in the set ")
Exception: move not in the set
经排查,result函数接收到的action参数为None,根源在minimax函数的实现错误。
错误点分析
- minimax函数语法与逻辑错误:
append方法仅接受一个参数,原代码中拆分传入分数和行动的写法语法错误。- 遍历候选行动时使用
range(len(score_play)-1)会遗漏最后一个元素,导致无法选中最优解。 - O玩家分支中存在无意义的循环代码,可能引发类型错误。
- player函数分支缺失:
- 当X和O步数相同时(初始状态或回合交替后),未返回先手玩家X,会导致返回
None引发后续异常。
- 当X和O步数相同时(初始状态或回合交替后),未返回先手玩家X,会导致返回
- terminal函数逻辑顺序错误:
- 先检查棋盘空位再判断赢家,导致已分出胜负但棋盘未填满时,错误判定游戏未结束。
修复后的完整代码
""" Tic Tac Toe Player """ import math import copy X = "X" O = "O" EMPTY = None def initial_state(): """ Returns starting state of the board. """ return [[EMPTY, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY]] def player(board): """ Returns player who has the next turn on a board. """ countx = 0 counto = 0 for i in range(3): for j in range(3): if board[i][j] == X: countx += 1 if board[i][j] == O: counto += 1 # X先手,步数相同时X行动 if countx == counto: return X elif countx > counto: return O else: return X def actions(board): """ Returns set of all possible actions (i, j) available on the board. """ allaction = set() for i in range(3): for j in range(3): if board[i][j] == EMPTY: allaction.add((i, j)) return allaction def result(board, action): """ Returns the board that results from making move (i, j) on the board. """ current_player = player(board) new_all_actions = actions(board) if action not in new_all_actions: raise Exception("move not in the set ") i, j = action copy_board = copy.deepcopy(board) copy_board[i][j] = current_player return copy_board def check_row(board, player): for i in range(3): if board[i][0] == player and board[i][1] == player and board[i][2] == player: return True return False def check_column(board, player): for i in range(3): if board[0][i] == player and board[1][i] == player and board[2][i] == player: return True return False def check_diagonals(board, player): if board[0][0] == player and board[1][1] == player and board[2][2] == player: return True elif board[0][2] == player and board[1][1] == player and board[2][0] == player: return True return False def winner(board): """ Returns the winner of the game, if there is one. """ if check_column(board, X) or check_row(board, X) or check_diagonals(board, X): return X elif check_column(board, O) or check_row(board, O) or check_diagonals(board, O): return O return None def terminal(board): """ Returns True if game is over, False otherwise. """ # 优先判断是否有赢家 if winner(board) is not None: return True # 检查棋盘是否还有空位 for i in range(3): for j in range(3): if board[i][j] == EMPTY: return False # 无赢家且棋盘满,游戏结束 return True def utility(board): """ Returns 1 if X has won the game, -1 if O has won, 0 otherwise. """ if not terminal(board): raise Exception("game not over") if winner(board) == X: return 1 if winner(board) == O: return -1 else: return 0 def max_value(board): v = -math.inf if terminal(board): return utility(board) for action in actions(board): v = max(v, min_value(result(board, action))) return v def min_value(board): v = math.inf if terminal(board): return utility(board) for action in actions(board): v = min(v, max_value(result(board, action))) return v def minimax(board): if terminal(board): return None current_player = player(board) if current_player == X: max_variable = -math.inf best_action = None # 遍历所有可能行动,记录最优解 for action in actions(board): current_score = min_value(result(board, action)) if current_score > max_variable: max_variable = current_score best_action = action return best_action elif current_player == O: min_variable = math.inf best_action = None # 遍历所有可能行动,记录最优解 for action in actions(board): current_score = max_value(result(board, action)) if current_score < min_variable: min_variable = current_score best_action = action return best_action
修复说明
- 重构
minimax函数逻辑,直接遍历行动并实时记录最优解,避免语法错误与冗余操作。 - 完善
player函数的分支覆盖,确保所有场景下都能返回正确的当前玩家。 - 调整
terminal函数的判断顺序,优先判定是否有赢家,保证游戏结束状态的准确性。
内容的提问来源于stack exchange,提问作者Philip Sebastian
相关产品推荐
相关产品推荐

