プログラミング初心者のための「単語帳風クイズラーニングアプリ」開発入門~第2部 学習クイズ実行編~
今回の「学習クイズ実行編」では、「クイズを実行」するプログラムの内容についてお話をしていきたいと思います。
まだ、第1部をご覧になっていない方は、
を先にご覧ください。
クイズを実行する機能は、
- 登録された順番に全てのクイズを実行
- ランダムに「指定されたクイズ数」のクイズを実行
という2つの実行方法があります。

「startLearningQuiz」関数は、次のようになります。
/**
* クイズをスタート
*/
function startLearningQuiz(){
resetSelectAnsBtnOpacity(); //「選択肢ボタン」の透明度を初期化
currentQiuzCount = 1; //現在のクイズ番号を「1」に設定
//ランダムクイズフラグの設定
getElmId("quiz_exec_random").checked ? randomQuiz = true : randomQuiz = false;
randQuizNums = []; //「ランダムクイズの配列要素番号」用配列を初期化
// ランダムクイズの「クイズの配列要素番号」を生成
randomQuiz ? createRandomQuizNums() : randomMaxCount = 0;
// 出題する「クイズの配列要素番号」を生成
createIndexNum();
getElmId("quiz_count").innerHTML = currentQiuzCount; //「クイズ数」を設定
getElmId("quiz").innerHTML = g_learning_data[indexNum]["contents"]; //「クイズ内容」を設定
getElmId("select_1").innerHTML = g_learning_data[indexNum]["select_1"]; //「選択肢1」を設定
getElmId("select_2").innerHTML = g_learning_data[indexNum]["select_2"]; //「選択肢2」を設定
getElmId("select_3").innerHTML = g_learning_data[indexNum]["select_3"]; //「選択肢3」を設定
getElmId("select_4").innerHTML = g_learning_data[indexNum]["select_4"]; //「選択肢4」を設定
getElmId("next").style.display = "none"; //「次へ」ボタンを非表示
getElmId("learning_quiz").style.display = "block"; //「クイズ」を表示
getElmId("setting").style.display = "none"; //「クイズスタート前設定画面」を非表示
dispQuizCount(); //「クイズ番号」と「残りクイズ数」を設定
hideAnswer(); //「クイズ解答」クリック時の処理
getElmId("results").innerHTML = ""; //「結果」を「空」に設定
}
さまざまな処理が実行されていますが、最後に「プログラムの全容」を公開しますので、現在のところは「処理の流れ」を掴んでおいてください。

「clickAnswer」関数は、次のようになります。
/**
* クイズの「解答」クリック時の処理
*/
function clickAnswer(e){
e.target.style.opacity = 0.5; //ボタンの透明度を設定
result = []; //クイズの正誤結果格納用(クイズ内容と結果)
result.push(g_learning_data[indexNum]["contents"]); //クイズ内容を配列に設定
correctAnsObj[parseInt(g_learning_data[indexNum]["answer"]) -1].style.display = "block"; //正解の選択肢に「〇」を表示
// クイズの解答が合っている場合
if(e.target.dataset.id === g_learning_data[indexNum]["answer"]){
correctCount++; // 「正解カウント」を「+1カウントアップ」
// 「クイズデータ」の正解数を「+1カウントアップ」
g_learning_data[indexNum]["success_count"] = parseInt(g_learning_data[indexNum]["success_count"])+1;
result.push("〇"); //「クイズの正誤結果格納用」配列に「〇」を追加
} else { // クイズの解答が間違っている場合
mistakeAnsObj[e.target.dataset.id-1].style.display = "block"; //「誤り」の選択肢に「×」を表示
result.push("×"); //「クイズの正誤結果格納用」配列に「×」を追加
}
results.push(result); //「結果データ群配列」に結果データを追加
// 「クイズ挑戦回数」を「+1カウントアップ」
g_learning_data[indexNum]["challenge_count"] = parseInt(g_learning_data[indexNum]["challenge_count"])+1;
saveLearningData(); //クイズデータをセーブ
dispNextBtn(); //「次へ」ボタンを表示
if (isLast()){dispResults()}; //「クイズ実行結果」を表示
}
「選択肢」ボタンをクリックすると、「選択項目」のボタンの透明度を「0.5」に設定し、結果をボタンの右横に表示しています。

