diff --git a/resources/public/cljs/tictactoe.cljs b/resources/public/cljs/tictactoe.cljs new file mode 100644 index 0000000..a0f4229 --- /dev/null +++ b/resources/public/cljs/tictactoe.cljs @@ -0,0 +1,87 @@ +(ns tictactoe + "Ported from https://github.com/borkdude/tictactoe-cljs" + (:require [reagent.core :as r] + [reagent.dom :as rdom])) + +(defn foo [] (< 1 2)) + +(def empty-board [[\- \- \-] + [\- \- \-] + [\- \- \-]]) + +(def state (r/atom {:board empty-board :player \X})) + +(defn get-board-cell + ([board row col] + (get-in board [row col]))) + +(defn get-player [app-state] + (-> app-state :game-state :player)) + +(defn other-player [player] + (if (= player \X) \O \X)) + +(defn winner-in-rows? [board player] + (boolean (some (fn [row] (every? (fn [c] (= c player)) row)) board))) + +(defn transposed-board [board] + (vec (apply map vector board))) + +(defn winner-in-cols? [board player] + (winner-in-rows? (transposed-board board) player)) + +(defn winner-in-diagonals? [board player] + (let [diag-coords [[[0 0] [1 1] [2 2]] + [[0 2] [1 1] [2 0]]]] + (boolean (some (fn [coords] + (every? (fn [coord] + (= player (apply get-board-cell board coord))) + coords)) + diag-coords)))) + +(defn winner? + "checks if there is a winner. when called with no args, checks for player X and player O. +returns the character for the winning player, nil if there is no winner" + ([board] + (boolean (or (winner? board \X) + (winner? board \O)))) + ([board player] + (when (or (winner-in-rows? board player) + (winner-in-cols? board player) + (winner-in-diagonals? board player)) + player))) + +(defn full-board? + [board] + (let [all-cells (apply concat board)] + (not-any? #(= % \-) all-cells))) + +(defn new-state [old-state row col] + (if (and (= (get-board-cell (:board old-state) row col) \-) + (not (winner? (:board old-state)))) + {:board (assoc-in (:board old-state) [row col] (:player old-state)) + :player (other-player (:player old-state))} + old-state)) + +(defn tictactoe [] + [:div + (if (winner? (:board @state)) + (str "The winner is " (other-player (:player @state))) + (if (full-board? (:board @state)) + "It's a draw" + (str "Your turn, player " (:player @state)))) + (let [board (-> @state :board)] + [:table + [:tbody + (map-indexed + (fn [i row] + ^{:key i} + [:tr + (map-indexed (fn [j elt] + ^{:key j} + [:td {:on-click (fn [] + (swap! state new-state i j))}elt]) + row)]) + board)]])]) + +(rdom/render [tictactoe] (.getElementById js/document "app")) diff --git a/resources/public/index.html b/resources/public/index.html index 05e33d3..05cc17d 100644 --- a/resources/public/index.html +++ b/resources/public/index.html @@ -24,7 +24,6 @@ - @@ -104,6 +103,8 @@ </script> + Also see a tic-tac-toe demo. +
diff --git a/resources/public/tictactoe.html b/resources/public/tictactoe.html new file mode 100644 index 0000000..387f05c --- /dev/null +++ b/resources/public/tictactoe.html @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + +The following source was loaded from cljs/tictactoe.cljs:
+
+
+
+