module MinimaxRB
Public Class Methods
best_move(args)
click to toggle source
# File lib/minimax_rb.rb, line 2 def self.best_move args minimax(args[:board], args[:curr_player_marker], args[:opponent_marker], args.fetch(:empty_marker, nil)) end
Private Class Methods
available_moves(array, empty_marker)
click to toggle source
# File lib/minimax_rb.rb, line 28 def self.available_moves array, empty_marker available_moves = [] array.each_with_index do |value, index| if value == empty_marker available_moves << index end end available_moves end
board_full?(board, empty_marker)
click to toggle source
# File lib/minimax_rb.rb, line 80 def self.board_full? board, empty_marker not board.include?(empty_marker) end
columns(board)
click to toggle source
# File lib/minimax_rb.rb, line 54 def self.columns board rows(board).transpose end
diagonals(board)
click to toggle source
# File lib/minimax_rb.rb, line 58 def self.diagonals board left_diag = [] right_diag = [] (0...grid_size(board)).each do |i| left_diag.push(rows(board)[i][i]) right_diag.push(rows(board).reverse[i][i]) end [left_diag, right_diag] end
draw?(board, marker, opponent, empty_marker)
click to toggle source
# File lib/minimax_rb.rb, line 72 def self.draw? board, marker, opponent, empty_marker board_full?(board, empty_marker) and not win?(board, marker, opponent) end
grid_size(board)
click to toggle source
# File lib/minimax_rb.rb, line 68 def self.grid_size board Math.sqrt(board.length) end
marker_winner?(marker, board)
click to toggle source
# File lib/minimax_rb.rb, line 42 def self.marker_winner? marker, board combos = [rows(board), columns(board), diagonals(board)] combos.each do |combo| combo.each { |line| return true if marker_winning_combo?(marker, line) } end false end
marker_winning_combo?(marker, board)
click to toggle source
# File lib/minimax_rb.rb, line 38 def self.marker_winning_combo? marker, board board.uniq.length == 1 and board.include?(marker) end
max_move(best_score)
click to toggle source
# File lib/minimax_rb.rb, line 20 def self.max_move best_score best_score.max_by { |key, value| value }[0] end
max_score(best_score)
click to toggle source
# File lib/minimax_rb.rb, line 24 def self.max_score best_score best_score.max_by { |key, value| value }[1] end
minimax(board, marker, opponent, empty_marker, depth=0, best_score={})
click to toggle source
# File lib/minimax_rb.rb, line 7 def self.minimax board, marker, opponent, empty_marker, depth=0, best_score={} return 0 if draw?(board, marker, opponent, empty_marker) return -1 if win?(board, marker, opponent) available_moves(board, empty_marker).each do |move| board[move] = marker best_score[move] = -1 * minimax(board, opponent, marker, empty_marker, depth+1, {}) board[move] = empty_marker end depth == 0 ? max_move(best_score) : max_score(best_score) end
rows(board)
click to toggle source
# File lib/minimax_rb.rb, line 50 def self.rows board board.each_slice(grid_size(board)).to_a end
win?(board, marker, opponent)
click to toggle source
# File lib/minimax_rb.rb, line 76 def self.win? board, marker, opponent marker_winner?(marker, board) or marker_winner?(opponent, board) end