次のクイズが存在する場合は「次へ」ボタンをクリックすると、「toNext」関数が実行され、次のクイズを実行することができます。
/**
* 「次へ」ボタンクリック時の処理
*/
function toNext(){
resetSelectAnsBtnOpacity(); //「選択肢ボタン」の透明度をリセット
hideAnswer(); //「〇」「×」画像を非表示
currentQiuzCount++; //「クイズ番号」を「+1カウントアップ」
// 出題する「クイズの配列要素番号」を生成
createIndexNum(); // 出題する「クイズの配列要素番号」を生成
getElmId("quiz_count").innerHTML = currentQiuzCount; //「クイズ数」を設定
getElmId("quiz").innerHTML = g_learning_data[indexNum]["contents"]; //「クイズ内容」を設定
getElmId("select_1").innerHTML = g_learning_data[indexNum]["select_1"]; //「選択肢1」を設定
getElmId("select_2").innerHTML = g_learning_data[indexNum]["select_2"]; //「選択肢2」を設定
getElmId("select_3").innerHTML = g_learning_data[indexNum]["select_3"]; //「選択肢3」を設定
getElmId("select_4").innerHTML = g_learning_data[indexNum]["select_4"]; //「選択肢4」を設定
getElmId("next").style.display = "none"; //「次へ」ボタンを非表示
getElmId("learning_quiz").style.display = "block"; //「クイズ」を表示
dispQuizCount(); //「クイズ番号」と「残りクイズ数」を設定
}
「次のクイズ」をセットして、画面に表示する処理が実行されています。
全てのクイズを完了すると、「クイズ実行結果」が表示されます。

