# frozen_string_literal: true
require_relative './rack'
require_relative './display'
require_relative './game'
game = Game.new
game.play_game
# frozen_string_literal: true
# contains rack state
class Rack
attr_reader :rows
def initialize
@rows = Array.new(7) { Array.new(6, '.') }
@piece = ['X', 'O']
end
def four_in_row?
lines.any? do |line|
line.each_cons(4).any? { |a| a.all?(a[0]) unless a[0] == '.' }
end
end
def insert_piece(row, rows = @rows[row - 1])
rows.any?('.') ? rows[rows.index('.')] = @piece[0] : false
end
private
def columns
@rows.transpose
end
def diagonals
rotate_each(pad, -1, 1) + rotate_each(pad('l'), 1, -1)
end
def lines
@rows + columns + diagonals
end
def rotate_each(arr, shift, base)
arr.map { |row| row.rotate(base += shift) }.transpose
end
def pad(side = 'r', pad = ['.'] * 6)
@rows.map { |row| side == 'r' ? row + pad : pad + row }
end
end
# frozen_string_literal: true
# contains logic for looping gameplay script
class Game
include Display
def initialize
@rack = Rack.new
@player = [1, 2]
@column = ''
end
def loop_verify
ask_for_column
gets_column_choice
return if input_verified? && @rack.insert_piece(@column.to_i)
puts_typo
loop_verify
end
def draw?
@rack.rows.none? { |row| row.any? '.' }
end
def input_verified?
@column.match?(/^[1-7]$/)
end
def switch_player
@player.reverse!
@rack.instance_variable_get(:@piece).reverse!
end
def play_game
until @rack.four_in_row? || draw?
loop_verify
print_rows
switch_player
end
game_over_msg
end
private
def gets_column_choice
@column = gets.chomp
end
end
# frozen_string_literal: true
# prints messages and board to player
module Display
private
def print_rows(rows = @rack.rows)
6.times do |i|
rows.each { |row| print row[-1 - i] }
puts
end
end
def ask_for_column
puts "Player #{@player[0]}, choose a column 1 thru 7."
end
def puts_typo
puts 'Typo or column full. Try again.'
end
def game_over_msg
puts @rack.four_in_row? ? "Player #{@player[-1]} wins!" : 'Draw!'
end
end