Created
October 18, 2018 07:07
-
-
Save cwervo/9fe0d083f0a1a63393625b1be963c507 to your computer and use it in GitHub Desktop.
An entry for my Recurse Center pairing interview! Note: this requires boot to run Clojure!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env boot | |
;; Note: this script requires Boot to run: https://github.com/boot-clj/boot#install | |
(def state (atom ["1" "2" "3" | |
"4" "5" "6" | |
"7" "8" "9"])) | |
;; Test state | |
#_(def state (atom ["X" "X" "3" | |
"4" "X" "6" | |
"O" "O" "9"])) | |
(def current-player (atom 1)) | |
(defn exit [] (System/exit 0)) | |
(defn get-next-line [] (flush) (first (line-seq (java.io.BufferedReader. *in*)))) | |
(defn threeven? [n] (= 0 (mod n 3))) | |
(defn clear-screen [] | |
; clear screen | |
(print (str (char 27) "[2J")) | |
; move cursor to the top left corner of the screen | |
(print (str (char 27) "[;H"))) | |
(defn print-state [board] | |
(dorun | |
(map-indexed | |
(fn [idx itm] | |
(let [index-is-threeven (-> idx | |
inc | |
threeven?)] | |
(print (str itm (if index-is-threeven "\n" " | "))))) | |
board)) | |
(println)) | |
(defn in-board-bounds? [n] | |
(and (> n 0) | |
(< n 10))) | |
(defn string-is-number? [s] (some? (re-find #"^-?\d+$" s))) | |
(defn parse-int [s] | |
(Integer. s)) | |
(defn spot-not-taken? [n] | |
(let [current-char (get @state n)] | |
(and (not= "X" current-char) | |
(not= "O" current-char)))) | |
(defn retake-input [error-prompt] | |
(println error-prompt) | |
(get-next-line)) | |
(defn validate-input [input] | |
(loop [recursiveInput input] | |
(when (re-matches #"^q(uit)?" recursiveInput) | |
(println "👋🏼") | |
(exit)) | |
(if (string-is-number? recursiveInput) | |
;; First case (is a number): | |
(let [n (parse-int recursiveInput)] | |
(if (in-board-bounds? n) | |
;; Need to decriment because UI numbering is +1 of indexes :) | |
(if (spot-not-taken? (dec n)) | |
n | |
(recur (retake-input (str "whoops, try again, spot " recursiveInput " is already taken")))) | |
(recur (retake-input (str "whooops, try again, " recursiveInput " is out of bounds"))))) | |
;; Second case (not a number): | |
(recur (retake-input (str "whooops, try again, " recursiveInput " is not a number")))))) | |
(defn all-same? [collection-of-three] | |
(= 1 (count (distinct collection-of-three)))) | |
(defn check-collection [collection] | |
(when (all-same? collection) | |
(let [row-symbol (first collection) | |
player-number (if (= "X" row-symbol) | |
1 | |
2)] | |
(println (str "Game over! Player " player-number " ("row-symbol") wins! 🎉")) | |
(exit)))) | |
(defn get-from-state [one two three] | |
[(get @state one) | |
(get @state two) | |
(get @state three)]) | |
(defn check-for-win [] | |
;; Brute force check | |
;; first row | |
(check-collection (subvec @state 0 3)) | |
;; second row | |
(check-collection (subvec @state 3 6)) | |
;; third row | |
(check-collection (subvec @state 6 9)) | |
;; first column | |
(check-collection (get-from-state 0 3 6)) | |
;; second column | |
(check-collection (get-from-state 1 4 7)) | |
;; thrid column | |
(check-collection (get-from-state 2 5 8)) | |
;; diagonal-1-9 column | |
(check-collection (get-from-state 0 4 8)) | |
;; diagonal-7-3 column | |
(check-collection (get-from-state 6 4 2))) | |
(defn current-sign [] | |
(get ["X" "O"] (dec @current-player))) | |
(defn evaluate-game-info [] | |
(clear-screen) | |
(println "current state of the board:") | |
(print-state @state) | |
(check-for-win) | |
(println (str "Current player: " @current-player " ("(current-sign)"'s)"))) | |
(while true | |
(evaluate-game-info) | |
(let [index (dec (validate-input (get-next-line)))] | |
;; Process current player move | |
(swap! | |
state | |
assoc index (current-sign)) | |
(swap! current-player #(if (= %1 2) 1 2)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment