Skip to content

Instantly share code, notes, and snippets.

@benneuman
Created February 24, 2014 02:17
Show Gist options
  • Save benneuman/9180839 to your computer and use it in GitHub Desktop.
Save benneuman/9180839 to your computer and use it in GitHub Desktop.
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