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
- my board would be a vector of vectors ([[:circle 0 :cross][:any :circle :empty][:cross :none :none]] where only :circle and :cross values matter)
- I would have a simple text-based method which takes a board and return a string
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]) ) )
- But it seems that there are no way for me to fetch the new value of the board, from the mouseClicked event of the Panel : unless I introduce a state variable.
So is there a workaround :
Sources for my complete project :
(I've tried to improve thanks to Igrapenthin comment, but I am still failing.)