Create a gist now

Instantly share code, notes, and snippets.

crepl Tic Tac Toe example with atom sync
(ns crepl.tic-tac-toe
(:require [reagent.core :as r]
crepl.atom-sync))
;; use this instead of reagent.core/atom to keep the state in sync
(def data (crepl.atom-sync/atom-sync {:turn :X}))
(def win-lines (-> #{}
(into (for [i (range 3)]
(for [j (range 3)]
[i j])))
(into (for [j (range 3)]
(for [i (range 3)]
[i j])))
(conj (for [d (range 3)]
[d d]))
(conj (for [d (range 3)]
[d (- 2 d)]))))
(defn find-winner [board]
(some (fn [cells]
(when-let [[winner] (#{[:X :X :X] [:O :O :O]} (map #(get-in board %) cells))]
[winner (set cells)]))
win-lines))
(defn cell [i j piece winner-cell game-over]
(let [play (fn []
(when-not (or piece game-over)
(swap! data (fn [{:keys [turn board] :as d}]
(-> d
(assoc-in [:board i j] turn)
(update :turn {:X :O, :O :X})))))
)]
[:a {:href "#", :on-click (fn [e] (play) (.preventDefault e))}
[:div {:style {"display" "inline-block"
"width" "40px"
"height" "40px"
"lineHeight" "40px"
"fontSize" "30px"
"paddingLeft" "8px"
"paddingBottom" "0px"
"color" (if piece "black" "white")
"backgroundColor" (if winner-cell "green" "white")
"borderLeft" (if (#{1 2} j)
"2px solid black"
"0px")
"borderTop" (if (#{1 2} i)
"2px solid black"
"0px")}}
(if piece (name piece) "#")]]))
(defn tic-tac-toe []
(let [{:keys [turn board]} @data
[winner winner-line] (find-winner board)
tie (when-not winner
(= (count (mapcat val board)) 9))
reset-board (fn []
(reset! data {:turn turn}))]
[:div
[:h3 "TicTacToe"]
(cond
winner
[:div (name winner) " has won! "
[:button {:on-click reset-board}
"Play again"]]
tie
[:div "Tie! "
[:button {:on-click reset-board}
"Play again"]]
:else
[:div "To play:" turn])
(for [i (range 3)
j (range 3)]
[:span {:key (+ (* j 3) i)}
[cell i j (get-in board [i j]) (contains? winner-line [i j]) (or winner tie)]
(when (= j 2) [:br])
])
]))
(r/render-component [tic-tac-toe]
(.getElementById js/document "app"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment