Clojure 在一个或多个嵌套循环中从函数返回?
在一个或多个嵌套循环中,有没有方法可以立即从函数返回 下面是一些示例代码,用于说明问题:Clojure 在一个或多个嵌套循环中从函数返回?,clojure,Clojure,在一个或多个嵌套循环中,有没有方法可以立即从函数返回 下面是一些示例代码,用于说明问题: ; 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) initi
; 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))
;网格数据结构
; -------------------
(defstruct栅格:宽度:高度)
(定义创建网格[w h初始值]
(结构映射网格)
:宽度w
:高度h
:数据(参考(vec(重复(*w h)初始值‘‘‘)’)
(定义使用数据创建网格[w h gdata]
(结构映射网格)
:宽度w
:高度h
:数据(参考gdata)))
(定义获取栅格[g x y]
(let[gdata(g:数据)
idx(+x(*(g:宽度)y))]
(gdataidx)))
(定义设置网格[g x y值]
(let[数据(deref(g:数据))
idx(+x(*(g:宽度)y))]
(dosync(alter(g:data)(fn[0;](assoc data idx value ')))
(defn获取网格行[g]
(分区(g:宽度)(deref(g:数据)))
; 开始测试应用程序
; ---------------------
; 俄罗斯方块游戏场
(def当前字段(创建网格20 10 0))
; 俄罗斯方块(L形)
(def当前块{
:网格(结构贴图网格:宽度3:高度3:数据[0 1 0
0 1 0
0 1 1 ])
;运动场中拦网位置的左上角
:x(参考文献0)
:y(参考文献0)
} )
; check position valid检查当前位置是否有效
; 一个区块的位置是运动场中的一个有效位置
(defn检查位置有效[字段块]
(dotimes[x((块:网格):宽度)]
(点时间[y((块:网格):高度)]
(如果
(let[g(块:网格)
块值(获取栅格g x y)
字段-x(+x(数据块:x)))
field-y(+y(deref(block:y)))]
(如果(不是(零块值))
(如否)
(和(>=字段x 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]
(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))
;check position valid检查当前位置是否有效
; 一个区块的位置是运动场中的一个有效位置
(defn检查位置有效[字段块]
(让[停止条件(参考错误)]
(循环[x0]
(何时(和(非(解除停止条件))
(=字段x 0)
(
它使用可变引用作为停止标志,打破了编程的功能风格。但我很高兴有一个解决办法。请随意分享更好的方式
更新对于那些感兴趣的人,我已经完成了游戏的第一个版本。可以尝试一下:)在循环递归结构中,您需要进行某种检查,以确定是否需要继续循环,如果需要,则进行循环,如果不需要,则返回一个值。在while循环中,您只需使谓词等于false。Clojure中没有中断和继续,因为它在Clojure中没有意义
我认为您正在寻找
循环
,而不是dotimes
我认为您可以用一个惯用的高阶函数替换dotimes
嵌套循环,该函数遍历数据集合并返回布尔值。例如,我认为这可能会有所帮助。用loop/recur替换dotimes是正确的。现在,要去掉可变停止标志:
(loop [x 0 stop false] ...
(if stop (println "I'm all done) (...
(if (stop-condition-is-true) (recur y true) (recur (inc y) false))
(defn position-valid? [field block]
(let [g (block :grid)]
(every? true? (for [x (range 0 (inc (g :width)))
y (range 0 (inc (g :height)))
:let [block-value (get-grid g x y)
field-x (+ x @(block :x))
field-y (+ y @(block :y))]]
(and (not (zero? block-value))
(>= field-x 0)
(< field-x (field :width))
(< field-y (field :height))
(zero? (get-grid field field-x field-y)))))))
(定义位置有效?[字段块]
(让[g(块:网格)]
(每?真?(适用于[x(范围0)(包括(g:宽度)))
y(范围0(包括(g:高度)))
:let[块值(获取栅格g x y)
字段-x(+x@(块:x))
字段-y(+y@(块:y))]]
(和(非(零块值))
(>=字段x 0)
(
for
是惰性的,所以每一个?
只会一直运行到它达到第一个非真值。因为在OP的另一个问题中,我为播放网格提出了一种不同的数据结构——即向量向量向量——我很想展示如何用这种表示来解决这个问题。对于这个问题,我认为使用0
和<
(defn check-position-valid [field-grid block]
(let [grid-rect (subgrid field-grid
@(block :x)
(-> block :grid :width)
@(block :y)
(-> block :grid :height))
block-rect (-> block :grid :data)]
(and grid-rect
(not-any? pos?
(mapcat #(map (comp dec +) %1 %2)
grid-rect
block-rect)))))
(defn create-grid
([w h] (create-grid w h 0))
([w h initial-value]
(let [data (vec (map vec (repeat h (repeat w initial-value))))]
data)))
(defn print-grid [g]
(doseq [row g]
(apply println row)))
(defn subgrid
"x & y are top left coords, x+ & y+ are spans"
[g x x+ y y+]
(if (and (<= (+ x x+) (count g))
(<= (+ y y+) (count (first g))))
(vec
(map #(subvec % x (+ x x+))
(subvec g y (+ y y+))))))
(def current-block
{:grid [[0 1 0]
[0 1 0]
[0 1 1]])
:x (ref 0)
:y (ref 0)})
(defn get-grid [g x y]
(get-in g [y x]))
(defn set-grid [g x y v]
(assoc-in g [y x] v))
(defn swap-grid [g x y f & args]
(apply update-in g [y x] f args))
(defn get-grid-row [g y]
(get g y))
(defn set-grid-row [g y v]
(assoc g y (vec (repeat (count (g 0)) v))))
(defn get-grid-col [g x]
(vec (map #(% x) g)))
(defn set-grid-col [g x v]
(vec (map #(assoc-in % [x] v) g)))
user> (print-grid (set-grid-row (set-grid-col (create-grid 6 10) 1 2) 0 3))
3 3 3 3 3 3
0 2 0 0 0 0
0 2 0 0 0 0
0 2 0 0 0 0
0 2 0 0 0 0
0 2 0 0 0 0
0 2 0 0 0 0
0 2 0 0 0 0
0 2 0 0 0 0
0 2 0 0 0 0
nil