Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

inital checkin

  • Loading branch information...
commit 4dcd096eab85621be0da8aec5d9f3fb6268f3784 0 parents
Carin Meier authored
4 .gitignore
@@ -0,0 +1,4 @@
+pom.xml
+*jar
+lib
+classes
16 README.markdown
@@ -0,0 +1,16 @@
+# bowling-game
+
+This is the Bowling Game Kata done in Clojure with STM. The tests use Midje. The original kata is here in Java. http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata
+
+## Usage
+
+install Leiningen https://github.com/technomancy/leiningen
+lein deps
+lein test
+
+
+## License
+
+Copyright (C) 2011 Carin Meier
+
+Distributed under the Eclipse Public License, the same as Clojure.
6 project.clj
@@ -0,0 +1,6 @@
+(defproject bowling-game "1.0.0-SNAPSHOT"
+ :description "FIXME: write"
+ :dependencies [[org.clojure/clojure "1.2.0"]
+ [org.clojure/clojure-contrib "1.2.0"]]
+ :dev-dependencies [[swank-clojure "1.2.1"]
+ [midje "1.1-alpha-1"]])
152 src/bowling_game/game.clj
@@ -0,0 +1,152 @@
+(ns bowling-game.game)
+
+(defrecord Frame [pins-hit-list])
+(defrecord Game [frame-list])
+
+(defn construct-frame [pins]
+ (Frame. [pins]))
+
+(defn construct-empty-frame []
+ (Frame. []))
+
+(defn construct-game []
+ (Game. [(construct-empty-frame)]))
+
+(def current-game (atom (construct-game)))
+
+(defn new-game []
+ (reset! current-game (construct-game)))
+
+(defn all-pins-down-old? [frame]
+ (let [frame-score (reduce + (:pins-hit-list frame))]
+ (if (nil? frame-score)
+ false
+ (if (<= 10 frame-score)
+ true
+ false))))
+
+(defn all-pins-down? [frame]
+ (let [frame-score (reduce + (:pins-hit-list frame))]
+ (if (<= 10 frame-score)
+ true
+ false)))
+
+(defn all-rolls-done? [frame]
+ (let [rolls-in-frame (count (:pins-hit-list frame))]
+ (if (<= 2 rolls-in-frame)
+ true
+ false)))
+
+(defn start-new-frame? [frame num-frames]
+ (if (or (all-pins-down? frame) (all-rolls-done? frame))
+ (if (> 10 num-frames)
+ true
+ false)
+ false))
+
+(defn add-pins-to-current-frame [frame, pins]
+ (let [pinlist (:pins-hit-list frame)]
+ (if (nil? pinlist)
+ (assoc frame :pins-hit-list (construct-frame pins))
+ (assoc frame :pins-hit-list (conj pinlist pins)))))
+
+(defn replace-end-of-list [list, item]
+ (vec (reverse (conj (rest (reverse list) ) item))))
+
+(defn add-pins-to-frame-list [frame-list, pins]
+ (let [current-frame (last frame-list)
+ new-frame (construct-frame pins)
+ num-frames (count frame-list)]
+ (if (start-new-frame? current-frame num-frames)
+ (conj frame-list new-frame)
+ (replace-end-of-list
+ frame-list
+ (add-pins-to-current-frame current-frame pins)))))
+
+(defn roll [pins]
+ (reset! current-game
+ (assoc
+ @current-game
+ :frame-list
+ (add-pins-to-frame-list (:frame-list @current-game) pins))))
+
+(defn is-spare? [frame]
+ (let [frame-score (reduce + (:pins-hit-list frame))
+ try-count (count (:pins-hit-list frame))]
+ (if (and (= 2 try-count) (= 10 frame-score))
+ true
+ false)))
+
+(defn is-strike? [frame]
+ (let [frame-score (reduce + (:pins-hit-list frame))
+ try-count (count (:pins-hit-list frame))]
+ (if (and (= 1 try-count) (= 10 frame-score))
+ true
+ false)))
+
+(defn sum-frame [frame]
+ (reduce + (:pins-hit-list frame)))
+
+(defn get-next-roll-in-frame-list [frames]
+ (first (:pins-hit-list (first frames))))
+
+(defn get-next-two-rolls-in-frame-list [frames]
+ (let [first-frame (first frames)
+ next-frame (first (rest frames))
+ last-frame? (nil? next-frame)]
+ (if last-frame?
+ (+ (first (:pins-hit-list first-frame)) (first (next (:pins-hit-list first-frame))))
+ (if (is-strike? first-frame)
+ (+ 10 (first (:pins-hit-list next-frame)))
+ (sum-frame first-frame)))))
+
+
+(defn get-next-roll-in-final-frame [frame]
+ (first (next (:pins-hit-list frame))))
+
+(defn get-next-two-rolls-in-final-frame [frame]
+ (let [roll1 (first (next (:pins-hit-list frame)))
+ roll2 (last (:pins-hit-list frame))]
+ (+ roll1 roll2)))
+
+(defn score-first-frame [frames]
+ (let [first-frame (first frames)
+ next-frames (rest frames)]
+ (if (is-spare? first-frame)
+ (+ (sum-frame first-frame) (get-next-roll-in-frame-list next-frames))
+ (if (is-strike? first-frame)
+ (+ (sum-frame first-frame) (get-next-two-rolls-in-frame-list next-frames))
+ (sum-frame first-frame)
+ ))))
+
+(defn score-last-frame [frames]
+ (let [last-frame (first frames)
+ first-roll (first (:pins-hit-list (first frames)))]
+ (if (is-spare? last-frame)
+ (+ first-roll (get-next-roll-in-final-frame last-frame))
+ (if (is-strike? last-frame)
+ (+ first-roll (get-next-two-rolls-in-final-frame last-frame))
+ (sum-frame last-frame)
+ ))))
+
+(defn sum-frames [score, frame-list]
+ (let [num-frames (count frame-list)
+ next-frames (rest frame-list)]
+ (if (= 1 num-frames)
+ (+ score (score-last-frame frame-list))
+ (+ score (sum-frames (score-first-frame frame-list) next-frames)))))
+
+(defn sum-frames-test [score, frame-list]
+ (let [num-frames (count frame-list)
+ next-frames (rest frame-list)
+ score-first (score-first-frame frame-list)]
+ (if (>= 2 num-frames)
+ score
+ (recur (+ score score-first) next-frames))))
+
+(defn score []
+ (sum-frames 0 (:frame-list @current-game)))
+
+
+
+
61 test/bowling_game/test/game.clj
@@ -0,0 +1,61 @@
+(ns bowling-game.test.game
+ (:use [bowling-game.game] :reload)
+ (:use [clojure.test])
+ (:use [midje.sweet]))
+
+
+(defn roll-many [n, pins]
+ (dorun (map roll (repeat n pins))))
+
+(defn roll-spare []
+ (do
+ (roll 5)
+ (roll 5)))
+
+(defn roll-strike []
+ (do
+ (roll 10)))
+
+(deftest testGutterGame
+ (do
+ (new-game)
+ (roll-many 20 0)
+ (fact (score) => 0)))
+
+(deftest testAllOnes
+ (do
+ (new-game)
+ (roll-many 20 1)
+ (fact (score) => 20)))
+
+
+(deftest testOneSpare
+ (do
+ (new-game)
+ (roll-spare)
+ (roll 3)
+ (roll-many 16 0)
+ (fact (score) => 16)))
+
+(deftest testOneStrike
+ (do
+ (new-game)
+ (roll-strike)
+ (roll 3)
+ (roll 4)
+ (roll-many 16 0)
+ (fact (score) => 24 )))
+
+(deftest testPerfectGame
+ (do
+ (new-game)
+ (roll-many 12 10)
+ (fact (score) => 300)
+ ))
+
+(deftest testAllFivesGame
+ (do
+ (new-game)
+ (roll-many 21 5)
+ (fact (score) => 150)
+ ))
Please sign in to comment.
Something went wrong with that request. Please try again.