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

1 つのアプローチを次に示します。

(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 に答える