Permalink
Browse files

refactored - a game is now expressible as a pure function

you pass it winlogic, and a (player, throws) tuple where throws is a possibly
infinite sequence of throws.  right now it's backed by prompted-for input
from the console
  • Loading branch information...
1 parent 860272f commit 29c58f9687dca873e0c8dc95f3d3fbbbfda185b4 @youngnh committed Sep 27, 2010
Showing with 27 additions and 26 deletions.
  1. +12 −12 rps/src/rps/core.clj
  2. +15 −14 rps/test/rps/test/core.clj
View
24 rps/src/rps/core.clj
@@ -18,15 +18,13 @@
:paper :rock} throw)
other))
-(defn play-round []
- (let [throw (prompt-for-throw)
- other (prompt-for-throw)]
- (cond (beats throw other) [1 0]
- (beats other throw) [0 1]
- :otherwise [0 0])))
+(defn score-round [throw other]
+ (cond (beats throw other) [1 0]
+ (beats other throw) [0 1]
+ :otherwise [0 0]))
-(defn play-round-and-score [scores]
- (map + scores (play-round)))
+(defn add-score [score1 score2]
+ (map + score1 score2))
(defn win-by [by _ n]
(let [won? (fn [score1 score2]
@@ -40,11 +38,13 @@
(defn best-of [n] (first-to (inc (quot n 2))))
+(defn game [winlogic [player1 p1throws] [player2 p2throws]]
+ (some #(winlogic % [player1 player2]) (reductions add-score [0 0] (map score-round p1throws p2throws))))
+
(defn rps
([] (rps (first-to 1)))
([winlogic]
- (let [player1 (prompt-for-username "Player 1")
- player2 (prompt-for-username "Player 2")
- winner (some #(winlogic % [player1 player2])
- (iterate play-round-and-score [0 0]))]
+ (let [player1 [(prompt-for-username "Player 1") (repeatedly prompt-for-throw)]
+ player2 [(prompt-for-username "Player 2") (repeatedly prompt-for-throw)]
+ winner (game winlogic player1 player2)]
(println winner "Wins!"))))
View
29 rps/test/rps/test/core.clj
@@ -48,21 +48,17 @@
:scissors :rock)))
(deftest test-play-round
- (testing "prompts both players for a throw"
- (binding [*in* (reader (StringReader. "R\nS\n"))]
- (is (starts-with? (output-of (play-round))
- (join (take 2 (repeat "[R]ock, [P]aper, or [S]cissors? ")))))))
-
(testing "returns score based on who had wining throw"
- (let [rock-v-scissors (reader (StringReader. "R\nS\n"))
- paper-v-scissors (reader (StringReader. "P\nS\n"))
- rock-v-rock (reader (StringReader. "R\nR\n"))]
- (are [input-stream expected-score] (binding [*in* input-stream
- *out* (StringWriter.)]
- (= expected-score (play-round)))
- rock-v-scissors [1 0]
- paper-v-scissors [0 1]
- rock-v-rock [0 0]))))
+ (are [throw other expected-score] (= expected-score (score-round throw other))
+ :rock :scissors [1 0]
+ :paper :scissors [0 1]
+ :rock :rock [0 0])))
+
+(deftest test-add-score
+ (testing "adds two scores together"
+ (are [score1 score2 expected] (= expected (add-score score1 score2))
+ [0 0] [0 0] [0 0]
+ [1 2] [1 0] [2 2])))
(deftest test-first-to
(let [test-fn (first-to 3)]
@@ -112,6 +108,11 @@
(is (nil? (test-fn [18 19] ["Ghandi" "Lincoln"])))
(is (nil? (test-fn [19 19] ["Ghandi" "Lincoln"]))))))
+(deftest test-game
+ (testing "a game reads throws until the win logic produces a winner"
+ (is (= "Ghandi" (game (first-to 1) ["Ghandi" [:paper]] ["Lincoln" [:rock]])))
+ (is (= "Ghandi" (game (first-to 5) ["Ghandi" (repeat :paper)] ["Lincoln" (repeat :rock)])))))
+
(deftest test-scripted-games
(testing "one throw games"
(are [filename]

0 comments on commit 29c58f9

Please sign in to comment.