3

我在这里玩一个狡猾的教程:

http://buildnewgames.com/introduction-to-crafty/

并且想知道如何在 clojurescript/clojure 中实现这个特定的功能

 var max_villages = 5;
 for (var x = 0; x < Game.map_grid.width; x++) {
   for (var y = 0; y < Game.map_grid.height; y++) {
     if (Math.random() < 0.02) {
       Crafty.e('Village').at(x, y);

       if (Crafty('Village').length >= max_villages) {
        return;
       }
    }
  }
}

我知道我们可以拥有这个(for [])构造,但是当 max_villages 达到 5 时,你如何让它停止呢?

4

3 回答 3

5

这是一种方法:

(def max-villages 5)

(->> (for [x (range map-width)
           y (range map-height)]
       [x y])
     (filter (fn [_] (< (rand) 0.02)))
     (take max-villages))

然后可能添加(map make-village-at)或类似于管道的下一阶段;如果它打算执行副作用,添加一个dorunordoall作为最后阶段以强制它们立即发生(根据返回值是否有趣选择一个或另一个)。

注意。由于 seq 分块,可能会生成一些额外的向量和随机数,但它会小于 32。

一种更重要的方法,带有用于比较的计数器:

(let [counter (atom 0)]
  (doseq [x (range map-width)
          :while (< @counter max-villages)
          y (range map-height)
          :while (< @counter max-villages)
          :when (< (rand) 0.02)]
    (swap! counter inc)
    (prn [x y]))) ; call make-village-at here

:while当其测试表达式失败时,在当前嵌套级别终止循环;:when立即进入下一个迭代。doseq也支持分块,但:while会阻止它执行不必要的工作。

于 2013-05-17T00:02:08.640 回答
2

使用递归它会是这样的:

(letfn [(op [x y]
          (if (= (rand) 0.02)
            (do
              (village-at x y)
              (if (>= (village-length) max-villages) true))))]
  (loop [x 0 y 0]
    (when (and (< x width) (not (op x y)))
      (if (= (inc y) height)
        (recur (inc x) 0)
        (recur x (inc y))))))
于 2013-05-17T05:04:17.030 回答
0

这是一个很棒的教程!

Michael 方法的一个变体(我只是对他的回答发表了评论,但我还没有足够的堆栈能力)是使用笛卡尔积而不是嵌套的 for 循环:

;; some stub stuff to get the example to run
(ns example.core
  (:use clojure.math.combinatorics))

(def max-villages 5)
(def map-width 10)
(def map-height 10)
(defn crafty-e [x y z] (print z))

;; the example, note I use doseq rather than map to empasize the fact that the loop 
;; is being performed for its side effects not its return value.
(doseq [coord (take max-villages 
                (filter 
                 (fn [_] (< (rand)  0.02))
                 (cartesian-product (range map-width) (range map-height))))]
(crafty-e :village :at coord))
于 2014-03-17T06:43:48.307 回答