zca*_*ate 3 clojure clojurescript
我在这里玩一个狡猾的教程:
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;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我知道我们可以拥有(for [])构造但是当max_villages达到5时你会如何让它停下来?
这是一种方法:
(def max-villages 5)
(->> (for [x (range map-width)
y (range map-height)]
[x y])
(filter (fn [_] (< (rand) 0.02)))
(take max-villages))
Run Code Online (Sandbox Code Playgroud)
然后可能添加(map make-village-at)或类似管道的下一个阶段; 如果它意味着执行副作用,添加一个dorun或doall作为最后阶段强制它们立即发生(根据返回值是否有趣选择一个或另一个).
NB.由于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
Run Code Online (Sandbox Code Playgroud)
:while当测试表达式失败时,在当前嵌套级别终止循环; :when立即进入下一次迭代.doseq也支持分块,但:while会阻止它执行不必要的工作.