Я пытаюсь реализовать минимаксный алгоритм для создания бота ti c -ta c, но получаю ошибку рекурсии - PullRequest
0 голосов
/ 23 апреля 2020

Я пытаюсь реализовать минимаксный алгоритм для создания бота ti c -ta c, но я получаю RecursionError: максимальная глубина рекурсии превышена при ошибке сравнения. У меня есть код ниже. Я добавил комментарии, в которых упоминается, что должна делать функция. Я в последний раз Можете ли вы взглянуть на код ниже. Спасибо

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.
    """
    o_counter = 0
    x_counter = 0
    for i in board:
        for j in i:
            if j == 'X':
                x_counter += 1
            elif j == 'O':
                o_counter += 1
    if x_counter == 0 and o_counter == 0:
        return 'O'
    elif x_counter > o_counter:
        return 'O'
    elif o_counter > x_counter:
        return 'X'



def actions(board):
    """
    Returns set of all possible actions (i, j) available on the board.
    """
    action = []
    for i in range(3):
        for j in range(3):
            if board[i][j] is None:
                action.append([i, j])
    return action


def result(board, action):
    """
    Returns the board that results from making move (i, j) on the board.
    """
    p = player(board)
    i, j = action
    board[i][j] = p
    return board


def winner(board):
    """
    Returns the winner of the game, if there is one.
    """
    i = 1
    if board[0][0] == board[1][1] == board[2][2] and (board[0][0] == 'X' or board[0][0] == 'O'):
        return board[0][0]
    elif board[0][2] == board[1][1] == board[2][0] and (board[0][2] == 'X' or board[0][2] == 'O'):
        return  board[0][2]
    else:
        if board[0][0] == board[0][1] == board[0][2] and (board[0][0] == 'X' or board[0][0] == 'O'):
            return board[0][0]
        elif board[i][0] == board[i][1] == board[i][2] and (board[i][0] == 'X' or board[i][0] == 'O'):
            return board[i][0]
        elif board[2][0] == board[2][1] == board[2][2] and (board[2][0] == 'X' or board[2][0] == 'O'):
            return board[2][0]

        elif board[0][0] == board[1][0] == board[2][0] and (board[0][0] == 'X' or board[0][0] == 'O'):
            return board[0][0]
        elif board[0][i] == board[1][i] == board[2][i] and (board[0][i] == 'X' or board[0][i] == 'O'):
            return board[0][i]
        elif board[0][2] == board[1][2] == board[2][2] and (board[0][2] == 'X' or board[0][2] == 'O'):
            return board[0][2]

def terminal(board):
    """
    Returns True if game is over, False otherwise.
    """
    check = True
    if winner(board) == 'X' or winner(board) == 'O':
        return True
    elif check:
        for i in board:
            for j in i:
                if j is None:
                    check = False
                    return False
        if check:
            return True
    else:
        return False


def utility(board):
    """
    Returns 1 if X has won the game, -1 if O has won, 0 otherwise.
    """
    if winner(board) == 'X':
        return 1
    elif winner(board) == 'O':
        return -1
    else:
        return 0


def maximum(board):
    if terminal(board):
        return utility(board)
    v = -9999999999999999999999
    for action in actions(board):
        m = minimum(result(board, action))
        if m > v:
            v = m
    return v


def minimum(board):
    if terminal(board):
        return utility(board)
    v = 9999999999999999999999
    for action in actions(board):
        m = maximum(result(board, action))
        if m < v:
            v = m
    return v


def minimax(board):
    """
    Returns the optimal action for the current player on the board.
    """
    return_action = None
    curr_player = player(board)
    states = actions(board)
    temp_board = board.copy()
    score = 0
    temp_score = 0
    for state in states:
        i, j = state
        if curr_player == 'X':
            temp_board[i][j] = curr_player
            temp_score = maximum(temp_board)
        elif curr_player == 'O':
            temp_board[i][j] = curr_player
            temp_score = minimum(temp_board)
        if curr_player == 'X':
            if temp_score > score:
                score = temp_score
                return_action = state
        elif curr_player == 'O':
            if temp_score < score:
                score = temp_score
                return_action = state

    return  return_action

1 Ответ

1 голос
/ 23 апреля 2020

Ваша проблема - застревание в бесконечном состоянии, что означает, что вы продолжаете рекурсивно вызывать функцию, пока не достигнете предела рекурсии. Ваша проблема заключается в функции игрока и в том, как вы решаете, чей ход следующий. После того, как О играет в позиции 0,0, а Х играет в позиции 0,1, вы пытаетесь решить, кто будет играть дальше

Итак, вы считаете, и О и Х поставили по 1 жетону каждый. Однако ваша логика c, чтобы решить, кто следующий, не учитывает это состояние платы.

    if x_counter == 0 and o_counter == 0:
        return 'O'
    elif x_counter > o_counter:
        return 'O'
    elif o_counter > x_counter:
        return 'X'

, поэтому, когда x_counter и y_counter равны, но не равны 0, вы ничего не возвращаете. Это приводит к тому, что функция None не возвращает значение. Таким образом, вы застряли и никогда не поместите токен в положение 0,2. Если O всегда идет первым, то в любое время x_counter == o_counter вы должны вернуть '0', поэтому измените его на

    if x_counter == o_counter:
        return 'O'
    elif x_counter > o_counter:
        return 'O'
    elif o_counter > x_counter:
        return 'X'
...