Skip to content

Instantly share code, notes, and snippets.

@fj
Created Jul 10, 2014
Embed
What would you like to do?
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