How to implement multithreading
游戏规则
考虑一个简单的2人游戏,其玩法如下:连续排列偶数个硬币。轮流,每位玩家从该行两端的硬币中取出硬币。当所有硬币都被取走时,目标是使硬币中的价值最高。
玩家一发现所有偶数硬币和所有奇数硬币的总和。如果奇数硬币的总和更高,则玩家1拿走最左边的硬币;否则,玩家1拿走最左边的硬币。否则,他将获得最右边的权利。
玩家二有一个选择,可以选择奇数个硬币。因此,他尝试从两端拿硬币,以查看哪个选项会使玩家1的状况更糟。
问题
我基本上想对该程序实施多头处理。我对Clojure还是很陌生,而且我在网上真的找不到关于多线程的任何适用于我的程序的好材料。
编码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | (ns game.core (:gen-class)) (defn vector-from-string [s] (drop 1 (map read-string (clojure.string/split (clojure.string/trim-newline s) #"")))) (defn string-from-file [f] (slurp f)) (defn sum-of-evens [v] (def evens (vector)) (loop [v v, index 1] (when (seq v) (if (even? index) (def evens (conj evens (first v)))) (recur (rest v) (inc index)))) (reduce + evens)) (defn sum-of-odds [v] (def odds (vector)) (loop [v v, index 1] (when (seq v) (if (odd? index) (def odds (conj odds (first v)))) (recur (rest v) (inc index)))) (reduce + odds)) (defn player-two [v p1score p2score] (if (not (empty? v)) (if (> (max (sum-of-odds (drop 1 v)) (sum-of-evens (drop 1 v))) (max (sum-of-odds (drop-last v)) (sum-of-evens (drop-last v)))) (player-one (drop-last v) p1score (+ p2score(last v))) (player-one (drop 1 v) p1score (+ p2score (first v)))) (println"p1score" p1score"p2score" p2score))) (defn player-one [v p1score p2score] (if (not (empty? v)) (if (> (sum-of-odds v) (sum-of-evens v)) (player-two (drop 1 v) (+ p1score (first v)) p2score) (player-two (drop-last v) (+ p1score (last v)) p2score)) (println"p1score" p1score"p2score" p2score))) (defn -main [& args] (let [v (vector-from-string (string-from-file"numbers.txt")) ] (player-one v 0 0))) |
因此,
您的代码目前非常简单。
希望能帮助您朝正确方向发展的几点评论:
您的循环不必要地复杂。您想对偶数或奇数索引的元素求和?组合使用
1 2 3 4 | (take-nth 2 [1 2 3]) ;=> (1 3) (take-nth 2 (rest [1 2 3 4])) ;=> (2 4) |
整个过程看起来像是一次又一次地编译它,然后使用它运行JVM。我对吗?首选方式是在REPL工作。如何访问它,取决于您使用的编辑环境。有很多初学者友好的REPL。大猩猩REPL就是一个例子。
一旦使代码和开发工作流状态变得更好,您可能希望探索
希望对您有所帮助,即使这不是您问题的直接答案。
首先,让我们看一下示例中的一些问题,这些问题在并行化此代码之前需要解决。
1 2 3 4 5 6 7 8 9 10 11 | (defn sum-of-evens [v] (loop [v v index 1 evens []] (if (seq v) (recur (rest v) (inc index) (if (even? index) ;; add a binding to loop, not a def (conj evens (first v)) evens)) ;; pass unchanged value when necessary (reduce + evens)))) |
但是我们可以使用
1 2 3 4 5 | (defn sum-of-evens [coll] (->> coll (keep-indexed (fn [i v] (when (even? (inc i)) v))) (apply +))) |
当我们对
1 2 3 4 5 6 7 | (defn sum-by-index-pred [f coll] (->> coll (keep-indexed (fn [i v] (when (f i) v))) (apply +))) ;; using partial application and function composition (def sum-of-evens (partial sum-by-index-pred (comp even? inc))) (def sum-of-odds (partial sum-by-index-pred (comp odd? inc))) |
查看
我建议将其重构,以便将游戏规则和状态计算在一个位置,而不是相互递归的函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | (loop [scores (array-map :player-1 0 :player-2 0) turns (cycle (keys scores)) vs (shuffle (range 100))] (if (seq vs) (let [higher-odds? (> (sum-of-odds vs) (sum-of-evens vs)) scores (if higher-odds? (update scores (first turns) + (first vs)) (update scores (first turns) + (last vs))) remain (if higher-odds? (rest vs) (butlast vs))] (recur scores (rest turns) remain)) (prn scores))) ;; {:player-1 2624, :player-2 2326} |
我不确定这是否能保留您的原始游戏逻辑,但应该接近,并且可以将它推广到两个以上的玩家。尝试将