加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – 在TicTacToe中调试递归MinMax

发布时间:2020-12-17 02:23:56 所属栏目:百科 来源:网络整理
导读:我试图让minmax算法(计算机AI)在我的tic-tac-toe游戏中运行.我已经坚持了几天.基本上,我不明白为什么计算机AI只是从板块0-8按顺序放置它的标记(“O”). 例如,作为人类玩家,如果我选择1,那么计算机将选择0: O| X| 2--+---+-- 3| 4| 5--+---+-- 6| 7| 8 接下
我试图让minmax算法(计算机AI)在我的tic-tac-toe游戏中运行.我已经坚持了几天.基本上,我不明白为什么计算机AI只是从板块0-8按顺序放置它的标记(“O”).

例如,作为人类玩家,如果我选择1,那么计算机将选择0:

O| X| 2
--+---+--
 3| 4| 5
--+---+--
 6| 7| 8

接下来,如果我选择4,那么计算机将选择2:

O| X| O
--+---+--
 3| X| 5
--+---+--
 6| 7| 8

等等:

O| X| O
--+---+--
 O| X| O
--+---+--
 X| 7| X

我尽可能地调试了minmax算法,但是很难跟踪正在发生的事情.

这是带有算法的ComputerPlayer类(并且没有我的所有打印语句). minmax方法是我遇到很多麻烦的地方. (我不是百分之百肯定使用的是bad_score甚至是相关的逻辑.)

class ComputerPlayer < Player
  def move(game_board)
    minmax(game_board) #minmax to create @best_move

    game_board.place_piece(@best_move,marker)
  end

  def minmax(board,player_tracker = 0) 
    if board.game_over?
      return score(board)
    else
      worst_score  = (1.0/0.0) #Infinity
      best_score  = -(1.0/0.0) #-Infinity
      @best_move  = board.get_available_positions.first

      new_marker = player_tracker.even? ? 'O' : 'X'
      player_tracker += 1

      board.get_available_positions.each do |move|
        new_board = board.place_piece(move,new_marker)
        current_score = minmax(new_board,player_tracker)
        if new_marker == marker #if the player is the computer player
          if current_score > best_score
            @best_move = move
            best_score = current_score
          end
        else
          if current_score < worst_score
            worst_score = current_score
          end
        end
      end
    end
    return best_score
  end

  def score(board)
    if board.winner == "O" #'O' == 'O','nil' == 'O'
      10
    elsif board.winner == "X" #'X' != 'O','nil' != 'O'
      -10
    elsif board.winner == nil
      0
    end
  end
end

解决方法

问题是minmax总是返回best_score.

minmax例程不断在两个玩家之间切换.当被模拟的当前玩家是计算机玩家时,最佳分数是最高分,当被模拟的当前玩家是人类玩家时,则最佳分数是最低分.

我重写了例程,尝试迭代的所有剩余移动,并跟踪本地哈希中的相应分数.完成后,将返回最佳分数,并根据当前模拟的玩家设置最佳移动.

def minmax(board,player_tracker = 0,iteration = 0) #minmax
    if board.game_over?
        return score(board,iteration)
    end

    new_marker = player_tracker.even? ? 'O' : 'X'

    scores = {}
    board.get_available_positions.each do |move|
        new_board = board.place_piece(move,new_marker)
        scores[move] = minmax(new_board,player_tracker + 1,iteration + 1)
    end

    if player_tracker.even?
        @best_move = scores.sort_by {|_key,value| value}.reverse.to_h.keys[0]
    else
        @best_move = scores.sort_by {|_key,value| value}.to_h.keys[0]
    end

    return scores[@best_move]
end

为了提高准确性,我重写了分数例程,还考虑了创建评分板所需的迭代次数.能够在1次迭代中获胜应该优于在3次迭代中获胜,对吗?

def score(board,iteration)
    # "O","X","nil"
    if board.winner == "O" #'O' == 'O','nil' == 'O'
      10.0 / iteration
    elsif board.winner == "X" #'X' != 'O','nil' != 'O'
      -10.0 / iteration
    elsif board.winner == nil
      0
    else
      raise "ERROR"
    end
end

通过这两个例程替换,计算机采取的步骤似乎更合乎逻辑.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读