井字游戏AI不工作(极小极大算法)

我正在尝试使用Python和极小极大算法创建一个井字游戏AI。我阅读了一些博客并编写了这些函数。但不知为何它不起作用。

代码:

class RunTimeError(Exception):    passclass TicTacToe:    '''Tic Tac Toe class'''        SYMBOL_X = 'x'    SYMBOL_O = 'o'    SYMBOL_EMPTY = '-'    INDEX_MAP = {        0: [0, 0], 1: [0, 1], 2: [0, 2],        3: [1, 0], 4: [1, 1], 5: [1, 2],        6: [2, 0], 7: [2, 1], 8: [2, 2]    }    def __init__(self) -> None:        '''Initialize the game'''        self.reset()    def reset(self) -> None:        '''Reset the game'''        self.board = [[self.SYMBOL_EMPTY for _ in range(3)] for _ in range(3)]        self.current_turn = 'x'        self.moves_stack = []        self.winner = None        self.game_state = 'RUNNING'    def swap_turn(self) -> None:        '''Swap the turn'''        self.current_turn = self.SYMBOL_X if self.current_turn == self.SYMBOL_O else self.SYMBOL_O    def play_move(self, index: int) -> None:        '''Play a move on the given index:            0 1 2            3 4 5            6 7 8'''        if self.game_state != 'RUNNING':            raise RuntimeError('Game already terminated')        if not isinstance(index, int):            raise RunTimeError(f"Expected index type 'int' got {type(index)}")        try:            y, x = self.INDEX_MAP[index]        except KeyError:            raise RunTimeError(f'Expected index to be from 0-8, got {index}')        if self.board[y][x] != self.SYMBOL_EMPTY:            raise RunTimeError('Invalid Move - Box occupied')        self.board[y][x] = self.current_turn        self.moves_stack.append(index)        self.update_game_state()        self.swap_turn()    def undo_move(self) -> int:        '''Reverse the last move and return its index'''        index = self.moves_stack.pop()        y, x = self.INDEX_MAP[index]        self.board[y][x] = self.SYMBOL_EMPTY        self.winner = None        self.game_state = 'RUNNING'        self.swap_turn()        return index    def update_game_state(self) -> None:        '''Check for a winner'''        win_cases = [            self.board[0][0] == self.board[0][1] == self.board[0][2] == self.current_turn,            self.board[1][0] == self.board[1][1] == self.board[1][2] == self.current_turn,            self.board[2][0] == self.board[2][1] == self.board[2][2] == self.current_turn,            self.board[0][0] == self.board[1][0] == self.board[2][0] == self.current_turn,            self.board[0][1] == self.board[1][1] == self.board[2][1] == self.current_turn,            self.board[0][2] == self.board[1][2] == self.board[2][2] == self.current_turn,            self.board[0][0] == self.board[1][1] == self.board[2][2] == self.current_turn,            self.board[0][2] == self.board[1][1] == self.board[2][0] == self.current_turn,        ]        if any(win_cases):            self.winner = self.current_turn            self.game_state = 'WIN'        elif self.SYMBOL_EMPTY not in [element for row in self.board for element in row]:            self.game_state = 'DRAW'    def generate_possible_moves(self) -> list:        '''Returns a list with all possible move indexes'''        moves = []        for num in range(8):            if num not in self.moves_stack:                moves.append(num)        return moves    def __str__(self) -> str:        '''Returns the board as a string'''        return '\n'.join([            f' {self.board[0][0]} | {self.board[0][1]} | {self.board[0][2]}',            '-' * 11,            f' {self.board[1][0]} | {self.board[1][1]} | {self.board[1][2]}',            '-' * 11,            f' {self.board[2][0]} | {self.board[2][1]} | {self.board[2][2]}'        ])    def ai_play(self):        best_score = -100        best_move = None        for move in self.generate_possible_moves():            self.play_move(move)            score = self.minmax(False, self.current_turn)            print(score)            self.undo_move()            if score > best_score:                best_score = score                best_move = move        self.play_move(best_move)    def minmax(self, maximizing, symbol):        if self.game_state == 'DRAW':            return 0        elif self.game_state == 'WIN':            return 1 if self.winner == symbol else -1        scores = []        for move in self.generate_possible_moves():            self.play_move(move)            scores.append(self.minmax(not maximizing, symbol))            self.undo_move()        return max(scores) if maximizing else min(scores)game1 = TicTacToe()print(game1)game1.ai_play()print(game1)

它引发了以下错误:

Traceback (most recent call last):  File "c:\Users\LENOVO\Desktop\tic tac toe.py", line 139, in <module>    game1.ai_play()  File "c:\Users\LENOVO\Desktop\tic tac toe.py", line 112, in ai_play    score = self.minmax(False, self.current_turn)  File "c:\Users\LENOVO\Desktop\tic tac toe.py", line 131, in minmax    scores.append(self.minmax(not maximizing, symbol))  File "c:\Users\LENOVO\Desktop\tic tac toe.py", line 131, in minmax    scores.append(self.minmax(not maximizing, symbol))  File "c:\Users\LENOVO\Desktop\tic tac toe.py", line 131, in minmax    scores.append(self.minmax(not maximizing, symbol))  [Previous line repeated 4 more times]  File "c:\Users\LENOVO\Desktop\tic tac toe.py", line 134, in minmax    return max(scores) if maximizing else min(scores)ValueError: max() arg is an empty sequence

我不知道问题出在哪里(我已经花了很多时间试图解决它)。任何帮助都将不胜感激!


回答:

max和min函数期望传递的列表中至少有一个项目。当在minmax函数中没有更多可能的移动时,generate_possible_moves返回一个空列表,因此scores[]max([])将会抛出错误,因为没有可以进行max操作的项目。

len(scores)为0时,你需要为没有可能移动的情况分配某个分数并返回该分数。

此外,当你撤销任何移动时,你还需要调用update_game_state,否则状态将不正确。

Related Posts

Keras Dense层输入未被展平

这是我的测试代码: from keras import…

无法将分类变量输入随机森林

我有10个分类变量和3个数值变量。我在分割后直接将它们…

如何在Keras中对每个输出应用Sigmoid函数?

这是我代码的一部分。 model = Sequenti…

如何选择类概率的最佳阈值?

我的神经网络输出是一个用于多标签分类的预测类概率表: …

在Keras中使用深度学习得到不同的结果

我按照一个教程使用Keras中的深度神经网络进行文本分…

‘MatMul’操作的输入’b’类型为float32,与参数’a’的类型float64不匹配

我写了一个简单的TensorFlow代码,但不断遇到T…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注