Skip to content

Instantly share code, notes, and snippets.

@steven-ferguson
Created September 6, 2013 00:59
Show Gist options
  • Save steven-ferguson/6458243 to your computer and use it in GitHub Desktop.
Save steven-ferguson/6458243 to your computer and use it in GitHub Desktop.
class Board
def initialize(grid_length)
@spaces = []
@grid_length = grid_length
create_spaces
end
attr_reader :spaces, :grid_length
def create_spaces
number_counter = 1
(0...@grid_length).each do |row|
(0...@grid_length).each do |column|
@spaces << Space.new(number_counter, column, row)
number_counter += 1
end
end
end
def get_row(row_number)
@spaces.select do |space|
space.row == row_number
end
end
def get_column(column_number)
@spaces.select do |space|
space.column == column_number
end
end
def get_negative_slope_diagonal
@spaces.select do |space|
space.column == space.row
end
end
def get_positive_slope_diagonal
@spaces.select do |space|
space.column + space.row == @grid_length - 1
end
end
def has_winning_combination?
winning_row? || winning_column? || winning_diagonal?
end
def winning_row?
(0...@grid_length).any? do |row_number|
row = get_row(row_number)
row.all? do |space|
space.occupying_player == row[0].occupying_player && !row[0].occupying_player.nil?
end
end
end
def winning_column?
(0...@grid_length).any? do |column_number|
column = get_column(column_number)
column.all? do |space|
space.occupying_player == column[0].occupying_player && !column[0].occupying_player.nil?
end
end
end
def winning_diagonal?
diagonals = [get_negative_slope_diagonal, get_positive_slope_diagonal]
diagonals.any? do |diagonal|
diagonal.all? do |space|
space.occupying_player == diagonal[0].occupying_player && !diagonal[0].occupying_player.nil?
end
end
end
end
require 'rspec'
require 'game'
require 'player'
require 'board'
require 'space'
describe Board do
it 'intializes with a grid length' do
board = Board.new(3)
board.should be_an_instance_of Board
end
it 'creates spaces based on the board size' do
board = Board.new(4)
board.spaces.length.should eq 16
end
it 'creates spaces with the right number, column, and row' do
board = Board.new(3)
board.spaces[4].number.should eq 5
board.spaces[4].column.should eq 1
board.spaces[4].row.should eq 1
end
describe 'get_row' do
it 'gets all the spaces from a specified row' do
board = Board.new(3)
row = board.get_row(0)
row[0].number.should eq 1
row[1].number.should eq 2
row[2].number.should eq 3
end
end
describe 'get_column' do
it 'gets all the spaces from a specified column' do
board = Board.new(3)
column = board.get_column(0)
column[0].number.should eq 1
column[1].number.should eq 4
column[2].number.should eq 7
end
end
describe 'get_negative_slope_diagonal' do
it 'gets all the spaces in the diagonal' do
board = Board.new(3)
diagonal = board.get_negative_slope_diagonal
diagonal[0].number.should eq 1
diagonal[1].number.should eq 5
diagonal[2].number.should eq 9
end
end
describe 'get_positive_slope_diagonal' do
it 'gets all the spaces of the diagonal' do
board = Board.new(3)
diagonal = board.get_positive_slope_diagonal
diagonal[0].number.should eq 3
diagonal[1].number.should eq 5
diagonal[2].number.should eq 7
end
end
describe 'winning_row?' do
it 'is false if all the spaces in a row are not occupied by the same player' do
board = Board.new(3)
board.winning_row?.should eq false
end
it 'is true if all the spaces in a row are occupied by the same player' do
board = Board.new(4)
player = Player.new('X')
board.spaces[0].occupy(player)
board.spaces[1].occupy(player)
board.spaces[2].occupy(player)
board.spaces[3].occupy(player)
board.winning_row?.should eq true
end
end
describe 'winning_column?' do
it 'is false if all the spaces in a column are not occupied by the same player' do
board = Board.new(3)
board.winning_column?.should eq false
end
it 'is true if all the spaces in a column are occupied by the same player' do
board = Board.new(4)
player = Player.new('X')
board.spaces[0].occupy(player)
board.spaces[4].occupy(player)
board.spaces[8].occupy(player)
board.spaces[12].occupy(player)
board.winning_column?.should eq true
end
end
describe 'winning_diagonal?' do
it 'is false if all the spaces in both diagonals are not occupied by the same player' do
board = Board.new(3)
board.winning_diagonal?.should eq false
end
it 'is true if all the spaces in a diagonal are occupied by the same player' do
board = Board.new(3)
player = Player.new('X')
board.spaces[0].occupy(player)
board.spaces[4].occupy(player)
board.spaces[8].occupy(player)
board.winning_diagonal?.should eq true
end
end
describe 'has_winning_combination?' do
it 'is false when the board does not have a winning combination' do
board = Board.new(3)
board.has_winning_combination?.should eq false
end
it 'is true when there is a winning comibination' do
board = Board.new(3)
player = Player.new('X')
board.spaces[0].occupy(player)
board.spaces[1].occupy(player)
board.spaces[2].occupy(player)
board.has_winning_combination?.should eq true
end
end
end
class Game
def initialize(number_of_players=2, board_size=3)
@players = []
create_players(number_of_players)
@current_player = @players[0]
@board = Board.new(board_size)
end
attr_reader :players, :current_player, :board
def create_players(number_of_players)
symbols = { 0 => 'X', 1 => 'O', 2 => '@', 3 => '$', 4 => '&' }
number_of_players.times do |i|
@players << Player.new(symbols[i])
end
end
def switch_current_player
@current_player = @players.pop
@players.unshift(@current_player)
end
def has_winner?
@board.has_winning_combination?
end
def over?
@board.spaces.all? { |space| space.occupied? } || has_winner?
end
def tie?
@board.spaces.all? { |space| space.occupied? } && !has_winner?
end
end
require 'rspec'
require 'game'
require 'player'
require 'board'
require 'space'
describe Game do
it 'is initialized with a number of players and board size' do
game = Game.new(2, 3)
game.should be_an_instance_of Game
end
it 'has players' do
game = Game.new(3, 3)
game.players.length.should eq 3
end
it 'has a board' do
game = Game.new(3, 3)
game.board.should be_an_instance_of Board
end
it 'has a current player' do
game = Game.new(3, 3)
game.current_player.symbol.should eq 'X'
end
it 'can switch the current player' do
game = Game.new(2, 3)
game.switch_current_player
game.current_player.symbol.should eq 'O'
end
describe 'has_winner?' do
it 'is true if there is a winner' do
game = Game.new(2, 3)
game.board.spaces[0].occupy(game.current_player)
game.board.spaces[1].occupy(game.current_player)
game.board.spaces[2].occupy(game.current_player)
game.has_winner?.should eq true
end
it 'is false if there is no winner' do
game = Game.new(2, 3)
game.has_winner?.should eq false
end
end
describe 'over?' do
it 'is true when all the spaces are occupied' do
game = Game.new(2, 4)
game.board.spaces.each do |space|
space.occupy(game.current_player)
end
game.over?.should eq true
end
it 'is true if the board has a winning combination' do
game = Game.new(2, 3)
game.board.spaces[0].occupy(game.current_player)
game.board.spaces[1].occupy(game.current_player)
game.board.spaces[2].occupy(game.current_player)
game.over?.should eq true
end
end
describe 'tie?' do
it 'is true if the game is over and there is no winner' do
game = Game.new
game.board.spaces[0].occupy(game.current_player)
game.board.spaces[1].occupy(game.current_player)
game.board.spaces[5].occupy(game.current_player)
game.board.spaces[6].occupy(game.current_player)
game.switch_current_player
game.board.spaces[2].occupy(game.current_player)
game.board.spaces[3].occupy(game.current_player)
game.board.spaces[4].occupy(game.current_player)
game.board.spaces[7].occupy(game.current_player)
game.board.spaces[8].occupy(game.current_player)
game.tie?.should eq true
end
end
end
class Player
def initialize(symbol)
@symbol = symbol
end
attr_reader :symbol
end
require 'rspec'
require 'game'
require 'player'
require 'board'
require 'space'
describe Player do
it 'is initialized with a symbol' do
player = Player.new('X')
player.should be_an_instance_of Player
end
it 'has a symbol' do
player = Player.new('X')
player.symbol.should eq 'X'
end
end
class Space
def initialize(number, column, row)
@number = number
@column = column
@row = row
@mark = number
end
attr_reader :number, :occupying_player, :mark, :column, :row
def occupy(player)
@occupying_player = player
@mark = player.symbol
end
def occupied?
occupying_player != nil
end
end
require 'rspec'
require 'game'
require 'player'
require 'board'
require 'space'
describe Space do
it 'initializes with a number, column and row' do
space = Space.new(1, 0, 0)
space.should be_an_instance_of Space
end
it 'has a mark' do
space = Space.new(1, 0, 0)
space.mark.should eq 1
end
it 'is occupied by no one when created' do
space = Space.new(1, 0, 0)
space.occupying_player.should eq nil
end
it 'can be occupied by a player' do
space = Space.new(1, 0, 0)
player = Player.new('X')
space.occupy(player)
space.occupying_player.should eq player
end
it 'has its mark changed when it is occupied' do
space = Space.new(1, 0, 0)
player = Player.new('X')
space.occupy(player)
space.mark.should eq 'X'
end
describe 'occupied?' do
it "is false if a player is not occupying the space" do
space = Space.new(1, 0, 0)
space.occupied?.should eq false
end
it 'is true if a player is occupying the space' do
space = Space.new(1, 0, 0)
player = Player.new('X')
space.occupy(player)
space.occupied?.should eq true
end
end
end
class ThreeDBoard
def initialize
@boards = [Board.new, Board.new, Board.new]
end
attr_reader :boards
def straight_down_win?
(0..8).any? do |board_space_index|
@boards[0].spaces[board_space_index].occupying_player == @boards[1].spaces[board_space_index].occupying_player && @boards[1].spaces[board_space_index].occupying_player == @boards[2].spaces[board_space_index].occupying_player
end
end
end
require 'rspec'
require 'three_d_board'
require 'game'
require 'player'
require 'board'
require 'space'
describe ThreeDBoard do
it 'has 3 boards' do
three_d_board = ThreeDBoard.new
three_d_board.boards.length.should eq 3
end
describe 'straight_down_win?' do
it 'is true if the same space in each board is occupied by the same player' do
three_d_board = ThreeDBoard.new
player = Player.new('X')
three_d_board.boards[0].spaces[0].occupy(player)
three_d_board.boards[1].spaces[0].occupy(player)
three_d_board.boards[2].spaces[0].occupy(player)
three_d_board.straight_down_win?.should eq true
end
end
end
require './lib/game'
require './lib/player'
require './lib/board'
require './lib/space'
@game = Game.new
def draw_board(board)
puts "\n\n"
puts "-------" * board.grid_length
(0...board.grid_length).each do |row_number|
board.get_row(row_number).each do |space|
if space.number < 10
print "| #{space.mark} |"
elsif space.mark.to_i == 0
print "| #{space.mark} |"
else
print "| #{space.mark} |"
end
end
puts "\n"
puts "-------" * board.grid_length
end
puts "\n\n"
end
def new_game_menu
puts "==================================================================="
puts "******************** Welcome to Tic-Tac-Toe! ********************"
puts "==================================================================="
puts "\n"
puts "How many players?"
number_of_players = gets.to_i
puts "How big of a board would you like?"
grid_size = gets.to_i
@game = Game.new(number_of_players, grid_size)
draw_board(@game.board)
turn_menu
end
def turn_menu
puts "==================================================================="
puts "It's #{@game.current_player.symbol}'s turn! Enter the number of the space you'd like to mark."
puts "==================================================================="
player_selection
if @game.has_winner?
puts "#{@game.current_player.symbol} wins!"
play_again
elsif @game.tie?
puts "Cat's game!"
play_again
else
@game.switch_current_player
turn_menu
end
end
def player_selection
chosen_space_index = gets.to_i - 1
if chosen_space_index < 0 || chosen_space_index > @game.board.spaces.length
puts "That is not a valid space number. Please choose again."
player_selection
elsif @game.board.spaces[chosen_space_index].occupied?
puts "That space is already occupied. Please choose a different space."
player_selection
else
@game.board.spaces[chosen_space_index].occupy(@game.current_player)
draw_board(@game.board)
end
end
def play_again
puts "Would you like to play again? (Y / N)"
choice = gets.chomp.downcase
if choice == 'y'
new_game_menu
elsif choice == 'n'
puts "Good-bye!"
else
puts "Sorry, I didn't understand that"
play_again
end
end
new_game_menu
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment