【JavaScript】クイズアプリを作ってみよう（応用編）


こちらの記事は、[【JavaScript】クイズアプリを作ってみよう（基礎編）](https://qiita.com/asami___t/items/cb4c750b721737e83908)の続きになります。

基礎編は1問解いて終わりでしたが、応用編では3問解き続けて、最後に「あなたは3問中●問正解でした」と表示させたいと思います。
HTMLファイルは基礎編から変更はありません。

# 3問解き続けられるようにする

```JavaScript:app.js
// 複数のクイズを解けるようにするため、連想配列(辞書型){}に変更する。
// 連想配列を作ったら、リスト型[]で囲む。
const quiz = [
  // 1つ目のクイズを定義
  {
    question: '赤い果物は次のうちどれでしょう？',
    answers: [
      'メロン',
      'レモン',
      'バナナ',
      'りんご'
    ],
    correct: 'りんご'
  },
  // 2つ目のクイズを定義
  {
    question: '果物は次のうちどれでしょう？',
    answers: [
      'おにぎり',
      '餃子',
      'いちご',
      '寿司'
    ],
    correct: 'いちご'
  },
  // 3つ目のクイズを定義
  {
    question: '日本の首都は次のうちどれでしょう？',
    answers: [
      '京都',
      '東京',
      '大阪',
      '神戸'
    ],
    correct: '東京'
  }
]

// quizの要素数を定義する
let quizLength = quiz.length;
// quizのindex番号[0],[1],[2]...を変数で表現できるようにする
let quizIndex = 0;

/*****************************************************
ボタンはいろんな所で呼び出して使うため、グローバル変数として置く。
*****************************************************/
// 選択肢の文を上書き
const $button = document.getElementsByTagName('button');
const buttonLength = $button.length;


/**********************************************************
問題文、選択肢をHTMLから上書きする動きを、1つの「関数」としてまとめる。
この関数を実行することにより上書きされた情報が画面に表示される。
**********************************************************/
const setUpQuiz = () => {
  // 問題文を上書き
  document.getElementById('js-question').textContent = quiz[quizIndex].question;

  let i = 0;
  let choices_i = 0;
  // 選択肢を全部取得する
  while ( i < buttonLength ) {
    $button[i].textContent = quiz[quizIndex].answers[choices_i];
    i++;
    choices_i++;
  }
}
setUpQuiz();

/***************************************************
clickHandler()関数が定義されている箇所。
①クリックしたボタンが正解なのか不正解なのかで表示を切り替える。
②クイズを次に進める。
③クイズが終わるまでセットアップを繰り返す。
***************************************************/
const clickHandler = (e) => {
  if(quiz[quizIndex].correct === e.target.textContent ) {
    window.alert('正解!');
  } else {
    window.alert('不正解...');
  }
  // 問題文がまだある場合ともう無い場合とで条件分岐させる
  if (quizIndex < quizLength) {
    // 次のquizに進める命令文が必要なため、quizIndexをインクリメントさせる
    quizIndex++;
    // セットアップし直し
    setUpQuiz();
  } else {
    window.alert('終了');
  }
}

/****************************************
clickHandler()関数を呼び出して実行している箇所。
繰り返し期間を指定した状態で呼び出している。
*****************************************/
let eventHandleIndex = 0;
// buttonLength がローカル変数として定義されてしまっており使用できないため、グローバル変数に変更する。

// 該当ボタンをクリックした時にaddEventListenerが走るのを繰り返す。
while (eventHandleIndex < buttonLength) {
  $button[eventHandleIndex].addEventListener('click', (e) => {
  clickHandler(e);
  })
  eventHandleIndex++;
}
```

# 最後に「あなたは3問中●問正解でした」と表示させる

```JavaScript:app.js
// 複数のクイズを解けるようにするため、連想配列(辞書型){}に変更する。
// 連想配列を作ったら、リスト型[]で囲む。
const quiz = [
  // 1つ目のクイズを定義
  {
    question: '赤い果物は次のうちどれでしょう？',
    answers: [
      'メロン',
      'レモン',
      'バナナ',
      'りんご'
    ],
    correct: 'りんご'
  },
  // 2つ目のクイズを定義
  {
    question: '果物は次のうちどれでしょう？',
    answers: [
      'おにぎり',
      '餃子',
      'いちご',
      '寿司'
    ],
    correct: 'いちご'
  },
  // 3つ目のクイズを定義
  {
    question: '日本の首都は次のうちどれでしょう？',
    answers: [
      '京都',
      '東京',
      '大阪',
      '神戸'
    ],
    correct: '東京'
  }
]

let quizLength = quiz.length;
let quizIndex = 0;
/****
 * 問題文をsetUpQuiz()関数の中に入れておくと
「変数questionが未定義のため読み込めません」というエラーを吐くため、
グローバル変数とする。
****/
const $question = document.getElementById('js-question');

const $button = document.getElementsByTagName('button');
const buttonLength = $button.length;

// 結果（正解の数）を表す変数を定義
let score = 0;

const setUpQuiz = () => {
  /******** （更新した）問題文を取得してHTMLを上書き表示 *********/
  $question.textContent = quiz[quizIndex].question;
  /******** （更新した）選択肢を取得してHTMLを上書き表示 *********/
  let i = 0;
  let choices_i = 0;
  while ( i < buttonLength ) {
    $button[i].textContent = quiz[quizIndex].answers[choices_i];
    i++;
    choices_i++;
  }

}
setUpQuiz();

const clickHandler = (e) => {
  if(quiz[quizIndex].correct === e.target.textContent ) {
    window.alert('正解!');
    score++;
  } else {
    window.alert('不正解...');
  }
  // 問題文がまだある場合ともう無い場合とで条件分岐させる
  // 【注意】 quizIndex++はif-elseの直前で書かないとエラーとなる。
  quizIndex++;
  if (quizIndex < quizLength) {
    // 次のquizに進める命令文が必要なため、quizIndexをインクリメントさせる
    window.alert('次の問題です。');
    // セットアップし直し
    setUpQuiz();
  } else {
    window.alert('これでクイズは終了です。あなたは' + quizLength + '問中' + score + '問正解でした。' );
  }
}

let eventHandleIndex = 0;

while (eventHandleIndex < buttonLength) {
  $button[eventHandleIndex].addEventListener('click', (e) => {
  clickHandler(e);
  })
  eventHandleIndex++;
}
```