【HTML + JavaScript】漢字や読み仮名カードをドラッグ＆ドロップする2字熟語クイズ (PC+スマートフォン両対応)

この記事は、以下の記事で実装したスクリプトを利用して[2字熟語クイズ](https://cookiebox26.github.io/games/misc/card_3.html)を作ったものです。

https://qiita.com/CookieBox26/items/15cf863ddba02701aa6f

- 漢字検定を受検予定だが、漢字以前に言葉が難しいという人のために作ったものです。
- 思った動きになるよう実装しただけで、前回に輪をかけて知見も汎用性もないですが、以下の箇所を変更すれば「4字熟語クイズ」「難読地名クイズ」などに応用できます (?)。
[https://github.com/CookieBox26/games/blob/32f03fc/misc/card_3.html#L236-L293](https://github.com/CookieBox26/games/blob/32f03fc/misc/card_3.html#L236-L293)

### 作成物

以下が作成した2字熟語クイズゲームです。
https://cookiebox26.github.io/games/misc/card_3.html

ソースは上のページのソースを表示すればみられますが以下 (1ファイル) です。
[https://github.com/CookieBox26/games/blob/32f03fc/misc/card_3.html](https://github.com/CookieBox26/games/blob/32f03fc/misc/card_3.html)

お手元のデバイスがスマートフォンであるか、ウィンドウの横幅が狭い場合は、以下のようなレイアウトになります。カードに正しい漢字を置くと漢字が固定されカードが光ります。すべてのカードを正しい置き場に運ぶと次ラウンドに進みます。
<img width="270px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177688/5f204c48-0865-508a-b332-bccb5ffe8be5.png">　<img width="270px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177688/9aea374b-35d7-932e-6e69-4ce1850e3ccc.png">

横長のデバイスだと以下のようなレイアウトになるはずです。
<img width="400px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177688/9c3f7f8c-7f11-02f4-9cd2-e10f9e45bb92.png">

「？」ボタンをクリックするとカード10枚モードに切り替えられます (ただし横幅を一定以上確保しておかないと切り替わりません)。
<img width="560px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177688/093277b2-6b71-aba4-932d-7081efa3544c.png">

### 簡単な説明

JavaScript 部分は以下です。
[https://github.com/CookieBox26/games/blob/32f03fc/misc/card_3.html#L230-L710](https://github.com/CookieBox26/games/blob/32f03fc/misc/card_3.html#L230-L710)

- クイズのセットアップ (カード置き場やカードや漢字などの要素の作成) は `init()` からたどってください。
  - `2 * nQ` 個の正解漢字に加え、`nE - 2 * nQ` 個のダミー漢字が用意されます。
- 要素のドラッグドロップを実現する箇所は `// ----- パソコン・スマートフォン共通のドラッグドロップ用 -----` 以下をみてください。[前回記事](https://qiita.com/CookieBox26/items/15cf863ddba02701aa6f)からほとんど変わりません。
  - 前回記事からそうしていましたが、関数 `isDroppableBox(element)` に「そこに要素をドロップできるか」を集約しているので、実装時にパソコンとスマートフォンのイベントの差異を意識する必要はありませんでした。
    - ただし、カードに正しい漢字たちが置かれたらもうドラッグできないようにしたかったため、そこで意識する必要がありました (スマートフォン向けには「`item` クラスはドラッグできる」としてあるのでこのクラスさえはがせばよいですが、パソコンでは「`draggable` 属性がドラッグできる」なのでこの属性をはがします)。[https://github.com/CookieBox26/games/blob/32f03fc/misc/card_3.html#L489-L497](https://github.com/CookieBox26/games/blob/32f03fc/misc/card_3.html#L489-L497)
- 要素が正しい配置にドラッグドロップされたかの正解判定は `judge(element)` からたどってください。ドラッグ中のものが手放されるたびに (あるいはスマートフォンの画面から指が離れるたびに) これを走らせています。
  - これを書いていて気づきましたが、何か手放すたびに正解判定する必要はなく、その結果要素の `appenChild` が発生したときだけ正解判定すればよいと思います。
  - それぞれの漢字の要素には ID があるわけではなく、漢字の並びが採点されるので、同じ漢字を含む言葉が同時に出題されても破綻はしません。他方、正解が複数ありうる場合には対応していません (「称賛」でなく「賞賛」でもよいというような)。
  - 判定の結果正解であった場合は、モーダルで画面を多い、その中央に配置した白いメッセージ欄でプレイヤーに「ミッションコンプリート！」と伝えます (下図)。メッセージ欄が `body` の中央にくるようにモーダルを `body` の大きさに同期させています。<br/><img width="540px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177688/3c02cff3-4c9a-91ba-2599-ae38438c98c6.png">
- その他の補足事項として、
  - カード置き場を画面の一番目に付く場所に置き＆画面を有効活用するため、パソコン向けとスマートフォン向けとで order プロパティで要素の順序を変更しています (`div#progress-container` と `div#answer-container` が逆になっています)。

### 備考
- 仮にもしこのスクリプトをカスタマイズして使用される方がいらっしゃった場合、`helpMessage` の連絡先は変更の上でご使用ください。
- このようなクイズをつくった経緯は、最近ポケポケが登場したので、カードの上にエネルギーをドラッグ＆ドロップするインターフェースにしたかったからなのですが、完成したクイズを想定ユーザである子どもに遊んでもらいポケポケらしさがあるか訊いたら、「エネルギーをつけた結果、攻撃ができるようにしてほしい」といわれました。何を攻撃すればよいのかわかりません。