【问题标题】:Trying to build a tic tac toe without any state (in pure fp style)尝试在没有任何状态的情况下构建井字游戏(纯 fp 风格)
【发布时间】:2013-08-27 14:06:43
【问题描述】:

我正在学习 Clojure 并尝试实现一个简单的井字游戏(或 morpion)。但我正在努力避免任何 ref/atom/agent ...

我知道我可以在控制台应用程序中轻松做到这一点,因为它不是事件驱动的,所以我可以准确地知道何时传递一个新的板值。我是说

  • 我的板将是一个向量向量([[:circle 0 :cross][:any :circle :empty][:cross :none :none]] 其中只有 :circle 和 :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 事件中获取板的新值:除非我引入状态变量。

那么有没有解决方法:

我的完整项目的来源:

(感谢 Igrapenthin 的评论,我试图改进,但我仍然失败了。)

【问题讨论】:

  • 您可以将回调函数作为附加参数传递,该参数将从 MouseListener 内部使用新的板值调用。
  • 感谢您的想法:我正在尝试。我没想过这种方式(Clojure初学者:))
  • 您确定您使用的前提条件正确吗?看起来它现在所做的只是检查提供的值是否非零,但您实际上想检查 board 是一块板,turn-piece 是一块。
  • 为什么?我忘了括号或类似的东西吗?
  • 除非你想在每一回合后用一个新的面板替换你的面板,否则你无法避免状态。

标签: swing user-interface clojure stateless


【解决方案1】:
(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))))
    ;; ...
    ))

【讨论】:

  • 是的,我写过类似的东西,但我的代码中仍然遇到一个奇怪的 ArityException(它没有指出问题所在,但它只是在 : Symbol 中显示 ArityException)跨度>
  • 您的错误肯定是由于 morpion.core/play-board 之前的引号 (')
  • 谢谢,我引用了'morpion.core/play-board,因为我认为我可以通过这种方式解决命名空间问题。但它没有。所以我必须尝试使用​​ require/use。
  • 如果问题是递归 require 之一(两个命名空间都需要另一个),要么做一个两者都需要的第三个,或者使用 resolve 在运行时查找命名空间和函数。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-18
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多