4

在我弄清楚了一些事情之后,这个问题和我的另一个问题合二为一,所以我修改了这个问题。

下面概述了我试图用我的功能完成的事情。

  1. 遍历所有的点。如果它是开放的,请选择带有当前玩家符号的位置。
  2. 如果这一举动导致游戏获胜并且轮到计算机玩家,则将点的键值对(整数)和点的分数(整数,在本例中为 1)添加到scored-spots哈希图中。
  3. 递归并调用这个相同的函数,传递给它 scored-spots的哈希映射、刚刚移除的棋盘、相同的玩家和相同的符号。
  4. 但是,如果游戏没有获胜,请继续下一个条件语句并检查它。
  5. 以相同的方式继续下一个条件语句,只是分数不同(轮到计算机获胜为 1,轮到人类获胜为 -1,平局为 0)。
  6. 如果没有条件语句评估为真,则无论如何都要递归(scored-spots在这种情况下哈希映射不会有任何不同)。

这是我尝试过的代码,但这并没有返回我期望的值。

注意:
board是这样的散列图:({0 "0", 1 "1", 2 "2"}点位置 - 点值)
sym是一个符号,如“X”或“O”
current-player是关键字,如:computer或是:human
scored-spots这样的散列图:{}

(defn score-spots [board sym current-player scored-spots]
  (for [spot (keys board)]
    (if (some #(= % (.toString spot)) (filter #(not= "O" %) (filter #(not= "X" %) (vals board))))
      (let [board (assoc board spot sym)]
        (cond
          (and (game-won board) (= current-player :computer))
            (score-spots board sym current-player (assoc scored-spots spot 1))
          (and (game-won board) (= current-player :human))
            (score-spots board sym current-player (assoc scored-spots spot -1))
          (game-tied board)
            (score-spots board (switch-symbol sym) (switch-player current-player) (assoc scored-spots spot 0))
          :else
            (score-spots board (switch-symbol sym) (switch-player current-player) scored-spots)))
  scored-spots))))

我期望的返回值是一个散列图,每个开放点都得分。例如,{1 0, 4 1, 5 -1, 6 -1, 8 0}

相反,如果我通过这个 board:
{1 "X" 2 "X" 3 "O" 4 "4" 5 "5" 6 "6" 7 "7" 8 "X" 9 "O"}
我会得到一个带有大量list哈希映射的返回值。

4

1 回答 1

2

一般来说,我对 Clojure 和 FP 比较陌生。每当我想到递归时,我总是首先尝试考虑它是否是map和/或的机会reduce

在这种情况下,您正在尝试对每个位置进行评分。收集在一起的每个点都是一块板。因此,如果我可以对每个点进行评分,然后将它们收集在一起,我就可以完成手头的任务。就reduce术语而言,我可以对集合中的一个项目(点)做一些事情,然后将该值合并为一个值(板 - 从技术上讲,只有在下面的代码中没有“X”或“O”的点)。

这是我的重写:

(defn score-spot [scored-spot current-player board]
  (let [[spot score] scored-spot]
    (cond
      (and (game-won board) (= current-player :computer)) {spot 1}
      (and (game-won board) (= current-player :human)) {spot -1} 
      (game-tied board)  {spot 0}
      :else {spot score})))

(defn score-board [board current-player]
  (let [spots-to-score (filter #(and (not= "X" (second %))
                                     (not= "O" (second %))) board)]
    (reduce #(into %1 (score-spot %2 current-player board)) {} spots-to-score)))

这会给你的结果,例如{1 0, 4 1, 5 -1, 6 -1, 8 0}


编辑:

关于递归的需要,您基本上是想使用相互递归。为此,您可以使用declare转发声明函数,然后使用trampoline这里是一个快速教程)进行实际递归。

于 2012-11-13T18:25:53.920 回答