require 'stringio' | |
class Io | |
attr_accessor :instream, :outstream | |
def initialize(instream, outstream) | |
self.instream = instream | |
self.outstream = outstream | |
end | |
def get_opponent | |
get_input( | |
prompt: "Should your opponent be human or computer?", | |
validation: /\A(human|computer)\Z/ | |
).to_sym | |
end | |
def get_board_size | |
get_input( | |
prompt: "What size should the board be?", | |
validation: /\A\d+\Z/ | |
).to_i | |
end | |
def get_player_move(valid_moves) | |
get_input( | |
prompt: "Where would you like to move?", | |
validation: /\A[#{valid_moves.join('')}]\Z/ | |
).to_i | |
end | |
def display_board(board) | |
outstream.puts board_as_string(board) | |
end | |
def print_winner(winner) | |
outstream.puts "The winner is #{winner}!" | |
end | |
private | |
def get_input(options) | |
prompt options[:prompt] | |
result = instream.gets.chomp | |
return result if result =~ options[:validation] | |
invalid_input result | |
get_input options | |
end | |
def board_as_string(board) | |
board.map { |e| e || ' ' } | |
.each_slice(3) | |
.map { |a, b, c| " #{a} | #{b} | #{c} \n" } | |
.join("---|---|---\n") | |
end | |
def invalid_input(input) | |
outstream.puts "You said #{input.inspect}, which is invalid" | |
end | |
def prompt(message) | |
outstream.print message, ' ' | |
end | |
end | |
RSpec.configure { |config| config.fail_fast = true } | |
describe Io do | |
def output | |
@output_stream.string | |
end | |
def io(input='') | |
instream = StringIO.new input | |
@output_stream = StringIO.new | |
described_class.new instream, @output_stream | |
end | |
describe 'asking whether opponent is human or computer' do | |
it 'can be told human' do | |
io('human').get_opponent.should == :human | |
output.should include 'human or computer' | |
output.should_not include 'invalid' | |
end | |
it 'can be told computer' do | |
io('computer').get_opponent.should == :computer | |
output.should include 'human or computer' | |
output.should_not include 'invalid' | |
end | |
it 'reprompts for human or computer' do | |
io("nonsense\ncomputer").get_opponent.should == :computer | |
output.should include 'human or computer' | |
output.should include 'invalid' | |
end | |
end | |
describe 'asking for the board size' do | |
it 'accepts integers' do | |
io('1').get_board_size.should == 1 | |
output.should include 'size' | |
end | |
it 'reprompts for the board size when given an invalid value' do | |
io("x\n1x\n2").get_board_size.should == 2 | |
output.scan(/size/).size.should == 3 | |
output.scan(/invalid/).size.should == 2 | |
end | |
end | |
it 'displays the board' do | |
empty_board = Array.new(9) { nil } | |
io.display_board(empty_board) | |
output.should == " | | \n"\ | |
"---|---|---\n"\ | |
" | | \n"\ | |
"---|---|---\n"\ | |
" | | \n" | |
one_through_nine = [*1..9] | |
io.display_board(one_through_nine) | |
output.should == " 1 | 2 | 3 \n"\ | |
"---|---|---\n"\ | |
" 4 | 5 | 6 \n"\ | |
"---|---|---\n"\ | |
" 7 | 8 | 9 \n" | |
one_through_nine.should == [*1..9] | |
end | |
it 'prints a winner message' do | |
io.print_winner 'X' | |
output.should include 'X' | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment