我正在学习Clojure,并试图实现一个简单的tic-tac-toe(或morpion)。但我正在努力工作,以避免任何引用/原子/代理。。。
我知道我可以在控制台应用程序中轻松地做到这一点,因为它不会是事件驱动的,这样我就可以准确地知道何时传递新的板值。我是说
- 我的板将是一个向量的向量([[:circle 0:cross][:any:circle:empty][:cross:none:none]]其中只有:circular和:cross值很重要)
- 我会有一个简单的基于文本的方法,它使用一个板并返回一个字符串
但是,每当我想实现一个图形面板时,我都想知道如何才能做到这一点。例如:
-
我正在创建一个javax.swing.JPanel的实例(请不要关心这里使用的其他方法):
(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]) ) )
- 但我似乎没有办法从Panel的mouseClicked事件中获取板的新值:除非我引入一个状态变量
那么有没有一个变通方法:
我完整项目的来源:
- Morpion核心
- Morpion图案
(由于Igrapenthin的评论,我试图改进,但我仍然失败了。)
(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))))
;; ...
))