Có cách nào để trả về ngay lập tức từ một hàm khi ở một hoặc nhiều vòng lồng nhau không?Trả về từ một hàm trong khi bên trong một hoặc nhiều vòng lồng nhau?
Dưới đây là một số mẫu mã minh họa vấn đề:
; 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))
Có lẽ tôi đang tiếp cận vấn đề quá nhiều một cách bắt buộc.
Cập nhật
Ok, tôi tìm thấy một giải pháp:
; 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))
Nó sử dụng một tài liệu tham khảo có thể thay đổi như một lá cờ dừng, phá vỡ phong cách chức năng của chương trình. Nhưng tôi rất vui khi có một giải pháp. Hãy chia sẻ một cách tốt hơn.
Cập nhật
Đối với những người quan tâm, tôi đã hoàn thành một phiên bản phiên bản đầu tiên của Clojure Tetris trò chơi của tôi. Hãy thử một lần thử :)
Bằng vòng lặp lồng nhau, bạn có nghĩa là cấu trúc đệ quy (đệ quy thực sự hoặc cấu trúc lặp lại)? Hoặc bạn có nghĩa là một bộ xử lý chuỗi như "cho"? – Greg
@Greg Harman: Tôi đã cập nhật bài đăng của mình bằng mẫu mã. – StackedCrooked
Chỉ cần một mẹo: bạn nên giới thiệu trừu tượng trong mã này (ví dụ: tách các phần bằng cách sử dụng fns và macro nếu thích hợp) nếu không có nút cổ chai hiệu suất tại đây. Mã có vẻ khá phức tạp và do đó khó bảo trì hơn. – jjpe