在Clojure中实现Minimax算法 – 具有多个递归调用的条件函数

在我想出一些事情之后,这个问题和我的另一个问题合并为一个,所以我修改了这个问题.

我想用我的功能完成的工作概述如下.

>迭代所有的点.如果它已打开,请选择当前玩家符号的位置.
>如果此移动导致游戏获胜并且是计算机玩家的回合,则将点的一对键值对(整数)和点的得分(在这种情况下为整数,1)添加到得分点哈希地图.
>递归并调用相同的函数,将新的得分点哈希映射,移动的板移除,同一个播放器和相同的符号传递给它.
>但是,如果游戏尚未获胜,请继续执行下一个条件语句并进行检查.
>以相同的方式继续下一个条件陈述,只有不同的分数(计算机轮到1的胜利,人的回合胜利为-1,平局为0).
>如果条件语句都没有计算为true,那么无论如何都要递归(在这种情况下,得分点哈希映射不会有任何不同).

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

注意:
board是这样的哈希映射:{0“0”,1“1”,2“2”}(现货位置 – 现货价值)
sym是一个符号,如“X”或“O”
current-player是一个关键字,如:computer或:human
得分点是这样的哈希映射:{}

(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}.

相反,如果我通过它这个板:
{1“X”2“X”3“O”4“4”5“5”6“6”7“7”8“X”9“O”},
我得到一个带有大量哈希映射的返回值.

最佳答案 我对Clojure和FP相对较新.每当我考虑递归时,我总是首先想到它是否是映射和/或减少的机会.

在这种情况下,您正在尝试为每个位置打分.收集在一起的每个点都是一块板.因此,如果我能够得到每个位置然后将它们收集起来,我就可以完成手头的任务.在缩减方面,我可以对集合中的某个项目(点)执行某些操作,然后将该值合并为单个值(该板 – 从技术上讲,只有下面代码中没有“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(here’s a quick tutorial)进行实际递归.

点赞