实现一个极大极小算法的Clojure - 多递归调用条件函数递归、极小、算法、函数

2023-09-11 02:26:48 作者:甜ぃぅおか

这个问题,我的另一个问题排序合并为一个后,我想通了一些东西出来,所以我修改了这个问题。的

我试图实现我的功能概述如下。

What I'm trying to accomplish with my function is outlined below.

在遍历所有的景点。如果它是开放的,选择与当前玩家的符号的地方。 如果此举导致要赢得比赛,这是电脑玩家的回合中,添加一个键值对现场(整数)和现场(整数,1在这种情况下)的得分为的拿下斑点哈希映射。 递归和调用此相同的功能,它传递的新的拿下斑点哈希图,板,此举只是做删除,在一样的球员,而一样的象征。 如果然而,本场比赛没有取得胜利,进入下一个条件语句,检查。 在继续执行以同样的方式在未来条件语句,只是用不同的分数(一胜与计算机的又将是1,一个双赢与人的又将是-1,并列为0)。 如果没有条件语句的计算结果为真实的,反正递归(即拿下斑点哈希地图将不会在这种情况下,任何的不同)。 Iterate over all of the spots. If it's open, select the spot with the current player's symbol. If this move causes the game to be won and it's the computer player's turn, add a key-value pair of the spot (an integer) and the score of the spot (an integer, 1 in this case) to the scored-spots hash-map. Recurse and call this same function, passing it the new scored-spots hash-map, the board with the move just made removed, the same player, and the same symbol. If however, the game has not been won, proceed to the next conditional statement and check that. Proceed with the next conditional statements in the same way, just with different scores (a win with the computer's turn is 1, a win with the human's turn is -1, a tie is 0). If none of the conditional statements evaluate to true, recurse anyway (the scored-spots hash-map won't be any different in this case).

这里的code我试过了,但是这不是回来我期待的值。

Here's the code I tried, but this isn't returning the values I'm expecting.

注: 是一个哈希映射是这样的: {00,11,22} (点位置 - 点值) 符号是一个符号,如X或O 当前播放是一个关键字,如:计算机:人 拿下斑点是一个哈希映射是这样的: {}

Note: board is a hash-map like this: {0 "0", 1 "1", 2 "2"} (spot location - spot value) sym is a symbol, like "X" or "O" current-player is a keyword, like :computer or :human scored-spots is a hash-map like this: {}

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

相反,如果我通过它这块主板: {1X2X3O445566778X9O} , 我得到的哈希地图大列表返回值。

Instead, if I pass it this board: {1 "X" 2 "X" 3 "O" 4 "4" 5 "5" 6 "6" 7 "7" 8 "X" 9 "O"}, I get a return value with a large list of hash-maps.

推荐答案

我是比较新的Clojure的和FP一般。每当我想到递归,我总是尽量先想如果是地图和/或减少的机会。

I'm relatively new to Clojure and FP in general. Whenever I think about recursion, I always try to first think if it is an opportunity for map and/or reduce.

在这种情况下,你想进球的每个的位置。每个点的收集的一起是一个电路板。所以,如果我能进球各个部位,然后收集在一起,我可以完成手头的任务。在减少而言,我可以做一些集合中的一个项目(现货),然后合并值转换成单一值(板 - 在技术上只无斑点X或O为code以下)。

In this case, you're trying to score each spot. Each spot collected together is a board. So if I can score each spot and then collect them together, I can accomplish the task at hand. In reduce terms, I can do something to an item (the spot) in a collection, and then merge that value into a single value (the board - technically only the spots without "X" or "O" for the code below).

下面是我的改写:

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

编辑:

对于需要重现,你基本上想使用相互递归。对于这一点,你可以使用声明转发声明函数,然后使用蹦床(这里有一个快速教程)实际递归。

Regarding the need to recur, you're basically wanting to use mutual recursion. For that, you can use declare to forward declare functions and then use trampoline (here's a quick tutorial) for the actual recursion.