免责声明:这是我的第一个clojure函数&我仍在忙着完成“编程Clojure”的最后几章。谢谢!:)
我正在编写一个函数来随机填充游戏地图中的部分(也就是说,这不是一个可以递归填充所有可用空间的传统洪水填充)。这个想法是创建一个随机形状的岛屿,在这个岛内创建一个随机形状的山。(也就是说,将一组岛屿点作为过滤器传递到下一个洪水填充函数,这样,该山将只在岛上的瓷砖中创建)。
这就是我的代码目前产生的结果(您会注意到PragProg的编程Clojure中从蛇游戏中窃取的窗口/绘图代码)。(;)

这是我的密码:
(def dirs2 '([-1 0] [1 0] [0 -1] [0 1]))
(defn neighbours [pt]
(for [dir dirs2]
(vec (map + pt dir))))
(defn flood-fill2
"start -> point to start filling from
n -> number of tiles to create
filter-fn -> a fn that must return true for new points"
([start n]
(flood-fill2 start n (fn [& _] true)))
([start n filter-fn]
(loop [result #{}
candidates #{start}
i n]
(if (or (zero? i) (empty? candidates))
result
(let [current (rand-nth (seq candidates))]
(if (and (filter-fn current) (not (result current)))
(recur
(conj result current)
(apply conj (disj candidates current) (neighbours current))
(dec i))
(recur result (disj candidates current) i)))))))(take 600 (lazy-fill [25 25] optional-src-set))看起来比(flood-fill2 [25 25] 600 island)酷多了。#() )返回任何参数(S)的true,但最终不得不放弃,使用fn:(fn [& _] true)编写它。我能用#()吗?我的初始(天真)实现如下所示:
(defn flood-fill [filled n]
(if (zero? n)
filled
(let [start-point (rand-nth filled)
next-point (rand-nth (neighbours start-point))]
(if (contains? (set filled) next-point)
(recur filled n)
(recur (cons next-point filled) (dec n))))))但是:
user=> (time (flood-fill [[25 25]] 1250))
(time (flood-fill [[25 25]] 1250))
"Elapsed time: 8430.56 msecs"
([8 18] [43 40] [23 9] [38 40] ...我的flood-fill2做得更好:
user=> (time (flood-fill2 [25 25] 1250))
(time (flood-fill2 [25 25] 1250))
"Elapsed time: 257.361 msecs"
#{[34 33] [35 34] [36 3] [36 35] [38 5] [10 9] ...但是使用(time (flood-fill2 [500 500] 500000))来填充1000 *1000个瓷砖地图的50%要花费很长时间(@ 100% CPU)。最后我杀了那个REPL。
有什么表演建议吗?我试图避免从集合到向量/列表的许多转换,但是rand-nth需要一个序列,我找不到一个很好的“随机集元素”函数。
谢谢你看了这么多。
发布于 2013-03-16 06:21:43
我自己也是clojure的一名熟练工人,我不知道你所有的问题都有答案,但我有一些意见。
我不确定我完全理解你的算法,但是看起来你真的有两个循环。你有一个内环,寻找下一个可以绘制的瓷砖(不包括i),而外部循环实际上是填充像素,从n开始计数i。如果你以某种方式将这两者分开,可能会更清楚。
因为你随机选择候选人,所以填充n块所需的时间是随机的。
我发现当我这样做的时候:
(loop [result ()
input input-seq]
(let [item (computation input)]
(recur (conj result item) (rest input)))它通常可以改写为:
(reduce computation input-seq)(但我无法立即看出这是否适用于您的功能)
您考虑过使用一个2d的tiles数组而不是一个坐标列表来实现这一点吗?
其他几个问题:
https://codereview.stackexchange.com/questions/20028
复制相似问题