5

私は学習演習として 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]

私は map-indexed でもっと簡潔なことを試みましたが、すぐに醜くなり、それでも私が望んでいたものはまったく得られませんでした. この検索を行うためのより慣用的な方法はありますか、それとも別のデータ構造を使用したほうがよいでしょうか? マップ { [xy] -> cell } でしょうか。マップを使用してマトリックスを表すのは、私にはとても間違っているように感じます:)

4

2 に答える 2

4

forネストされたベクトルは、この種のものではごく普通のことであり、理解力を使用する場合、1つをスキャンするのは難しくも醜いことでもありません。

(let [h 5, w 10]
  (first
   (for [y (range h), x (range w)
         :let [coords [y x]]
         :when (f (get-in board coords))]
     coords)))
于 2012-04-18T00:11:06.100 に答える
2

単純なベクトルを使用すると、すべての「通常の」関数が利用可能になり、必要に応じて [xy] を抽出できます。

(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]
于 2012-04-17T23:38:35.033 に答える