rzv*_*rzv 5 iteration vector clojure tic-tac-toe
为了学习Clojure,我正在做一个小小的Tic Tac Toe游戏.在相对轻松地完成游戏的第一部分之后,我一直在努力构建智能电脑播放器.
对于我正在编写的测试来帮助指导这个,我想检查计算机是否选择了现货9,如果它是计算机轮到这个板子:
X | O | 3
4 | X | O
7 | 8 | 9
要开始游戏,电路板就像这样定义,作为一个带有键值对的地图,表示电路板上的位置和该空间的内容:
(def board {1 "1" 2 "2" 3 "3" 4 "4" 5 "5" 6 "6" 7 "7" 8 "8" 9 "9"})
Run Code Online (Sandbox Code Playgroud)
我对如何解决这个问题有一些想法.一个是定义这样的获胜集:
(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)]])
Run Code Online (Sandbox Code Playgroud)
迭代每一组:
(for [set winning-sets]
(filter #(= symbol %) set))
Run Code Online (Sandbox Code Playgroud)
但这似乎并不正确......我不知道从哪里开始.我试图解决的问题可以这样描述:
告诉计算机查看8个获胜组,找到一组有两个符号和一个开放点.
我对Clojure很新,所以我不确定我是否理解解决这个问题的最佳方法.我一直在看ClojureDocs(检查迭代函数,如for
和loop
和case
),但一直无法完成这项工作.
什么是迭代那些获胜集的最佳方式,目前是矢量形式,并找到具有两个特定符号和一个开头的集合?或者最好将获胜的集合存储在不同的数据结构中?
注意:我已阅读此问题的回复,但未能将其应用于我的问题.
首先,我建议你在董事会位置上使用这种结构:
(def board [[1 1 0]
[0 0 0]
[1 0 1]])
Run Code Online (Sandbox Code Playgroud)
其中 X 是1
,O 是-1
,空单元格是0
。在我的示例中,主板只有 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]]))
Run Code Online (Sandbox Code Playgroud)
这是“获胜”的坐标集。如果需要的话你可以计算这个,但是对于 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)
Run Code Online (Sandbox Code Playgroud)
如果你在 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]])
Run Code Online (Sandbox Code Playgroud)
这看起来像正确答案(2 条水平线,1 条垂直线和 1 条对角线)。代码很粗糙,几乎没有什么方法可以让它变得更加美观和可重用。我应该解释发生了什么或者代码足够清晰吗?