要学习Clojure,我正在做一个小小的Tic Tac Toe游戏。在相对轻松地完成游戏的第一部分之后,我一直在努力构建智能电脑播放器。
对于测试我写的是为了帮助指导这个,我想检查计算机是否选择了现场9,如果它是计算机的轮到这是董事会:
X | O | 3
4 | X | Ø
7 | 8 | 9
要开始游戏,电路板就像这样定义,作为一个带有键值对的地图,表示电路板上的位置和该空间的内容:
(def board {1 "1" 2 "2" 3 "3" 4 "4" 5 "5" 6 "6" 7 "7" 8 "8" 9 "9"})
我对如何解决这个问题有一些想法。一个是定义这样的获胜集:
(def winning-sets
[[(board 1) (board 2) (board 3)],
[(board 4) (board 5) (board 6)],
[(board 7) (board 8) (board 9)],
[(board 1) (board 4) (board 7)],
[(board 2) (board 5) (board 8)],
[(board 3) (board 6) (board 9)],
[(board 1) (board 5) (board 9)],
[(board 3) (board 5) (board 7)]])
迭代每一组:
(for [set winning-sets]
(filter #(= symbol %) set))
但这看起来并不正确......我不知道从哪里去。我试图解决的问题可以这样描述:
告诉计算机查看8个获胜套装,找到一套有两个符号和一个开放点的套装。
我对Clojure很新,所以我不确定我是否理解解决这个问题的最佳方法。我一直在查看ClojureDocs(查看迭代函数,例如for
和loop
以及case
),但还没有能够做到这一点工作
迭代那些目前以矢量形式获胜的集合的最佳方法是什么,并找到具有两个特定符号和一个开头的集合?或者最好将获胜的集合存储在不同的数据结构中?
注意:我已阅读this question的回复,但尚未将其应用于我的回复。
答案 0 :(得分:4)
首先,我建议您将此结构用于董事会职位:
(def board [[1 1 0]
[0 0 0]
[1 0 1]])
其中X是1
,O是-1
,空单元格是0
。我的示例中的Board只有X个符号(为了简化)。接下来,
(def winning-sets
'([[0 0] [0 1] [0 2]]
[[1 0] [1 1] [1 2]]
[[2 0] [2 1] [2 2]]
[[0 0] [1 0] [2 0]]
[[0 1] [1 1] [2 1]]
[[0 2] [1 2] [2 2]]
[[0 0] [1 1] [2 2]]
[[0 2] [1 1] [2 0]]))
这是“获胜”的坐标集。如果有必要,你可以计算一下,但是对于3x3这个列表真的不是那么大。在这个术语中,你的答案是
(defn check
[target combo]
(= (map #(count (filter (partial = %) combo)) [target 0]) '(2 1)))
(defn extract
[coords]
(apply vector (map (fn [[f s]] ((board f) s)) coords)))
(filter #(check 1 (extract %)) winning-sets)
如果在REPL中执行此代码,您将看到
user=> (filter #(check 1 (extract %)) winning-sets)
([[0 0] [0 1] [0 2]]
[[2 0] [2 1] [2 2]]
[[0 0] [1 0] [2 0]]
[[0 0] [1 1] [2 2]])
看起来像是正确答案(2条水平线,1条垂直线和1条对角线)。代码很粗糙,很少有方法可以使它更美观和可重用。我应该解释一下发生了什么或代码是否足够清楚?