Created
February 2, 2011 16:54
-
-
Save gdakram/807979 to your computer and use it in GitHub Desktop.
The game in ruby via cli. Have fun.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# the anatomy of a slot | |
Slot = Struct.new(:row, :column, :value) | |
# The board has n x n slots | |
class Board | |
# Constants | |
X = "X" | |
O = "O" | |
# attr accessor | |
attr_accessor :grid, :slots, :game_over, :current_player, :winner | |
# constructor | |
def initialize(n) | |
# initialize the instance variables | |
@grid, @slots = Array.new(n), Hash.new | |
@game_over, @current_player, @winner = false, Board::X, nil | |
# build the board | |
slot_counter = 0 | |
@grid.each_with_index do |row, i| | |
@grid[i] = Array.new(n) | |
@grid[i].each_with_index do |column, j| | |
@grid[i][j] = Slot.new(i, j, slot_counter) | |
@slots[slot_counter] = @grid[i][j] | |
slot_counter += 1 | |
end | |
end | |
end | |
def draw | |
system("clear") | |
@grid.each_with_index do |row, i| | |
row_print = row.collect{ |s| s.value }.join(" | ") | |
puts row_print | |
puts "-" * row_print.length if @grid.length != (i + 1) | |
end | |
puts "" | |
end | |
def move | |
print "#{@current_player} -- Please enter a number from the board: " | |
slot_number = gets.chomp.to_i | |
if [email protected]_key?(slot_number) | |
move | |
elsif @slots[slot_number].value == Board::X || @slots[slot_number].value == Board::O | |
puts "Please enter a number that is not already marked!" | |
move | |
else | |
@board_updated = true | |
@slots[slot_number].value = @current_player | |
end | |
# post-move analysis. | |
if won?(@slots[slot_number]) | |
@game_over = true | |
@winner = @current_player | |
elsif stalemate? | |
@game_over = true | |
else | |
switch_turn if @board_updated | |
end | |
end | |
def switch_turn | |
@current_player = (@current_player == Board::X) ? Board::O : Board::X | |
@board_updated = false | |
end | |
def won?(slot) | |
horizontal_win?(slot) || | |
vertical_win?(slot) || | |
diagonal_win?(:orientation => "l2r") || | |
diagonal_win?(:orientation => "r2l") | |
end | |
def stalemate? | |
stalemate = true | |
@slots.each { |k,slot| stalemate = false if slot.value.is_a?(Fixnum) } | |
stalemate | |
end | |
def game_over? | |
@game_over | |
end | |
private | |
def horizontal_win?(slot) | |
slot_values = @grid[slot.row].collect{ |s| s.value == @current_player } | |
slot_values.length == @grid.length && slot_values.uniq.to_s == "true" | |
end | |
def vertical_win?(slot) | |
slot_values = @grid.collect{ |r| r[slot.column] }.collect { |s| s.value == @current_player } | |
slot_values.length == @grid.length && slot_values.uniq.to_s == "true" | |
end | |
def diagonal_win?(options = {}) | |
slots = [] | |
case options[:orientation] | |
when "l2r" then 0.upto(@grid.length - 1) { |i| slots << @grid[i][i] } | |
when "r2l" then (@grid.length - 1).downto(0) { |i| slots << @grid[i][@grid.length - 1 - i] } | |
end | |
slot_values = slots.collect { |s| s.value == @current_player } | |
slots.length == @grid.length && slot_values.uniq.to_s == "true" | |
end | |
end | |
# new game | |
board = Board.new(3) | |
while !board.game_over? do | |
board.draw | |
board.move | |
end | |
board.draw | |
# result | |
puts !board.winner.nil? ? "#{board.winner} won the game!" : "The game was a draw!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment