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.

Play three games on the gfx backend e98a184 · on main · nandi · 11d ago
tictactoe.clj · 60 lines · 1.9 KBClojure Blame HistoryRaw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
(ns glimmer-gfx.tictactoe
  "Tic-tac-toe on the gfx backend: a 3x3 grid of buttons and one pure rule.

   The board is a vector of 9 cells, each :x, :o or nil. You are X; O replies
   with the first free square, which is dumb on purpose -- the point here is
   that a game is just another glimmer component."
  (:require [glimmer.ratom :as ra]
            [glimmer.core :as ui]
            [glimmer-gfx.core]))

(def ^:private lines
  [[0 1 2] [3 4 5] [6 7 8] [0 3 6] [1 4 7] [2 5 8] [0 4 8] [2 4 6]])

(defn winner
  "The mark occupying a whole line, or nil."
  [board]
  (some (fn [l] (let [[a b c] (map board l)] (when (and a (= a b c)) a))) lines))

(defn reply
  "O's move: the first empty square. ponytail: no minimax, add one when losing
   to this stops being funny."
  [board]
  (first (remove #(board %) (range 9))))

(defn play
  "X takes `i`, then O replies -- unless the game is already over."
  [board i]
  (if (or (board i) (winner board))
    board
    (let [b (assoc board i :x)]
      (if-let [o (and (not (winner b)) (reply b))] (assoc b o :o) b))))

(def ^:private empty-board (vec (repeat 9 nil)))
(def state (ra/atom empty-board))

(defn- status [board]
  (case (winner board)
    :x "You win"
    :o "O wins"
    (if (every? some? board) "Draw" "Your turn")))

(defn- cell [board i]
  [:button {:label (case (board i) :x "X" :o "O" " ")
            :kind (when (= :x (board i)) :primary)
            :on-click #(ra/swap! state play i)}])

(defn app []
  (let [board (ra/deref state)]
    [:page {:max-width 300}
     [:card {:spacing 8}
      [:title {:label "Tic-tac-toe"}]
      [:label {:label (status board)}]
      (into [:vbox {:spacing 6}]
            (for [row (partition 3 (range 9))]
              (into [:hbox {:spacing 6}] (for [i row] (cell board i)))))
      [:spacer {:size 4}]
      [:button {:label "new game" :on-click #(ra/reset! state empty-board)}]]]))

(defn -main [& _]
  (ui/run app :title "tic-tac-toe" :width 300 :height 340))