Skip to content

Instantly share code, notes, and snippets.

@Arham4
Last active July 20, 2020 23:19
Show Gist options
  • Save Arham4/8d7845b4d277d80e3296d6e7628ddd49 to your computer and use it in GitHub Desktop.
Save Arham4/8d7845b4d277d80e3296d6e7628ddd49 to your computer and use it in GitHub Desktop.
Clojure Rock-Paper-Scissors
(ns clojure-rock-paper-scissors.clojure_rock_paper_scissor
(:require [clojure-rock-paper-scissors.utils :refer :all]))
(def results #{:player-1-win :player-2-win :tie})
(def types #{:rock :paper :scissor})
(def game-modes #{:one-player :two-player})
(def guess-map {"r" :rock, "p" :paper, "s" :scissor})
(defn get-type [raw-type]
(get guess-map raw-type))
(defn get-type-from-console []
(let [raw-type (read-line)]
(get-type raw-type)))
(defn get-random-type []
(get-type (rand-nth (keys guess-map))))
(defn get-result [type1 type2]
(let [type-pair [type1 type2]]
(if (= type1 type2)
:tie
(case type-pair
[:rock :scissor] :player-1-win
[:scissor :rock] :player-2-win
[:paper :rock] :player-1-win
[:rock :paper] :player-2-win
[:scissor :paper] :player-1-win
[:paper :scissor] :player-2-win))))
(defn print-result [result game-mode]
(let [player-1-name (cond
(= game-mode :one-player) "Player"
(= game-mode :two-player) "Player 1")
player-2-name (cond
(= game-mode :one-player) "Computer"
(= game-mode :two-player) "Player 2")]
(cond
(= result :player-1-win) (println player-1-name "wins!")
(= result :player-2-win) (println player-2-name "wins!")
(= result :tie) (println "It's a tie!"))))
(defn get-game-mode [single-player-input two-player-input]
(let [input (read-line)]
(cond
(eq-ignore-case input single-player-input) :one-player
(eq-ignore-case input two-player-input) :two-player)))
(defn print-prompt []
(println "Enter either (r)ock, (p)aper, or (s)cissors"))
(defn- main []
(println "Do you want to play single-player mode? ((y)es = single-player, (n)o = two-player)")
(let [game-mode (get-game-mode "y" "n")]
(if (nil? game-mode)
(println "Invalid input for game mode!")
(do
(print-prompt)
(let [player-1-type (get-type-from-console)]
(if (= game-mode :two-player)
(print-prompt))
(let [player-2-type (cond
(= game-mode :one-player) (get-random-type)
(= game-mode :two-player) (get-type-from-console))]
(if (or (nil? player-1-type) (nil? player-2-type))
(println "That is not a valid type! Either \"r\", \"p\", or \"s\"!")
(print-result (get-result player-1-type player-2-type) game-mode))))))))
(ns clojure-rock-paper-scissors.clojure_rock_paper_scissor-test
(:require [clojure.test :refer :all]
[clojure-rock-paper-scissors.clojure_rock_paper_scissor :refer :all]))
(deftest get-type-test
(testing "r returns rock"
(is (= (get-type "r") :rock)))
(testing "p returns paper"
(is (= (get-type "p") :paper)))
(testing "s returns scissor"
(is (= (get-type "s") :scissor)))
(testing "other char returns nil"
(is (= (get-type "o") nil))))
(deftest results-test
(testing "rock beats scissors"
(is (= (get-result :rock :scissor) :player-1-win)))
(testing "paper beats rock"
(is (= (get-result :paper :rock) :player-1-win)))
(testing "scissor beats paper"
(is (= (get-result :scissor :paper) :player-1-win)))
(testing "scissor loses to rock"
(is (= (get-result :scissor :rock) :player-2-win)))
(testing "rock ties with rock"
(is (= (get-result :rock :rock) :tie))))
(ns clojure-rock-paper-scissors.utils)
(defn eq-ignore-case [str1 str2]
(= (clojure.string/lower-case str1) (clojure.string/lower-case str2)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment