Skip to content

Instantly share code, notes, and snippets.

@fj
Created July 10, 2014 05:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fj/39c3462fa25fe187ca69 to your computer and use it in GitHub Desktop.
Save fj/39c3462fa25fe187ca69 to your computer and use it in GitHub Desktop.
My work on the Uncle Bob bowling kata.
class Game
def roll(*pins)
(@rolls ||= []).push *pins
end
def score
scores.inject(:+)
end
def scores
[].tap do |frame_scores|
10.times do
score, taken = score_frame(@rolls)
@rolls = @rolls.drop(taken)
frame_scores << score
end
end
end
def score_frame(rolls)
rolls_for_scoring, rolls_in_this_frame = case frame_kind(rolls)
when :strike then [3, 1]
when :spare then [3, 2]
when :open then [2, 2]
end
[rolls.take(rolls_for_scoring).inject(:+), rolls_in_this_frame]
end
def frame_kind(rolls)
first, second = rolls
return :strike if first == 10
return :spare if first + second == 10
return :open
end
end
require 'spec_helper'
require 'lib/game'
describe Game do
let(:game) { described_class.new }
def roll(*rolls)
game.roll(*rolls.flatten)
end
def frames(n, frame = [0, 0])
Array.new(n, frame)
end
it "scores twelve strikes as 300" do
roll frames(12, [10])
expect(game.score).to eq 300
end
it "scores ten gutter frames as 0" do
roll frames(10)
expect(game.score).to eq 0
end
it "scores ten open frames as their sums" do
roll frames(10, [2, 3])
expect(game.score).to eq 50
end
it "scores a spare as 10 plus next roll" do
roll 4, 6, 7, 3, frames(8)
expect(game.scores.first).to eq 17
end
it "scores a strike as 10 plus next two rolls" do
roll 10, 4, 6, 7, 3, frames(7)
expect(game.scores.first).to eq 20
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment