/
core.cljs
108 lines (99 loc) · 3.61 KB
/
core.cljs
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
(ns react-tutorial.core
(:require
[reagent.core :as r]))
;; -------------------------
;; Views
(defn calculate-winner [squares]
(let [lines (vec [[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
[0, 3, 6]
[1, 4, 7]
[2, 5, 8]
[0, 4, 8]
[2, 4, 6]])]
(reduce (fn [_ [a b c]]
(if (and (not= (squares a) "")
(= (squares a) (squares b))
(= (squares b) (squares c)))
(reduced (squares a))
nil))
nil
lines)))
(defn square [{:keys [on-click value]}]
[:button.square
{:on-click #(on-click)}
value])
(defn board [& {:keys [squares on-click]}]
(letfn
[(render-square [i]
[square {
:value (squares i)
:on-click #(on-click i)
}])]
[:div
[:div.board-row
(render-square 0)
(render-square 1)
(render-square 2)]
[:div.board-row
(render-square 3)
(render-square 4)
(render-square 5)]
[:div.board-row
(render-square 6)
(render-square 7)
(render-square 8)]]))
(defn game []
(let [state (r/atom {:history (vec [{:squares (vec (repeat 9 ""))}])
:step-number 0
:x-is-next? true})]
(fn []
(letfn
[(handle-click [i]
(let [history (vec (take (inc (get @state :step-number)) (get @state :history)))
current (last history)
squares (get current :squares)
x-is-next? (get @state :x-is-next?)]
(js/console.log (pr-str (get @state :x-is-next?)))
(when (and (= (calculate-winner squares) nil) (= (squares i) ""))
(swap! state
assoc :history
(conj history
(assoc-in current [:squares i] (if x-is-next? "X" "O"))))
(swap! state assoc :step-number (count history))
(swap! state assoc :x-is-next? (not x-is-next?)))))
(jump-to [step]
(swap! state assoc :step-number step)
(swap! state assoc :x-is-next? (if (= (mod step 2) 0) true false)))]
(let [history (get @state :history)
current (get history (get @state :step-number))
squares (get current :squares)
winner (calculate-winner squares)
moves (map-indexed (fn [move _]
(let [desc (if (= move 0)
(str "Go to game start")
(str "Go to move #" move))]
[:li {:key move} [:button {:on-click #(jump-to move)} desc]]))
history)
status (if (= winner nil)
(str "Next player: " (if (get @state :x-is-next?) "X" "O"))
(str "Winner: " winner))]
[:div.game
[:div.game-board
[board :squares squares
:on-click handle-click]
]
[:div.game-info
[:div status]
[:ol
moves
]]])))))
(defn home-page []
[game])
;; -------------------------
;; Initialize app
(defn mount-root []
(r/render [home-page] (.getElementById js/document "app")))
(defn init! []
(mount-root))