「クイズの実行結果」を表示する関数は「dispResults」関数ですが、次のようになっています。
/**
* 「クイズ実行結果」を表示
*/
function dispResults(){
getElmId("results").style.display = "block";
let count = 1;
let html = "";
html += "<hr>";
html += "<table>";
html += "<tr>";
html += "<th>No</th><th>問題</th><th>結果</th>";
html += "</tr>";
results.forEach(element => {
html += "<tr>";
html += "<td>" + count + "</td><td>" + element[0] + "</td><td>" + element[1] + "</td>";
html += "</tr>";
count++;
});
html += "</table>";
getElmId("results").innerHTML = html;
results = [];
result = [];
}
「学習クイズ実行ページ(learning.html)」のプログラムコード
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>単語帳風クイズラーニングアプリ-学習-</title>
<link rel="stylesheet" href="common.css">
<link rel="stylesheet" href="learning.css">
<script src="common.js"></script>
<script>
let g_learning_data = null; //学習データ格納用
let currentQiuzCount = 1; //現在のクイズ番号
let indexNum = 0; //配列要素番号
let correctAnsObj = null; //「〇」画像オブジェクト格納用
let mistakeAnsObj = null; //「×」画像オブジェクト格納用
let correctCount = 0; //問題正解数カウント
let randomQuiz = false; //ランダム出題ステータス
let randomMaxCount = 0; //ランダム出題時の出題数
let results = []; //結果データ群
let result = []; //結果データ
let randQuizNums = []; //ランダム出題時の配列要素番号格納用
/**
* クイズをスタート
*/
function startLearningQuiz(){
resetSelectAnsBtnOpacity(); //「選択肢ボタン」の透明度を初期化
currentQiuzCount = 1; //現在のクイズ番号を「1」に設定
//ランダムクイズフラグの設定
getElmId("quiz_exec_random").checked ? randomQuiz = true : randomQuiz = false;
randQuizNums = []; //「ランダムクイズの配列要素番号」用配列を初期化
// ランダムクイズの「クイズの配列要素番号」を生成
randomQuiz ? createRandomQuizNums() : randomMaxCount = 0;
// 出題する「クイズの配列要素番号」を生成
createIndexNum();
getElmId("quiz_count").innerHTML = currentQiuzCount; //「クイズ数」を設定
getElmId("quiz").innerHTML = g_learning_data[indexNum]["contents"]; //「クイズ内容」を設定
getElmId("select_1").innerHTML = g_learning_data[indexNum]["select_1"]; //「選択肢1」を設定
getElmId("select_2").innerHTML = g_learning_data[indexNum]["select_2"]; //「選択肢2」を設定
getElmId("select_3").innerHTML = g_learning_data[indexNum]["select_3"]; //「選択肢3」を設定
getElmId("select_4").innerHTML = g_learning_data[indexNum]["select_4"]; //「選択肢4」を設定
getElmId("next").style.display = "none"; //「次へ」ボタンを非表示
getElmId("learning_quiz").style.display = "block"; //「クイズ」を表示
getElmId("setting").style.display = "none"; //「クイズスタート前設定画面」を非表示
dispQuizCount(); //「クイズ番号」と「残りクイズ数」を設定
hideAnswer(); //「クイズ解答」クリック時の処理
getElmId("results").innerHTML = ""; //「結果」を「空」に設定
}
/**
* 出題する「クイズの配列要素番号」を生成
*/
function createIndexNum(){
indexNum = currentQiuzCount-1; //クイズの配列要素番号を取得
if( randomQuiz ){
indexNum = randQuizNums[0]; //ランダムクイズの配列要素番号を取得
randQuizNums.splice(0, 1); //取得した配列要素番号を削除
}
}
/**
* ランダムに出題する「クイズの配列要素番号」を生成
*/
function createRandomQuizNums(){
randomMaxCount = getElmId("quiz_exec_count").value; //クイズの実行数を設定
let nums = []; //配列要素番号格納用
let rand = 0; //ランダム値格納用
//配列要素番号を作成
for( let i = 0; i < g_learning_data.length; i++) {
nums.push(i);
}
//ランダムな配列要素番号を作成
for( let i = 0; i < randomMaxCount; i++) {
rand = Math.floor(Math.random() * nums.length);
randQuizNums.push(nums[rand]);
nums.splice(rand, 1);
}
}
/**
* 「クイズ実施数」のセレクトボックスの選択項目を作成
*/
function createQuizCountSelectOption(){
for( var i =0; i < g_learning_data.length; i++){
let optionObj = document.createElement('option');
optionObj.value = i+1;
optionObj.innerHTML = i+1;
getElmId('quiz_exec_count') .appendChild(optionObj);
getElmId('start_learning_btn').addEventListener('click', startLearningQuiz, false);
}
}
/**
* クイズの「解答」クリック時の処理
*/
function clickAnswer(e){
e.target.style.opacity = 0.5; //ボタンの透明度を設定
result = []; //クイズの正誤結果格納用(クイズ内容と結果)
result.push(g_learning_data[indexNum]["contents"]); //クイズ内容を配列に設定
correctAnsObj[parseInt(g_learning_data[indexNum]["answer"]) -1].style.display = "block"; //正解の選択肢に「〇」を表示
// クイズの解答が合っている場合
if(e.target.dataset.id === g_learning_data[indexNum]["answer"]){
correctCount++; // 「正解カウント」を「+1カウントアップ」
// 「クイズデータ」の正解数を「+1カウントアップ」
g_learning_data[indexNum]["success_count"] = parseInt(g_learning_data[indexNum]["success_count"])+1;
result.push("〇"); //「クイズの正誤結果格納用」配列に「〇」を追加
} else { // クイズの解答が間違っている場合
mistakeAnsObj[e.target.dataset.id-1].style.display = "block"; //「誤り」の選択肢に「×」を表示
result.push("×"); //「クイズの正誤結果格納用」配列に「×」を追加
}
results.push(result); //「結果データ群配列」に結果データを追加
// 「クイズ挑戦回数」を「+1カウントアップ」
g_learning_data[indexNum]["challenge_count"] = parseInt(g_learning_data[indexNum]["challenge_count"])+1;
saveLearningData(); //クイズデータをセーブ
dispNextBtn(); //「次へ」ボタンを表示
if (isLast()){dispResults()}; //「クイズ実行結果」を表示
}
/**
* 「〇」「×」画像を非表示
*/
function hideAnswer(){
//「〇」画像オブジェクトを全て非表示
correctAnsObj.forEach(element => {
element.style.display = "none";
});
//「×」画像オブジェクトを全て非表示
mistakeAnsObj.forEach(element => {
element.style.display = "none";
});
}
/**
* 「次へ」ボタンクリック時の処理
*/
function toNext(){
resetSelectAnsBtnOpacity(); //「選択肢ボタン」の透明度をリセット
hideAnswer(); //「〇」「×」画像を非表示
currentQiuzCount++; //「クイズ番号」を「+1カウントアップ」
// 出題する「クイズの配列要素番号」を生成
createIndexNum(); // 出題する「クイズの配列要素番号」を生成
getElmId("quiz_count").innerHTML = currentQiuzCount; //「クイズ数」を設定
getElmId("quiz").innerHTML = g_learning_data[indexNum]["contents"]; //「クイズ内容」を設定
getElmId("select_1").innerHTML = g_learning_data[indexNum]["select_1"]; //「選択肢1」を設定
getElmId("select_2").innerHTML = g_learning_data[indexNum]["select_2"]; //「選択肢2」を設定
getElmId("select_3").innerHTML = g_learning_data[indexNum]["select_3"]; //「選択肢3」を設定
getElmId("select_4").innerHTML = g_learning_data[indexNum]["select_4"]; //「選択肢4」を設定
getElmId("next").style.display = "none"; //「次へ」ボタンを非表示
getElmId("learning_quiz").style.display = "block"; //「クイズ」を表示
dispQuizCount(); //「クイズ番号」と「残りクイズ数」を設定
}
/**
* 「クイズ番号」と「残りクイズ数」を設定
*/
function dispQuizCount(){
getElmId("quiz_count").innerHTML = currentQiuzCount;
if( randomQuiz ){
getElmId("quiz_remain").innerHTML = randomMaxCount - currentQiuzCount;
} else {
getElmId("quiz_remain").innerHTML = g_learning_data.length - currentQiuzCount;
}
}
/**
* 「次へ」ボタンを表示
*/
function dispNextBtn(){
isLast() ? getElmId("next").style.display = "none" : getElmId("next").style.display = "block";
}
/**
* 「クイズ実行結果」を表示
*/
function dispResults(){
getElmId("results").style.display = "block";
let count = 1;
let html = "";
html += "<hr>";
html += "<table>";
html += "<tr>";
html += "<th>No</th><th>問題</th><th>結果</th>";
html += "</tr>";
results.forEach(element => {
html += "<tr>";
html += "<td>" + count + "</td><td>" + element[0] + "</td><td>" + element[1] + "</td>";
html += "</tr>";
count++;
});
html += "</table>";
getElmId("results").innerHTML = html;
results = [];
result = [];
}
/**
* 「スタート画面(設定画面)」表示処理
*/
function resetScreenToStart(){
getElmId("setting").style.display = "block"; //「クイズ設定画面」を表示
getElmId("learning_quiz").style.display = "none"; //「クイズ画面」を非表示
getElmId("results").style.display = "none"; //「クイズ結果画面」を非表示
}
/**
* 「選択肢ボタン」の透明度をリセット
*/
function resetSelectAnsBtnOpacity(){
getElmId("select_1").style.opacity = 1.0;
getElmId("select_2").style.opacity = 1.0;
getElmId("select_3").style.opacity = 1.0;
getElmId("select_4").style.opacity = 1.0;
}
/**
* 「最後のクイズ」を判定
*/
function isLast(){
if( randomQuiz ){
if(randomMaxCount <= currentQiuzCount){
return true;
}
} else {
if(g_learning_data.length <= currentQiuzCount){
return true;
}
}
return false;
}
window.onload = function(){
loadLearningData(); //「学習データ」をロード
createQuizCountSelectOption(); //「クイズ実施数」のセレクトボックスの選択項目を作成
getElmId("select_1").addEventListener("click", clickAnswer, false); //「選択肢1」ボタンのイベントリスナーを設定
getElmId("select_2").addEventListener("click", clickAnswer, false); //「選択肢2」ボタンのイベントリスナーを設定
getElmId("select_3").addEventListener("click", clickAnswer, false); //「選択肢3」ボタンのイベントリスナーを設定
getElmId("select_4").addEventListener("click", clickAnswer, false); //「選択肢4」ボタンのイベントリスナーを設定
getElmId("start_screen").addEventListener("click", resetScreenToStart, false); //「スタート画面へ」ボタンのイベントリスナーを設定
getElmId("next").addEventListener("click", toNext, false); //「次へ」ボタンのイベントリスナーを設定
getElmId("learning_quiz").style.display = "none"; //「クイズ画面」を非表示
correctAnsObj = Array.from(document.getElementsByClassName("correct")); //「〇」画像オブジェクトを配列で取得
mistakeAnsObj = Array.from(document.getElementsByClassName("mistake")); //「×」画像オブジェクトを配列で取得
hideAnswer(); //「〇」「×」画像を非表示
//「クイズデータ」の有無を確認
if(g_learning_data.length === 0){
alert("先にクイズを登録してください。クイズがスタートできません。");
}
}
</script>
</head>
<body>
<div id="wrap_frame">
<header>
<img src="./images/title.png">
</header>
<section id="setting">
<h2>ランダム実行</h2>
<input type="checkbox" id="quiz_exec_random">
<h2>ランダム出題時のラーニングクイズ実行数</h2>
<select id="quiz_exec_count"></select>
<button id="start_learning_btn">スタート</button>
</section>
<section id="learning_quiz">
<div id="quiz_num">第<span id="quiz_count"></span>問</div>
<div id="remain_num">(残り<span id="quiz_remain"></span>問)</div>
<div id="quiz"></div>
<ul id="answer">
<li><button id="select_1" data-id="1"></button><img src="./images/answer_correct.png" class="correct"><img src="./images/answer_mistake.png" class="mistake"></li>
<li><button id="select_2" data-id="2"></button><img src="./images/answer_correct.png" class="correct"><img src="./images/answer_mistake.png" class="mistake"></li>
<li><button id="select_3" data-id="3"></button><img src="./images/answer_correct.png" class="correct"><img src="./images/answer_mistake.png" class="mistake"></li>
<li><button id="select_4" data-id="4"></button><img src="./images/answer_correct.png" class="correct"><img src="./images/answer_mistake.png" class="mistake"></li>
</ul>
<button id="next">次へ</button>
<hr>
<button id="start_screen">スタート画面へ</button>
</section>
<section id="results"></section>
<a href="index.html" id="to_main">メイン画面へ戻る</a>
</div>
</body>
</html>
下記のリンクから「ラーニングクイズアプリ」が試用できます。
「学習したい内容」は、自由に登録することができますので、クイズで遊びながら「学習をより楽しい時間」に変えてみてはいかがでしょうか。