I am learning Clojure and trying to implement a simple tic-tac-toe (or morpion). But i am working hard in order to avoid any ref/atom/agent ...
I know I could do it easily in a console application, as it would not be event-driven, so that I would exactly know when to pass in a new board value. I mean
But, whenever I want to implement a graphical Panel, I wonder how can I do the same thing. For example :
I am creating an instance of javax.swing.JPanel (please don't care about the other methods that are used here) :
(defn make-board-panel
"Builds the board JPanel, whose state is given by board argument,
and turn-piece argument (must be either :circle or :cross, I mean the next
value to set in the board)."
[board turn-piece]
{:pre ['morpion.core/is-board? board, 'morpion.core/is-a-player-piece? turn-piece]}
(proxy [JPanel MouseListener] []
(paintComponent [g]
(proxy-super paintComponent g)
(paint-board-lines g)
(paint-board board g)
)
(mouseClicked [e]
(if (and (abs-coord-in-cell? (.getX e)) (abs-coord-in-cell? (.getY e)))
(let [cell-x (abs-coord-to-rel (.getX e))
cell-y (abs-coord-to-rel (.getY e))]
;; Here I compute the new board value
)
nil ;; Here I wish I could return the new board value to the caller of make-board-panel, but this seems impossible !
)
)
(mouseEntered [e])
(mouseExited [e])
(mousePressed [e])
(mouseReleased [e])
)
)
So is there a workaround :
Sources for my complete project :
(I've tried to improve thanks to Igrapenthin comment, but I am still failing.)
(defn make-board-panel
[board turn-piece output-fn]
(proxy [JPanel MouseListener] []
;; ...
(mouseClicked [e]
(when (and (abs-coord-in-cell? (.getX e))
(abs-coord-in-cell? (.getY e)))
(let [cell-x (abs-coord-to-rel (.getX e))
cell-y (abs-coord-to-rel (.getY e))]
;; Here I compute the new board value
(output-fn new-board-value))))
;; ...
))