//Bowling Game Kata Implementation
open StateMonad
let AllPins = 10
let ZeroPins = 0
let IsStrike(roll, _) = roll = AllPins
let IsSpare(roll, nextRoll) = (roll + nextRoll) = AllPins
let SpareBonus rolls = match rolls with
| (rollA, rollB)::rolls' -> rollA
| [] -> 0
let StrikeBonus rolls = match rolls with
| (rollA,rollB)::rolls' -> rollA + if rollA = AllPins then rollA else rollB
| [] -> 0
let frames rolls =
let rec frames' rolls =
match rolls with
| rollA::rollB::[] -> [(rollA,rollB)]
| rollA::rollB::rolls' -> if (IsStrike(rollA, rollB)) then
(rollA, ZeroPins) :: frames' (rollB::rolls')
else
(rollA, rollB) :: frames' rolls'
| rollA::[] -> [(rollA, ZeroPins)]
frames' rolls
let NextScoreNoBonus prevScore rollA rollB = prevScore + rollA + rollB
let rec totals xs score =
match xs with
| (x,y)::[] when x < AllPins -> (NextScoreNoBonus score x y)
| (_,_)::[] -> score
| (x,y)::xs ->
if (IsStrike(x,y)) then
totals xs (score + x + StrikeBonus xs)
else
if (IsSpare(x,y)) then
totals xs ((NextScoreNoBonus score x y) + SpareBonus xs)
else
totals xs (NextScoreNoBonus score x y)
| [] -> score
let Score m = Execute (state { do! m
let! score = GetState
return score }) []
let Total xs = (totals (frames xs) 0)
let Roll(pins) = state { let! s = GetState
do! SetState(s @ [pins]) }
let RollList xs = state { let! xs' = MMap (fun s -> state { do! Roll s }) xs
return () }
let RollMany t s = state { do! RollList (List.map (fun _ -> s) [1..t]) }
let RollSpare = state { do! Roll 5
do! Roll 5 }
let RollStrike = state { do! Roll 10 }
Useful snippets of F# code, formatted in a way that makes it easy to copy and paste the snippet in the F# Interactive editor.
Monday, 2 March 2009
Bowling Game Kata Implementation
Bowling Game Kata Tests
// Bowling Game Kata Tests
open NUnit.Framework
open Bowling
open StateMonad
[<TestFixture>]
type BowlingTests =
new() = {}
[<Test>]
member x.gutterGame() =
Assert.AreEqual(0, Score(RollMany 20 0) |> Total)
[<Test>]
member x.allOnes() =
Assert.AreEqual(20, Score(RollMany 20 1) |> Total)
[<Test>]
member x.oneSpare() =
Assert.AreEqual(16, Score(state { do! RollSpare
do! Roll 3
do! RollMany 17 0 }) |> Total)
[<Test>]
member x.oneStrike() =
Assert.AreEqual(24, Score(state { do! RollStrike
do! Roll 3
do! Roll 4
do! RollMany 16 0 }) |> Total)
[<Test>]
member x.perfectGame() =
Assert.AreEqual(300, Score(state { do! RollMany 12 10 }) |> Total)
Subscribe to:
Posts (Atom)