diff --git a/cljs/tictactoe.cljs b/cljs/tictactoe.cljs new file mode 100644 index 0000000..a0f4229 --- /dev/null +++ b/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/index.html b/index.html index 05e33d3..05cc17d 100644 --- a/index.html +++ b/index.html @@ -24,7 +24,6 @@ - @@ -104,6 +103,8 @@ </script> + Also see a tic-tac-toe demo. +
diff --git a/js/sci-script-tag-plugin-reagent.js b/js/sci-script-tag-plugin-reagent.js index dacce81..6a99ecb 100644 --- a/js/sci-script-tag-plugin-reagent.js +++ b/js/sci-script-tag-plugin-reagent.js @@ -1,322 +1,22 @@ -(function(){ -shadow$provide[0]=function(P,aa,na,x){var w=Object.getOwnPropertySymbols,Q=Object.prototype.hasOwnProperty,ha=Object.prototype.propertyIsEnumerable;na.exports=function(){try{if(!Object.assign)return!1;var ba=new String("abc");ba[5]="de";if("5"===Object.getOwnPropertyNames(ba)[0])return!1;var Ca={};for(ba=0;10>ba;ba++)Ca["_"+String.fromCharCode(ba)]=ba;if("0123456789"!==Object.getOwnPropertyNames(Ca).map(function(R){return Ca[R]}).join(""))return!1;var ya={};"abcdefghijklmnopqrst".split("").forEach(function(R){ya[R]= -R});return"abcdefghijklmnopqrst"!==Object.keys(Object.assign({},ya)).join("")?!1:!0}catch(R){return!1}}()?Object.assign:function(ba,Ca){if(null===ba||void 0===ba)throw new TypeError("Object.assign cannot be called with null or undefined");var ya=Object(ba);for(var R,Ha=1;Ha