class PerfectComputer
Constants
- EARLIEST_CHANCE_TO_WIN
- MAXIMUM_DEPTH_TO_CHECK
- MAXIMUM_SCORE
- STARTING_DEPTH
Attributes
marker[R]
Public Class Methods
new(marker)
click to toggle source
# File lib/perfect_computer.rb, line 12 def initialize(marker) @marker = marker end
Public Instance Methods
choose_space(board)
click to toggle source
# File lib/perfect_computer.rb, line 16 def choose_space(board) @best_score = {} negamax(board) @best_score.size > EARLIEST_CHANCE_TO_WIN ? choose_random_space(board) : best_space_to_pick end
Private Instance Methods
best_space_to_pick()
click to toggle source
# File lib/perfect_computer.rb, line 47 def best_space_to_pick @best_score.max_by {|key, value| value}[0] end
choose_random_space(board)
click to toggle source
# File lib/perfect_computer.rb, line 51 def choose_random_space(board) SimpleComputer.new(board.current_player_marker).choose_space(board) end
negamax(board, depth = STARTING_DEPTH, alpha = -MAXIMUM_SCORE, beta = MAXIMUM_SCORE, color = 1, max_depth = MAXIMUM_DEPTH_TO_CHECK)
click to toggle source
# File lib/perfect_computer.rb, line 24 def negamax(board, depth = STARTING_DEPTH, alpha = -MAXIMUM_SCORE, beta = MAXIMUM_SCORE, color = 1, max_depth = MAXIMUM_DEPTH_TO_CHECK) return color * score_scenarios(board, depth) if board.game_over? || depth > max_depth max = -MAXIMUM_SCORE board.check_available_spaces.each do |space| new_board = board.place_marker(space) negamax_value = -negamax(new_board, depth+1, -beta, -alpha, -color) max = [max, negamax_value].max @best_score[space] = max if depth == STARTING_DEPTH alpha = [alpha, negamax_value].max return alpha if alpha >= beta end max end
score_scenarios(board, depth)
click to toggle source
# File lib/perfect_computer.rb, line 41 def score_scenarios(board, depth) return 0 if board.game_tied? return MAXIMUM_SCORE / depth if board.game_won_by?(marker) return -MAXIMUM_SCORE / depth end