プログラミング初心者のための「単語帳風クイズラーニングアプリ」開発入門~第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>
下記のリンクから「ラーニングクイズアプリ」が試用できます。
「学習したい内容」は、自由に登録することができますので、クイズで遊びながら「学習をより楽しい時間」に変えてみてはいかがでしょうか。