实现一个极大极小算法的Clojure - 多递归调用条件函数 [英] Implementing a Minimax Algorithm in Clojure - conditional function with multiple recursive calls
问题描述
这个问题,我的另一个问题排序合并为一个后,我想通了一些东西出来,所以我修改了这个问题。的
我试图实现我的功能概述如下。
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}
编辑:
对于需要重现,你基本上想使用相互递归。对于这一点,你可以使用声明转发声明函数,然后使用蹦床(<一HREF =http://jakemccrary.com/blog/2010/12/06/trampolining-through-mutual-recursion/相对=nofollow>这里有一个快速教程)实际递归。
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.
这篇关于实现一个极大极小算法的Clojure - 多递归调用条件函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!