kiyo_hikoのブログ

メモ+日記?

Javaでクイズ暗記ツール作成(5)

表面だけ作っていたので、いい加減内部構造を作ることにした。
データベースは詳しくないし、取り扱いがライトなテキストファイルから問題を読ませる。

まず多答形式を作った。
設計は適当。

ファイルフォーマット

とにかく記述が楽ちんになるように、フォーマットは次のようにした。

  • 「;」以下はコメント
  • 空行や空文字列だけの行を読み飛ばす
  • 「{」で問題開始、「}」で問題終了
  • 「----」で問題と選択肢を区切る
  • 選択肢で正解は「o:文字列」で、不正解は「x:文字列」

具体的にはこうなる↓

{ ; 理系・多答
次のうち毒を持つ植物を全て選びなさい。
----
o:トリカブト
o:スイセン
o:フクジュソウ
x:ドクダミ
x:アマチャヅル
}

これをUTF-8のテキストで用意する。こうしておくとNotepad++でユーザー定義言語として解析させるときに、「----」をブロック開始点、「}」をブロック終了点としておけば、Notepad++で開くだけでも回答部を折りたたんで復習ができる。「----」に「}」を対応させるのが気持ち悪いが仕方ない。フォーマットを再検討して別の形式に変えるかもしれない。

ローダー

上記のテキストを、以下のようなクラスで読み込ませる。

TatouLoader

  • List<Tatou> load(String filename) throws Exception

みたいなメソッドで、ファイル名から多答クイズのリストを作る。
Tatouというのは以下。

Tatou

以下の様なメソッドを用意する、クイズデータを保持するクラス。

  • question
    • 問題文を返す。
  • selections
    • 選択肢をランダムに返す。
    • 4項目を超えた場合、4項目に丸められる。
  • verify
    • 文字列リストを受け取って、正しい選択肢だけを選んでいればtrue、間違った選択肢を選んでいればfalseを返す述語。
  • answers
    • 正しい選択肢をすべて返す。


大ざっぱにはTatouLoaderのloadで作っておいて、出題時にquestionで問題とselectionsで選択肢を表示させて、回答するとverifyで正解か照合する。


selectionsを作るのでちょっと勝手がわからず色々調べながらやってみたところ、

  • ArrayListのコピーはArrayList copy = new ArrayList(original)とやるといいらしい
  • appendはone.addAll(another)とやるといいらしい
  • shuffleはCollections.shuffle(xs, new Random())とやるといいらしい
  • takeはxs.subList(from, to)でいいらしい

などがわかったので、こんな感じで書いた↓

	public List<String> selections() {
		List<String> xs = new ArrayList<String>(rights);
		xs.addAll(wrongs);
		Collections.shuffle(xs, new Random());
		return xs.size() <= 4 ? xs : xs.subList(0, 4);
	}

rightsは○の選択肢で、wrongsは✕の選択肢。
xsなんて変数名だと会社だとすごく怒られそうだけど、スコープ数行で読めばわかるローカル変数に、説明的な名前をつける気にならない…。
後半部を一般化しtakeRandom(n, xs)とかにして、汎用のユーティリティに昇格しておくと今後楽そうな気がした。

ガワとの結合

これから。画面を、持ってる昔のモバイルPC↓

ONKYO パーソナルモバイル NX707A4

ONKYO パーソナルモバイル NX707A4

でも遊べるサイズにしようと思ったら、CF-C1Bで表示したときにボタンがちっぽけすぎてまともにタッチできない。
画面解像度に追従するようなGUIをSwingで書けないものだろうか…。