有一種方法可以在一個或多個嵌套循環中立即從函數返回嗎?在一個或多個嵌套循環中從函數返回?
下面是說明問題的一些示例代碼:
; Grid data structure
; -------------------
(defstruct grid :width :height)
(defn create-grid [w h initial-value]
(struct-map grid
:width w
:height h
:data (ref (vec (repeat (* w h) initial-value)))))
(defn create-grid-with-data [w h gdata]
(struct-map grid
:width w
:height h
:data (ref gdata)))
(defn get-grid [g x y]
(let [gdata (g :data)
idx (+ x (* (g :width) y)) ]
(gdata idx)))
(defn set-grid [g x y value]
(let [data (deref (g :data))
idx (+ x (* (g :width) y)) ]
(dosync (alter (g :data) (fn [_] (assoc data idx value))))))
(defn get-grid-rows [g]
(partition (g :width) (deref (g :data))))
; Beginning of test app
; ---------------------
; The Tetris playing field
(def current-field (create-grid 20 10 0))
; A tetris block (the L-Shape)
(def current-block {
:grid (struct-map grid :width 3 :height 3 :data [ 0 1 0
0 1 0
0 1 1 ])
; upper-left corner of the block position in the playing field
:x (ref 0)
:y (ref 0)
})
; check-position-valid checks if the current position
; of a block is a valid position in a playing field
(defn check-position-valid [field block]
(dotimes [ x ((block :grid) :width) ]
(dotimes [ y ((block :grid) :height) ]
(if
(let [ g (block :grid)
block-value (get-grid g x y)
field-x (+ x (deref (block :x)))
field-y (+ y (deref (block :y))) ]
(if (not (zero? block-value))
(if-not
(and (>= field-x 0)
(< field-x (field :width))
(< field-y (field :height))
(zero? (get-grid field field-x field-y)))
false ; invalid position, function should now return false
true ; ok, continue loop
)))
true
false))))
(println (check-position-valid current-field current-block))
也許我接近問題的必要方式太多了。
更新
好吧,我發現了一個解決方案:
; check-position-valid checks if the current position
; of a block is a valid position in a playing field
(defn check-position-valid [field block]
(let [stop-condition (ref false)]
(loop [ x 0 ]
(when (and (not (deref stop-condition))
(< x ((block :grid) :width)))
(println "x" x)
(loop [ y 0 ]
(when (and (not (deref stop-condition))
(< y ((block :grid) :height)))
(println "y" y)
(let [ g (block :grid)
block-value (get-grid g x y)
field-x (+ x (deref (block :x)))
field-y (+ y (deref (block :y))) ]
(if (not (zero? block-value))
(if-not
(and (>= field-x 0)
(< field-x (field :width))
(< field-y (field :height))
(zero? (get-grid field field-x field-y)))
(do
(println "stop is true")
(dosync (alter stop-condition (fn [_] true)))))))
(recur (inc y))))
(recur (inc x))))
(not (deref stop-condition))))
(println (check-position-valid current-field current-block))
它使用可變引用作爲停止標誌,打破了編程功能的風格。但我很高興有一個解決方案。隨意分享更好的方式。
更新
對於那些有興趣,我已經完成了我的Clojure Tetris遊戲的第一個版本的版本。隨意試試吧:)
通過嵌套循環,你的意思是遞歸結構(實際遞歸或循環重複結構)?或者你的意思是像「for」這樣的序列處理器? – Greg 2010-05-14 03:06:39
@Greg哈曼:我用代碼示例更新了我的帖子。 – StackedCrooked 2010-05-14 04:22:36
只是一個提示:如果這裏沒有性能瓶頸,你應該在這段代碼中引入抽象(即在適當的地方使用fns和宏來分離出各個部分)。該代碼看起來相當複雜,因此更難以維護。 – jjpe 2013-10-04 10:19:12