минимаксный алгоритм крестики-нолики

#ruby #algorithm #tic-tac-toe #minimax

#ruby #алгоритм #крестики-нолики #минимакс

Вопрос:

Я застрял на реализации минимаксного алгоритма для игры в крестики-нолики. Я продолжаю получать одну и ту же ошибку каждый раз (неопределенный метод `<‘ для nil:NilClass (NoMethodError)), но, похоже, не могу ее исправить.

Моя реализация заключается в следующем:

 def minimax(current_board, current_player)
  if user_won?(current_board)
    return -10
  elsif computer_won?(current_board)
    return 10
  elsif tie?(current_board)
    return 0
  end

  available_squares = empty_squares(current_board)
  moves = []

  available_squares.each do |available_square|
    move = {}
    current_board[available_square] = COMPUTER_MARKER if current_player == 'computer'
    current_board[available_square] = PLAYER_MARKER if current_player == 'player'
    score = minimax(current_board, alternate_player(current_player))
    current_board[available_square] = INITIAL_MARKER
    move[available_square] = score
    moves.push(move)
  end

  best_move = nil
  best_score = current_player == 'computer' ? -Float::INFINITY : Float:: INFINITY

  if current_player == 'computer'
    for hsh in moves
      hsh.each do |move, score|
        if score > best_score
          best_move = move
          best_score = score
        end
      end
    end
  else
    for hsh in moves 
      hsh.each do |move, score|
        if score < best_score
          best_move = move
          best_score = score
        end
      end
    end
  end
  best_move
end
 

Я застрял на этом в течение нескольких дней, поэтому буду признателен за любую помощь.

Вот остальная часть моего кода: https://github.com/YBirader/launch_school/blob/master/RB101/lesson_6/ttt.rb

Комментарии:

1. Похоже, что оценка определяется внутри цикла, available_squares . каждый — поэтому, если available_squares пуст, этот код никогда не будет запущен, и оценка не будет определена. Это могло бы вызвать эту ошибку.

2. оценка используется только внутри блока. Он добавляется к хэшу перемещения, который затем деструктивно добавляется к массиву перемещений, так что это не должно быть проблемой. Я добавил остальную часть своего кода, если это поможет.

Ответ №1:

Переменная score должна быть определена вне цикла. Затем строка

 if score > best_score
 

будет работать.

Комментарии:

1. Я пробовал это, но это все равно не работает. Я получаю ту же ошибку. Кроме того, каждый блок получает доступ к ключу оценки хэш-элементов ходов, поэтому мне не нужно определять оценку перед циклом for.

2. Чтобы проверить, является ли это проблемой, попробуйте добавить ‘score = 0’ перед ‘available_squares.each’.

Ответ №2:

Я только что прошел и отладил это.

Оказывается, что минимаксный метод иногда возвращает nil, который затем помещается в хэш ходов в строке 94, поскольку он не может сравнить nil с любым числом, > или < это выдает ошибку, и мы не можем продолжить.

Вам просто нужно добавить резервный вариант к 0, когда результат равен нулю, измените строку 91 на это:

 minimax(current_board, alternate_player(current_player)) || 0
 

Вам также не нужно определять score вне цикла, поскольку эта переменная используется только для добавления ее в хэш в строке 94. Что я пропустил ранее, так это то, что оценка снова определяется в each цикле.

Комментарии:

1. Но это ошибка, если минимакс возвращает 0?

2. да. Хотя он устраняет ошибку, функция минимакса больше не работает, т.Е. логика теперь неправильная.