我正在尝试学习一些Clojure。我制作了一个非常基本的儿童游戏模型“滑道和梯子”。当玩家获得大于或等于100的分数时,游戏结束。 现在这仅适用于玩家。
以“(play player1)”开始游戏。
我被困在如何制作多人游戏,不得不使用重复和没有“foreach”声明。
我如何将其修改为多人游戏?
(defn roll []
(+ 1 (rand-int 6)))
(def chutes { 10 5, 12 3, 55 38, 77 69})
(def ladders { 12 16, 10 25, 20 55, 77 91})
(defn apply_chutes [player]
(if (contains? chutes @player)
(do (reset! player (chutes @player))
(println "down chute! " @player))))
(defn apply_ladders [player]
(if (contains? ladders @player)
(do (reset! player (ladders @player))
(println "up ladder! " @player))))
(defn move [player]
(do(swap! player + (roll))
(println "p: " @player)
(apply_chutes player)
(apply_ladders player)
player))
(if
("done")))
(defn play [player]
(move player)
(if (>= @player 100)
(println "done")
(play player)))
(def player1 (atom 0))
答案 0 :(得分:3)
好的,我不会为您提供完整的代码,但更好的是关于函数式编程的高级设计,特别是Clojure中的循环/递归。
让我们从函数式编程中一个非常重要的概念开始 - immutability 。功能程序试图避免系统状态的任何变化。程序不是更改状态,而是生成新的状态。例如,如果您有向量v1 = [1, 2, 3, 4]
并希望在其末尾插入5,则不会销毁v1
,而是会生成v2 = [1, 2, 3, 4, 5]
(v1
记忆不变)。有关函数式编程中不变性的更多详细信息,请参阅this问题。
有了这个,最好的方法是创建特殊变量state
,它将保持游戏的整体状态。
接下来要考虑的是循环。同样,在函数式编程循环中,概念几乎被递归取代。循环和递归通常是相似的 - 它们都允许您在终止之前多次重复某些代码。在大多数命令式编程语言(例如Python,Java)中,递归导致堆栈增长,但在函数式语言中,非常流行的尾递归概念。如果您不熟悉这个概念,我强烈建议您学习它。现在我只说,尾递归只能发生在尾部位置(控制流中的最后一个语句),而不会导致堆栈增长,因此可以用作循环结构。
在Clojure中,尾递归使用recur
关键字组织:
(defn play [state ...]
...
(recur new-state ...))
在这里,我们使用参数play
定义state
函数,并在最后一行使用关键字recur
递归调用它(我们也可以将其称为(play new-state ...)
,但是在这种情况下,JVM不会优化代码以进行尾递归)。 new-state
在函数体中的某处定义,并且完全符合它的含义 - 游戏的新状态。
最后,你想让你的游戏成为多人游戏,也就是说,在每次迭代后改变当前玩家。使用循环/递归,只需通过交换玩家就可以轻松实现:
(defn play [state current-player next-player]
;; do play with current-player and compute new-state
(recur new-state next-player current-player))
请注意,在重复呼叫中,玩家互换了他们的位置,因此在play
的新呼叫中,下一位玩家成为当前玩家,反之亦然。
有了这个,你应该能够将你的代码翻译成新版本。