私は最近、シーソーフレームワークを使用して小さなマインスイーパ UI を作成しました。関連するコードはここにあります。
基本的には今のところすべて問題なく動作していますが、唯一の問題は、エキスパート レベルでプレイすることを選択した場合のユーザー エクスペリエンスが非常に悪いことです。その理由は、セルをクリックするたびに UI 全体が再描画され、これにはかなりの時間がかかる (平均 850 ミリ秒) ためです。
再描画を担当するコードは次のとおりです。
(defn- update-fields
[cell-states]
(doseq [[idx state] (map-indexed vector cell-states)
:let [field (select-field idx)]]
(config! field :icon (icons/cell-icons state))))
(defn- update-board
[snapshot face]
(do
(change-smiley face)
(update-fields (:cells snapshot))
(repaint! ui)))
アイコン処理のコードは次のようになります
(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)))
だから私の質問は、これにもっと効率的にアプローチする方法は? クリックの影響を受けるセル (JButton で表される) のみを更新することを考えましたが、自動クリアが多数の隣接セルを開く場合、これにもかなりの時間がかかる場合があります。
ボードを表すためにボタン付きの mig レイアウトを使用することは、一般的に合理的な選択ですか?