gpt4 book ai didi

clojure - 在一个或多个嵌套循环内从函数返回?

转载 作者:行者123 更新时间:2023-12-02 23:13:33 25 4
gpt4 key购买 nike

有没有一种方法可以在一个或多个嵌套循环中立即从函数返回?

下面是一些说明问题的示例代码:

; 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 的第一个版本。游戏。欢迎尝试一下:)

最佳答案

未经测试:

(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)))))))

for 是惰性的,因此 every? 只会到达第一个非真值。

关于clojure - 在一个或多个嵌套循环内从函数返回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2831571/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com