carolineartz
2/20/2015 - 5:20 AM

bingo.rb

class BingoChecker
  
  def initialize (board)
    @board = board
    @key = Array.new(board.length, 'X')
  end

  def check_board
    win = in_row? || in_column? || in_descending_diagonal? || in_ascending_diagonal?
    puts "BINGO!" if win
    win
  end
  
  private
  attr_reader :board, :key

  def in_row?
    board.any? {|row| row == key}
  end

  def in_column?
    board.transpose.any? {|column| column == key}
  end

  def in_descending_diagonal?
    board.each_with_index.map {|row, index| row[index]} == key
  end
      
  def in_ascending_diagonal?
    board.each_with_index.map {|row, index| row[-1 - index]} == key
  end
end
require 'terminal-table'
require_relative 'bingo_checker'

class BingoBoard
  attr_reader :bingo_board
  LETTERS = %w(B I N G O)

  def initialize
    @bingo_board = (1..75).each_slice(15).each_with_object([]) do |range, board|
      board << range.sample(5)
    end
    @pool = LETTERS.zip((1..75).each_slice(15)).to_h
  end

  def play
    call.tap do |letter_number|
      puts "CALL: #{letter_number}\n\n"
      update(letter_number.first, letter_number.last)
    end
  end

  def to_s
    table = Terminal::Table.new :headings => LETTERS, :rows => bingo_board.transpose
    "" << table.to_s
  end

  private
  def call
    return "not a winner" if @pool.values.all?(&:empty?)
    puts "POOL: #{@pool}"
    letter = LETTERS.sample
    @pool[letter].length > 0 ? Array[letter, @pool[letter].shuffle!.pop] : call
  end

  def update(call_letter, call_number)
    bingo_board[LETTERS.index(call_letter)].map! {|square| square == call_number ? 'X' : square}
  end
end

card = BingoBoard.new
until !card.play || BingoChecker.new(card.bingo_board).check_board do
  card.play
  puts card
end