Clojure:迭代向量向量以找到满足特定条件的第一个向量

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(检查迭代函数,如forloopcase),但一直无法完成这项工作.

什么是迭代那些获胜集的最佳方式,目前是矢量形式,并找到具有两个特定符号和一个开头的集合?或者最好将获胜的集合存储在不同的数据结构中?

注意:我已阅读此问题的回复,但未能将其应用于我的问题.

Ale*_*yev 4

首先,我建议你在董事会位置上使用这种结构:

(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 条对角线)。代码很粗糙,几乎没有什么方法可以让它变得更加美观和可重用。我应该解释发生了什么或者代码足够清晰吗?