Created
February 24, 2014 02:17
-
-
Save benneuman/9180839 to your computer and use it in GitHub Desktop.
This file contains 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
require 'rspec' | |
#all gutters -> 0 | |
#scores twenty with one pin knocked down every roll | |
#spare in frame 1 followed by 3 pins = 16 | |
#strike -> 3-> 4 = 24 | |
#perfect game -> 300 | |
class BowlingGame | |
attr_reader :scorecard | |
def initialize | |
@scorecard = Scorecard.new | |
end | |
def roll(amount) | |
@scorecard.log_roll(amount) | |
end | |
def score | |
@scorecard.score | |
end | |
end | |
class Scorecard | |
attr_reader :frames, :current_frame | |
def initialize | |
@frames = (1..9).collect { |n| Frame.new(n, self) } + [TenthFrame.new] | |
@current_frame = @frames.find { |f| f.number == 1 } | |
end | |
def find(&block) | |
@frames.find(&block) | |
end | |
def log_roll(roll) | |
@current_frame.log_roll(roll) | |
@current_frame = @current_frame.next_frame if @current_frame.finished? | |
end | |
def score | |
@frames.reduce(0) { |score, frame| score += frame.score } | |
end | |
end | |
class TenthFrame | |
attr_accessor :roll1, :roll2, :roll3, :number | |
def initialize | |
@number = 10 | |
end | |
def log_roll(roll) | |
if @roll1.nil? | |
@roll1 = roll | |
elsif roll2.nil? | |
@roll2 = roll | |
else | |
@roll3 = roll | |
end | |
end | |
def next_frame | |
nil | |
end | |
def strike? | |
false | |
end | |
def score | |
@roll1 + @roll2 + @roll3.to_i | |
end | |
def finished? | |
(!(roll1.nil?) && !(roll2.nil?)) && ( | |
!(roll3.nil?) || | |
roll1 + roll2 < 10) | |
end | |
end | |
class Frame | |
attr_accessor :roll1, :roll2, :number | |
def initialize(number, scorecard) | |
@number = number | |
@scorecard = scorecard | |
end | |
def log_roll(roll) | |
if @roll1.nil? | |
@roll1 = roll | |
else | |
@roll2 = roll | |
end | |
end | |
def score | |
raw_score + bonus | |
end | |
def next_frame | |
@scorecard.find { |frame| frame.number == @number + 1 } | |
end | |
def finished? | |
roll1 == 10 || !(roll1.nil?) && !(roll2.nil?) | |
end | |
def raw_score | |
roll1 + roll2.to_i | |
end | |
def bonus | |
case | |
when strike? then strike_bonus | |
when spare? then spare_bonus | |
else 0 | |
end | |
end | |
def strike_bonus | |
if next_frame.strike? | |
10 + next_frame.next_frame.roll1 | |
else | |
next_frame.roll1 + next_frame.roll2 | |
end | |
end | |
def spare_bonus | |
next_frame.roll1 | |
end | |
def strike? | |
@roll1 == 10 | |
end | |
def spare? | |
@roll1 + @roll2 == 10 && !(@roll2.nil?) | |
end | |
end | |
describe BowlingGame do | |
let(:bowling_game) {BowlingGame.new} | |
context "#score" do | |
it "is 0 for game with all gutters" do | |
20.times{bowling_game.roll(0)} | |
expect(bowling_game.score).to eq 0 | |
end | |
it "is 20 for game with all ones" do | |
20.times{bowling_game.roll(1)} | |
expect(bowling_game.score).to eq 20 | |
end | |
it "is 16 for game with spare followed by 3" do | |
bowling_game.roll(5) | |
bowling_game.roll(5) | |
bowling_game.roll(3) | |
17.times { bowling_game.roll(0)} | |
expect(bowling_game.score).to eq 16 | |
end | |
it "is 24 for game with strike followed by 3 and 4" do | |
bowling_game.roll(10) | |
bowling_game.roll(4) | |
bowling_game.roll(3) | |
16.times { bowling_game.roll(0) } | |
expect(bowling_game.score).to eq 24 | |
end | |
it "is 300 for perfect game" do | |
12.times { bowling_game.roll(10) } | |
expect(bowling_game.score).to eq 300 | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment