5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JavaScriptでクイズアプリを作る

Last updated at Posted at 2021-06-25

HTML + CSS + JavaScript を使ってクイズアプリを作りました。問題数は少ないですが、遊んでみてください!

スクリーンショット 2021-06-23 1.30.47.png

URL
https://cordelia-sixth.github.io/quiz_app_js/

ソースコード
https://github.com/cordelia-sixth/quiz_app_js

ディレクトリ構成

app
 ├── index.html
 ├── script.js
 ├── style.css
 └── quiz_data_jp.js

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="style.css">
  <script type="module" src="script.js" defer></script>
</head>
<body>
  <div id="quiz-container">
    <div id="quiz-header">
      <h2 id="question">Question text</h2>
      
      <form id="quiz-form" name="quizForm">
        <ul>
          <li>
            <input type="radio" id="a" name="answer" value="a" />
            <label id="a-text" for="a">Question</label>
          </li>
          <li>
            <input type="radio" id="b" name="answer" value="b" />
            <label id="b-text"  for="b">Question</label>
          </li>
          <li>
            <input type="radio" id="c" name="answer" value="c" />
            <label id="c-text"  for="c">Question</label>
          </li>
          <li>
            <input type="radio" id="d" name="answer" value="d" />
            <label id="d-text"  for="d">Question</label>
          </li>
        </ul>  
      </form>
    </div>
    
    <button id="submit">回答する</button>

    <!-- 結果表示用の要素 -->
    <div id="results-container">
      <div id="results-header">
        <h2 id="results"></h2>
        <button id="next-quiz">次の問題へ</button>
      </div>
    </div>
  </div>
</body>
</html>

これはクイズに答えた結果を表示する要素です。初めはCSSで表示しないようにしてあります。

<!-- 結果表示用の要素 -->
<div id="results-container">
  <div id="results-header">
    <h2 id="results"></h2>
    <button id="next-quiz">次の問題へ</button>
  </div>
</div>

script.js
// クイズデータを読み込む
import { quizDataJp } from './quiz_data_jp.js';

// 問題文
const questionElm = document.getElementById('question');

// 選択肢
const a_text = document.getElementById('a-text');
const b_text = document.getElementById('b-text');
const c_text = document.getElementById('c-text');
const d_text = document.getElementById('d-text');

// 回答送信ボタン
const submitBtn = document.getElementById('submit');

// 現在の問題
let currentQuiz = 0;

// 現在のスコア
let score = 0;

// 次の問題へ進むボタン
const nextQuizBtn = document.getElementById('next-quiz');

// 結果表示用の要素
const quizHeaderElm = document.getElementById('quiz-header');
const resultsConElm = document.getElementById('results-container');
const resultsElm = document.getElementById('results');

loadQuiz();

// 問題を読み込む
function loadQuiz() {
  // 問題を取得
  const currentQuizData = quizDataJp[currentQuiz];

  // 質問文を表示
  questionElm.innerText = currentQuizData.question;

  // 選択肢を表示
  a_text.innerText = currentQuizData.a;
  b_text.innerText = currentQuizData.b;
  c_text.innerText = currentQuizData.c;
  d_text.innerText = currentQuizData.d;
}

// 回答を取得
function getAnswered() {

  // 選択したラジオボタンのvalueを返す
  return document.quizForm.answer.value;
}

// 結果表示
function showResults(results) {
  quizHeaderElm.style.display = 'none';
  submitBtn.style.display = 'none';
  resultsConElm.style.display = 'block';
  resultsElm.innerText = results;
}

// 次の問題を表示
function showQuiz() {
  quizHeaderElm.style.display = 'block';
  submitBtn.style.display = 'block';
  resultsConElm.style.display = 'none';
}

// 採点
function checkScore() {
  if (score == quizDataJp.length) {
    return '全問正解!おめでとう!';
  } else {
    return '曲を聞いてもう一回挑戦しよう!';
  }
}

submitBtn.addEventListener('click', event => {
  event.preventDefault();

  // 回答を取得
  const answer = getAnswered();

  // 回答している
  if(answer) {

    // 正誤判定
    if (answer === quizDataJp[currentQuiz].correct) {
      showResults('正解!');
      score++;
    } else {
      showResults('残念...');
    }

    // ラジオボタンの選択を解除する
    document.getElementById(answer).checked = false;
  }
});

nextQuizBtn.addEventListener('click', event => {
  event.preventDefault();

  // 次の問題へ進む
  currentQuiz++;

  // まだ問題が残っている
  if (currentQuiz < quizDataJp.length) {
    // 次の問題を読み込む
    loadQuiz();

    // 問題を表示する
    showQuiz();

  // 全ての問題に回答した
  } else {
    alert(checkScore());
    window.location.reload();
  }
});
処理の流れ
  1. 問題を表示する loadQuiz()
  2. 答えを選択して回答するボタンをクリック submitBtn.addEventListener()
  3. 回答を取得する getAnswered()
  4. 正誤判定をして結果を表示する showResults()
  5. 次の問題へ進むボタンを押す nextQuizBtn.addEventListener()
  6. 問題が残っていればそれを読み込み、表示する loadQuiz() showQuiz()
  7. すべての問題に回答していれば結果を判定して表示する alert(checkScore())
  8. 最初の問題に戻る window.location.reload()

style.css
@import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro&display=swap');

* {
  box-sizing: border-box;
}

body {
  background-color: #b8c6db;
  background-image: linear-gradient(315deg, #b8c6db 0%, #f5f7fa 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Source Sans Pro', sans-serif;
  margin: 0;
  min-height: 100vh;
}

#quiz-container {
  background-color: white;
  border-radius: 10px;
  box-shadow: 0 0 10px 2px rgba(100, 100, 100, 0.1);
  overflow: hidden;
  width: 600px;
  max-width: 100%;
  display: unset;
}

#quiz-header {
  padding: 4rem;
}

h2 {
  margin: 0;
}

ul {
  list-style-type: none;
  padding: 0;
}

ul li {
  font-size: 1.2rem;
  margin: 1rem 0;
}

ul li input {
  cursor: pointer;
}

ul li label {
  cursor: pointer;
}

button {
  background-color: #304dec;
  border: none;
  color: white;
  cursor: pointer;
  display: block;
  font-family: inherit;
  font-size: 1.1rem;
  width: 100%;
  padding: 1.3rem;
}

button:hover {
  background-color: #233bc4;
}

#results-container {
  display: none;
  align-items: center;
}

#results-header {
  text-align: center;
  justify-content: center;
}

#results {
  padding: 2rem 0;
}

今回の学び

クイズデータの表現方法と、その呼び出し方に触れることができたのが1番の学びでした。配列とオブジェクトを組み合わせるのは楽しかったです。データ構造に関してもっと勉強したくなりました!

今後の課題

課題は処理の切り出し方だと思いました。開発を進めていくにつれ、必要な処理が増えていきますがそれをどう分割すればいいのかまだわかっていません。油断していると1つの処理の中にすべて書いてしまいそうになります。

それと変数や関数などの名前が分かりにくいですね。もっと他の方のコードや書籍を読んで勉強します!


読んでいただきありがとうございました!フィードバックしていただけたらとても嬉しいです!

参考

My Link

Github
https://github.com/cordelia-sixth

Products
https://raindrop.io/cordelia/my-products-18715918

Qiita
https://qiita.com/cordelia

Twitter
https://twitter.com/cordelia_sixth

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?