Detecting Victory: Pattern matching REPL Experimentsλ︎
A seemingly simple approach to detecting a winner is to use pattern matching. Clojure also has the concept of destructuring, extracting values from a data structure based on a pattern.
The limitation with this approach is that more patterns need to be created if the size of the board changes
For a fixed 3x3 game board there are only 8 winning combinations, we could just create a pattern for each win. The patterns are the same for :nought
and :cross
we could just compare that each value is equal
Define patterns for matching horizontal winning linesλ︎
(def column-first
[[cell-0 _ _]
[cell-1 _ _]
[cell-2 _ _]])
(def column-second
[[_ cell-0 _]
[_ cell-1 _]
[_ cell-2 _]])
(def column-third
[[_ _ cell-0]
[_ _ cell-1]
[_ _ cell-2]])
(defn check-winning-rows
[board]
(let [[[cell-0 _ _]
[cell-1 _ _]
[cell-2 _ _]]
board]
(if (= cell-0 cell-1 cell-2)
cell-0
false)))
(check-winning-rows [[:cross :cross :cross]
[:cross :cross :cross]
[:cross :cross :cross]])
;; => :cross
(check-winning-rows [[:cross :cross :nought]
[:nought :nought :cross]
[:cross :cross :nought]])
;; => false
Pattern matching diagonalsλ︎
(= [:cross :cross :cross] [:cross :cross :cross])
(def board-of-crosses [[:cross :cross :cross]
[:cross :cross :cross]
[:cross :cross :cross]])
(def board-of-stalemate [[:cross :cross :nought]
[:nought :nought :cross]
[:cross :cross :nought]])
(= [[:cross :cross :cross] [:cross :cross :cross] [:cross :cross :cross]]
[[:cross :cross :cross] [:cross :cross :cross] [:cross :cross :cross]])
;; => true
(= [[:cross :cross :cross] [:cross :cross :cross] [:cross :cross :cross]]
[[:cross :cross :cross] [:cross :cross :cross] [:cross :cross :nought]])
;; => true
Pattern matching using destructuringλ︎
Using destructuring we can just look at the values we are interested in
The let destructuring pattern pulls out the values for the diagonal line, from top left to bottom right
(let [[[cell-00 _ _][_ cell-11 _][_ _ cell-22]] board-of-crosses]
(= cell-00 cell-11 cell-22))
;; => true
(let [[[cell-00 _ _][_ cell-11 _][_ _ cell-22]] board-of-stalemate]
(println cell-00 ":" cell-11 ":" cell-22)
(= cell-00 cell-11 cell-22))
;; => false
Not sure naming these patterns with a def is that useful Not this way, as its not correct clojure (names are not defined)
Should create two functions instead