Skip to content

Instantly share code, notes, and snippets.

@geowy
Created July 20, 2020 14:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save geowy/bb8a540aa3385abf2cf8ef415205262f to your computer and use it in GitHub Desktop.
Save geowy/bb8a540aa3385abf2cf8ef415205262f to your computer and use it in GitHub Desktop.
Tic Tac Toe in Ruby
class Game
WINNING_PATTERNS = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
]
private_constant :WINNING_PATTERNS
def next_turn(&block)
@next_turn_callback = block
end
def win(&block)
@win_callback = block
end
def draw(&block)
@draw_callback = block
end
def play
board = Array.new(9)
[:player1, :player2].cycle do |player|
selection = @next_turn_callback.call(board, player)
# This failure should be guarded against in @next_turn_callback
fail if selection > 8 || board[selection]
board[selection] = player
if winner?(board)
@win_callback.call(board, player)
break
elsif board.none?(&:nil?)
@draw_callback.call(board)
break
end
end
end
private
def winner?(board)
WINNING_PATTERNS.any? do |pattern|
values = pattern.map { |i| board[i] }
values.none?(&:nil?) && values.uniq.length == 1
end
end
end
require_relative 'game'
PLAYER_NAMES = {
player1: "Player 1",
player2: "Player 2"
}
def print_board(board)
board.each_slice(3) do |row|
row.each do |cell|
print \
case cell
when :player1 then 'O'
when :player2 then 'X'
when nil then '_'
end
print ' '
end
puts
end
end
puts "Tic Tac Toe"
game = Game.new
game.next_turn do |board, next_player|
print_board(board)
print "#{PLAYER_NAMES[next_player]}, pick a cell: "
# TODO guard against invalid selections
Integer(gets) - 1
end
game.win do |board, winner|
print_board(board)
puts "#{PLAYER_NAMES[winner]} wins!"
end
game.draw do |board|
print_board(board)
puts 'Draw!'
end
game.play
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment