BLOG

JavaScriptでランダム出題の4択クイズを作ろう【配列から質問と回答を取得】

更新日:2022/09/30

昨今のウェブサイトではさまざまなクイズが公開されていますよね。そんなクイズですが、JavaScriptを使うと簡単に作ることができます。
質問文と回答の選択肢を用意しておき、画面を切り替える、といった方法もありますが、今回は配列の中にある質問文と回答を取得し、HTMLの中身を動的に切り替えるという仕様のクイズの実装方法をご紹介します。
クイズの要素を配列から取得することで更新がしやすくなり、質問の入れ替えやクイズページの複製などがグッと簡単になります。ぜひ記事を参考にクイズコンテンツを作ってみてください。

実際の動作はこちらからご確認いただけます。

4択クイズのデモ「県庁所在地クイズ(全5問)」

ファイルの構成

まずは今回のファイル構成です。ベースとなるファイルは以下の通りです。

・index.html
・js/common.js
・js/jquery-3.6.0.min.js
・css/style.css(記事内ではscssを掲載しています)

HTMLを作成

これらの要素を簡単に作っていきます。

①大枠

cssで見た目を調整するために大枠を作ります。
クイズの要素は.quiz-content内に書いていきます。

②質問の番号

質問の番号を表示するためのエリアです。
文字はjQueryから動的に出力するので中身は空で大丈夫ですが、今は表示確認用に文字を入れています。

③質問文

質問文を表示するためのエリアです。
こちらもjQueryから動的に文字を出力するので中身は空で大丈夫ですが、表示確認用に文字を入れています。

④回答

回答用のエリアです。
こちらもjQueryから動的に文字を出力するので中身は空で大丈夫ですが、表示確認用に文字を入れています。
今回は4択なので、4つ複製します。

ソース全体の表示

css(scss)を作成

①大枠

②質問の番号

③質問文

④回答

gridを使い、選択肢を横並びにしています。
選択肢にあるA~Dのアルファベットは疑似要素で出すことにしました。

これで静的なサイト作りができました。このような見た目になります。

問題の配列を作成

まずは質問文と選択肢を記載した配列を作ります。common.jsの一番上に書いていきます。

idには質問の番号、questionには質問文、answer01~04には回答をいれています。
全5問にしたいので、この配列を5個に複製し、質問文と選択肢を適宜入れ替えてください。

また、今回は選択肢をランダムにして出すので、配列と同じ順番で表示されることはありません。

配列全体の表示

クイズのシステム部分の作成

ということで、本題のクイズのシステム部分を作っていきます。
ベースはこのようになります。

質問番号や質問文、選択肢ボタンなど、クイズに必要な要素を変数に入れておきます。
以下の$targetは、先ほど値を渡した $(‘.quiz’) になります。

現在の質問数も用意しておきます。最初は1番目の質問ですが、JavaScriptの1は0にあたるので0を挿入しておきます。

問題数の合計も用意します。問題数が変わった際は、ここの中身の数字を変更するだけでよいです。

1問あたりの得点用の変数も用意しました。

これで、最低限の下準備が整いました。

ここまでのcommon.jsの表示

質問をランダムにする

まずは質問の出題順をランダムにする準備をおこないます。
クイズのID(1~5)が入った配列quizIdの中身をランダムに入れ替え、ランダムになった数字を一つ目から呼び出す、ということをします。

数字の入れ替えについては、こちらの記事のソースをベースとして使わせてもらっています。
配列の要素の並びをシャッフルする

次の質問を取得

次の質問を取得する関数を作成します。選択肢のボタンをクリックした際、nextQuestion を定義し、その中の関数 searchQuestion に値 value を渡しています。

この値 value はソースの「//次の質問番号を取得」の下で、先ほどの「質問をランダムにする」でシャッフルしたidの $currentNum 番目(つまり先ほど定義した0)から+1された数字が入るようになっています。要するに、配列 quizId の2番目の数字が呼び出されます。

その下に書かれている関数 searchQuestion では配列 prefecturalCapital から$currentNum 番目と同じ数字(id)の質問を探し出す、ということをしています。

次の質問に切り替える

次の質問に切り替える部分を作っていきます。
ちょっと長いので、最初に全体ソースを記載します。

まず最初に変数 _this の中に this をいれています。

続いて、選択肢のボタンをクリックした際、changeQuestionという関数を呼び出します。
値で渡している nextQuestion は先ほどの「次の質問を取得」で定義したもの(つまりシャッフルしたidの $currentNum 番目のid)です。

シャッフルしたidの $currentNum 番目のid が仮に「05」だったとした場合、配列 prefecturalCapital の id:05 のデータを呼び出しています。

例:idが05だった場合に参照されるもの

「クイズのシステム部分の作成」で定義した変数に入れていきます。
先ほど参照した nextQuestion の質問文と選択肢のテキストを取得し、 text() を利用して差し替えます。

質問の型が決まっている場合、以下のように型をテキストで出すようにここで記載すると、質問の配列を少しだけ簡略化することができます。

上記のように書くと、実際には「北海道の県庁所在地は?」と表示されます。

また、「質問1」を「質問2」などに増やしていきたいので、$currentNum に +1 をし、 text() で入れ替えます。

以上までが「次の質問に切り替える」の関数になります。

選択肢をクリックした要素の得点に応じて正解/不正解を表示する

クリックした要素に .button01 というクラスがついている場合「正解」にする、という実装をおこないます。

選択肢のボタンをクリックした際、ボタンのクラスが .button01 だった場合、選択肢が入っているul(.quiz-answer)に is-correct というクラスを追加します。

その次の行で score に $pointPerCorrect(今回は10) を足していますが、この score は最終画面で「50点満点のうち xx点」という形でユーザーの結果発表時に使用しようと思います。

ボタンに .button01 というクラスがついていなかった場合、 is-incorrect というクラスを追加しています。

jQueryで追加したクラスの scss を用意します。
200px四方の疑似要素を用意しておき、.is-correct がついた場合は赤の「〇」、.is-incorrect がついた場合は青の「×」が表示されるようにします。

このような見た目で調整しました。

〇だった場合(.is-correct)

×だった場合(.is-incorrect)

正解/不正解を表示した1秒後に次の質問を取得

続いて、これまでに作った「次の質問を取得」と「次の質問に切り替える」を setTimeout の中に入れ、選択肢のボタンを押した1秒後に質問が切り替わる、というようにします。

その際に、「選択肢をクリックした要素の得点に応じて正解/不正解を表示する」で追加したクラス(.is-correct/.is-incorrect)はクラスを削除するようにします。〇か×が1秒表示されて消えるイメージです。

選択肢を押した1秒間はボタンをクリックできないようにする

〇×表示中に次の質問を呼び出さないよう、「正解/不正解を表示した1秒後に次の質問を取得」で追加した setTimeout を利用して、「選択肢を押した1秒間はボタンをクリックできないようにする」というようにします。

scss で .is-checked がついているときはクリック・タップを無効化します。

ウインドウの読み込み時、質問を取得する

このままでは最初に表示する質問を取得できていない(index.htmlに書かれていた場合、そのまま表示される)ため、1番目の質問を取得します。
これまでに作成した関数を利用し、quizId の配列から取得されるものを最初に宣言した0( $currentNum = 0 )番目とすると、1番目の質問を取得します。

これで、ウインドウが読み込まれた際に1番目の質問に切り替わるようになります。

選択肢をランダムにする

選択肢をランダムにします。

shuffleAnswer の箇所はこちらのブログのソースを使用させていただいています。
jQueryで要素をシャッフル。

このように、選択肢の順番がランダムになります。

5問目まで答えた際、合計点と戻るボタンを表示する

5問目まで答えた際、合計点と戻るボタンを表示しようと思います。
新たに追加するエリアなので、まずは .quiz-content の最上部にHTMLを書きます。

.finish というエリアを追加し、.is-show というクラスがついたら表示するようにしました。

HTML を作ったので、jQueryで呼び出しやすいよう変数に入れておきます。
$currentNum が$questionTotalNum(今回は5)になった際に .finish に .is-show というクラスを追加するようにします。
また、点数用のエリア .score-wrap .score のテキストを合計点(正解だった場合 +10 していったもの)に差し替えます。

作っている途中でエリアを足したりしましたが、これでクイズコンテンツが完成しました。

4択クイズのデモ「県庁所在地クイズ(全5問)」

全体のソース

HTMLソースの表示(mainタグの中のみ)

scssソースの表示

※スマホ用のscssは割愛しています。

jQueryソースの表示

まとめ

今回は4択クイズにしましたが、選択肢を増やしたり2択にして〇×クイズにする、というアレンジも簡単におこなえるソースになっているかと思います。
1ページ内で完結するとてもシンプルな作りではありますが、結果ページやSNSシェアを設けたりすることでより充実したコンテンツに変えられると思います。また、記事内では文字を差し替える .text() を紹介しましたが、他にも画像やCSSをjQueryで動的に変えることができます。問題によって画像を出し分けたり、より動きの多いアニメーションをつけたりすることも可能なので、今回紹介したクイズをベースにあなただけのオリジナルを作っていただければ幸いです。

参考にしたサイト
配列の要素の並びをシャッフルする
jQueryで要素をシャッフル。

FOLLOW US