如何加速落后的Swing扫雷板?

时间:2016-03-15 08:12:06

标签: swing user-interface clojure minesweeper seesaw

我最近使用seesaw框架创建了一个小扫雷UI,这个框架基本上是一个漂亮的clojure包装。可以找到相关代码here

Minesweeper board

基本上到目前为止一切正常,唯一的问题是当你选择在专家级别上玩时,用户体验非常糟糕。原因是每次点击一个细胞时,整个ui都会重新粉刷,这需要很长时间(平均850毫升)。

负责重新绘制的代码如下:

(ns minesweeper.icons
  (:require
    [clojure.java.io :as io]
    [clojure.string  :as str]
    [seesaw.icon :as icon]))

(def ^:private cell-icons-path "minesweeper/icons/cell")
(def ^:private face-icons-path "minesweeper/icons/face")

(defn- file-name
  [file]
  (str/replace-first
   (.getName file) #"\.[^.]+$" ""))

(def ^:private init-icons
  (memoize
   (fn [res]
     (let [parent (rest (file-seq (io/file (io/resource res))))]
       (reduce
        #(assoc %1 (keyword (file-name %2)) (icon/icon %2))
        {}
        parent)))))

(defn cell-icons
  [id]
  (let [icons (init-icons cell-icons-path)]
    (get icons id)))

(defn face-icons
  [id]
  (let [icons (init-icons face-icons-path)]
    (get icons id)))

图标处理的代码如下所示

{{1}}

所以我的问题是,如何更有效地处理这个问题?我想过只更新受点击影响的单元格(由JButtons表示)但是如果auto-clear打开了很多相邻的单元格,这可能还需要一段时间。

使用带有按钮的mig布局来表示电路板一般是合理的选择吗?

1 个答案:

答案 0 :(得分:2)

使用clojure.core/time我发现UI逻辑中的瓶颈是使用(select ui [(keyword (str "#field_" idx))])查找按钮,因为每次更新时,seesaw必须通过过滤层次结构中的所有组件来进行名称搜索板。

最快的解决方法是将select-field功能包装到memoize但是当您重新启动游戏时它不会起作用(将创建新的按钮,以便记住select-field从上一场比赛返回按钮。)

另一种可能的解决方案是将所有按钮放入向量中并将其保存在全局atom中:

(def items (atom []))
(defn select-field
  [idx]
  (@items idx))

改变你创建董事会的方式:

(defn- make-board-panel
  [snapshot]
  (let [bg    (button-group)
        [n m] (:dimension snapshot)
        buttons (into [] (for [idx (range (* n m))]
                       (make-button idx bg)))]
    (reset! items buttons)
    (mig-panel
     :constraints [(str "gap 0, wrap" n) "[]" "[]" ]
     :items       (map #(vector % "w 24px!, h 24px!") buttons))))

测试

我已将update-board正文包裹在clojure.core/time中并通过播放10次(new-game 50 50 1)获得了以下结果:

修复前

"Elapsed time: 7020.756206 msecs"
"Elapsed time: 6766.130362 msecs"
"Elapsed time: 6616.715565 msecs"
"Elapsed time: 6628.383521 msecs"
"Elapsed time: 6657.386279 msecs"
"Elapsed time: 6588.50692 msecs"
"Elapsed time: 6554.704587 msecs"
"Elapsed time: 6650.864132 msecs"
"Elapsed time: 6610.557065 msecs"
"Elapsed time: 6671.02469 msecs"

修复后

"Elapsed time: 92.491489 msecs"
"Elapsed time: 60.236867 msecs"
"Elapsed time: 32.254729 msecs"
"Elapsed time: 29.551383 msecs"
"Elapsed time: 29.383067 msecs"
"Elapsed time: 25.768517 msecs"
"Elapsed time: 25.724915 msecs"
"Elapsed time: 45.869723 msecs"
"Elapsed time: 25.898016 msecs"
"Elapsed time: 26.254874 msecs"