nandi/jolt-nativepublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/nandi/jolt-native.git
git clone ssh://git@rickub.com/nandi/jolt-native.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

tictactoe.clj · 60 lines · 1.9 KBClojure Blame HistoryRaw
Play three games on the gfx backend e98a184 nandi 11d ago1(ns glimmer-gfx.tictactoe
2 "Tic-tac-toe on the gfx backend: a 3x3 grid of buttons and one pure rule.
3
4 The board is a vector of 9 cells, each :x, :o or nil. You are X; O replies
5 with the first free square, which is dumb on purpose -- the point here is
6 that a game is just another glimmer component."
7 (:require [glimmer.ratom :as ra]
8 [glimmer.core :as ui]
9 [glimmer-gfx.core]))
10
11(def ^:private lines
12 [[0 1 2] [3 4 5] [6 7 8] [0 3 6] [1 4 7] [2 5 8] [0 4 8] [2 4 6]])
13
14(defn winner
15 "The mark occupying a whole line, or nil."
16 [board]
17 (some (fn [l] (let [[a b c] (map board l)] (when (and a (= a b c)) a))) lines))
18
19(defn reply
20 "O's move: the first empty square. ponytail: no minimax, add one when losing
21 to this stops being funny."
22 [board]
23 (first (remove #(board %) (range 9))))
24
25(defn play
26 "X takes `i`, then O replies -- unless the game is already over."
27 [board i]
28 (if (or (board i) (winner board))
29 board
30 (let [b (assoc board i :x)]
31 (if-let [o (and (not (winner b)) (reply b))] (assoc b o :o) b))))
32
33(def ^:private empty-board (vec (repeat 9 nil)))
34(def state (ra/atom empty-board))
35
36(defn- status [board]
37 (case (winner board)
38 :x "You win"
39 :o "O wins"
40 (if (every? some? board) "Draw" "Your turn")))
41
42(defn- cell [board i]
43 [:button {:label (case (board i) :x "X" :o "O" " ")
44 :kind (when (= :x (board i)) :primary)
45 :on-click #(ra/swap! state play i)}])
46
47(defn app []
48 (let [board (ra/deref state)]
49 [:page {:max-width 300}
50 [:card {:spacing 8}
51 [:title {:label "Tic-tac-toe"}]
52 [:label {:label (status board)}]
53 (into [:vbox {:spacing 6}]
54 (for [row (partition 3 (range 9))]
55 (into [:hbox {:spacing 6}] (for [i row] (cell board i)))))
56 [:spacer {:size 4}]
57 [:button {:label "new game" :on-click #(ra/reset! state empty-board)}]]]))
58
59(defn -main [& _]
60 (ui/run app :title "tic-tac-toe" :width 300 :height 340))