2014-09-22 20 views
2

我正在建造一個掃雷艇,其中的遊戲板是2D陣列。在clojure中使用2d數組的最佳做法?

爲了生成棋盤,我需要獲得一個2D數組,隨機放置一些炸彈,計算每個場的所有相鄰炸彈,然後將所有與另一個值(顯示)一起打包到應該是最終值的Map中的每個領域。

看來,要做到這一切,我需要像map,filter,nth或zip之類的函數的幫助,而不是在列表上工作,他們應該在2d數組上工作。我已經開始建立這些,但似乎是錯誤的路要走。

是否有一些很酷的抽象可以幫助我使用2d數組上的現有函數?或者是否有任何已經存在的函數來處理二維數組?

編輯:我是這樣做的方式 - 心裏對自己說,應該有更好的辦法之前 - 是這樣的:

(defn mapmap [f xxs] 
    (for [xs xxs] 
    (map f xs))) 

(defn mapmap-coords [f xxs] 
    (for [[i xs] (map-indexed list xxs)] 
    (map-indexed (fn [j x] (f j i)) xs))) 

(defn get-value [board x y] 
    (if (or (< x 0) (< y 0) (< (dec (count board)) y)) 
    false 
    (let [xs (nth board y)] 
     (if (< (dec (count xs)) x) 
     false 
     (nth xs x))))) 
+0

https://github.com/mikera/core.matrix – 2014-09-22 18:55:38

回答

1

for作品嵌套的順序數據。

user> (def game-state 
     (let [game '[[_ _ _ _] 
        [1 1 _ _] 
        [! 1 _ _] 
        [1 1 _ _]]] 
     (for [[i row] (map-indexed list game) 
       [j cell] (map-indexed list row) 
       :when (not= '_ cell)] 
       {:x i :y j :value cell}))) 
#'user/game-state 
user> (pprint game-state) 
({:x 1, :y 0, :value 1} 
{:x 1, :y 1, :value 1} 
{:x 2, :y 0, :value !} 
{:x 2, :y 1, :value 1} 
{:x 3, :y 0, :value 1} 
{:x 3, :y 1, :value 1}) 
nil 

我們可以使用reduce重新構建的數據結構(當然對國家的任何轉換可能已經在做之間)。

user> (let [empty-game (vec (repeat 4 '[_ _ _ _])) 
      fill-cell (fn [game, {:keys [x y value]}] (assoc-in game [x y] value)) 
      game (reduce fill-cell empty-game game-state)] 
     (doseq [row game] (apply println row))) 
_ _ _ _ 
1 1 _ _ 
! 1 _ _ 
1 1 _ _ 
nil 
+0

謝謝。我明白'for'可以用來解開我的電路板並做些什麼,但是我怎樣才能把它包裝起來(放入另一個電路板)? – sra 2014-09-22 19:12:12

+0

已更新,以顯示電路板數據的重構 – noisesmith 2014-09-22 19:24:34

+0

這是使用2d陣列的「慣用」方式嗎?這似乎有點複雜。到目前爲止,我有像'(defn mapmap [f xxs](for [xs xxs](map f xs)))''這樣可以更容易地實現類似的事情。使用二維數組甚至是一件騙局的事情嗎? – sra 2014-09-23 09:58:44