我正在Clojure的一个小游戏中进行学习练习。我想我已经决定在任何特定时间将游戏状态表示为“可移动物”列表和“地形”(板块正方形)的2D矢量矢量。
95%的时间我希望检查2D矢量看起来合适的特定方块中的碰撞。但在少数情况下,我需要转向另一个方向 - 找到符合某些条件的单元格的(x,y)位置。第一次尝试是这样的:
(defn find-cell-row [fn row x y]
(if (empty? row) nil
(if (fn (first row)) [x y]
(find-cell-row fn (rest row) (inc x) y))))
(defn find-cell [fn grid y]
(if (empty? grid) nil
(or (find-cell-row fn (first grid) 0 y)
(find-cell (rest grid) (inc y)))))
(def sample [[\a \b \c][\d \e \f]])
(find-cell #(= % \c) sample 0) ;; => [2 0]
我尝试了一些更简洁的地图索引,但它很快就变丑了,但仍然没有给我我想要的东西。是否有更惯用的方式来进行此搜索,或者我可能会更好地使用不同的数据结构?也许是地图{[x y] - >细胞 }?使用地图来表示矩阵对我来说是错误的:))
答案 0 :(得分:4)
对于这类事情,嵌套向量是很正常的,如果你使用for
理解,扫描一个并不难,也不难看:
(let [h 5, w 10]
(first
(for [y (range h), x (range w)
:let [coords [y x]]
:when (f (get-in board coords))]
coords)))
答案 1 :(得分:2)
如何使用普通矢量,那么所有“常用”功能都可供您使用,您可以根据需要提取[x y]。
(def height 3)
(def width 3)
(def s [\a \b \c \d \e \f \g \h \i])
(defn ->xy [i]
[(mod i height) (int (/ i height))])
(defn find-cell
"returns a vector of the [x y] co-ords of cell when
pred is true"
[pred s]
(let [i (first (keep-indexed #(when (pred %2) %1) s))]
(->xy i)))
(find-cell #(= \h %) s)
;=> [1 2]
(defn update-cells
"returns an updated sequence s where value at index i
is replaced with v. Allows multiple [i v] pairs"
[s i v & ivs]
(apply assoc s i v ivs))
(update-cells s 1 \z)
;=> [\a \z \c \d \e \f \g \h \i]
(update-cells s 1 \p 3 \w)
;=> [\a \p \c \w \e \f \g \h \i]