//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
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment