Skip to content

Instantly share code, notes, and snippets.

(defn get-owner-at
"Get the owner associated to the cell"
[board coord]
{:pre [(coordinates? coord)]}
(get board coord))
(defn has-owner?
"Check whether the coord has an owner associated to it"
[board coord]
{:pre [(coordinates? coord)]}
(def winning-diags
[(filter #(= (first %) (second %)) board/coordinates)
(filter #(= (dec board/size) (reduce + %)) board/coordinates)])
(def winning-rows (partition board/size board/coordinates))
(def winning-lines (algo/transpose winning-rows))
(def winning-cell-sets (concat winning-rows winning-lines winning-diags))
(defn- sole-owner
"Indicates whether all positions are owned by the same player"
[board positions]
(let [owners (set (map #(board/get-owner-at board %) positions))]
(case owners
#{:owner/circle} :owner/circle
#{:owner/cross} :owner/cross
nil)))
(defn get-winner
(defn game-over?
"The game is over if either:
* The board is full
* There is a winner"
[{:keys [board]}]
(or
(board/full-board? board)
(has-winner? board)))
(defn next-turn
"Convert a cell to the player color and switch player"
[turn coord]
(if-not (or (game-over? turn) (invalid-move? turn coord))
(-> turn
(update :board board/convert-cell (:player turn) coord)
(update :player next-player))))
(defn tic-tac-toe
"Main entry point, assemble:
* the game state
* the game view"
[]
[frame/render @store/current-turn
{:on-restart #(store/send-event! :restart)
:on-undo #(store/send-event! :undo)
:on-move #(store/send-event! %)}])
(defn- get-winner-name
[turn]
(if-let [winner (turn/get-winner turn)]
(clojure.string/capitalize (name winner))))
(defn get-title
[turn]
(if-let [winner-name (get-winner-name turn)]
(str winner-name " wins")
(if (turn/game-over? turn)
(def width 16)
(def height 11)
(s/def ::board
(s/every
(s/every ::player/owner :count height)
:count width))
(def empty-board
"An empty board of `width` columns times `height` owners"
(let [empty-column (vec (repeat height :none))]
(vec (repeat width empty-column))))