【ゲーム】JavaScript:21 都道府県クイズ

 「都道府県クイズ」は、名産品や名所、文化を表す絵文字の組み合わせから、対応する都道府県を4択で当てる知識クイズゲームです。全30件のデータからランダムに5問を出題し、正答率を競います。

遊び方・操作方法

  • スタート:タイトル画面の「▶️ スタート」ボタンをクリック
  • 問題:画面中央に絵文字列が表示される
  • 選択:4つの都道府県ボタンから正しいものをクリック
  • フィードバック:「✅ 正解!」または「❌ 不正解… 正解は『〇〇』です。」と表示
  • 次へ:フィードバック後に表示される「➡️ 次へ」ボタンをクリック
  • 結果:5問回答後、正答率(%)を表示
  • タイトルに戻る:結果画面の「🔄 タイトルへ戻る」ボタンをクリックすると再挑戦可

ルール

  1. 全30件の都道府県データをシャッフルし、先頭5問を出題
  2. 各問題につき一度だけ回答可能
  3. 回答後に正誤フィードバックと「次へ」ボタンが表示
  4. 5問終了後、正答率を計算し結果画面に表示
  5. 再挑戦は結果画面からタイトルに戻って再スタート

🎮ゲームプレイ

以下のリンク先から実際にプレイできます。

21 都道府県クイズ

素材のダウンロード

以下のリンクから使用する素材をダウンロードできます。

prefecture_quiz_title.pngprefecture_quiz_bg.png

ゲーム画面イメージ

プログラム全体(prefecture_quiz.html)

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>🌸 都道府県クイズ 🗾</title>
  <style>
    /* ===== 全体リセット ===== */
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    /* ===== 背景設定 ===== */
    body {
      font-family: 'Arial', sans-serif;       /* フォント指定 */
      background: url('prefecture_quiz_bg.png') no-repeat center center fixed;
      background-size: cover;                 /* 背景画像を全面に */
      display: flex;
      justify-content: center;                /* 水平方向中央寄せ */
      align-items: center;                    /* 垂直方向中央寄せ */
      height: 100vh;                          /* 画面高さいっぱい */
      color: #fff;                            /* 文字色白 */
    }

    /* ===== コンテナ ===== */
    #quiz-container {
      background-color: rgba(0, 0, 0, 0.6);    /* 半透明黒 */
      padding: 2rem;                           /* 内側余白 */
      border-radius: 10px;                     /* 角丸 */
      width: 90%;                              /* 幅90% */
      max-width: 600px;                        /* 最大幅600px */
      text-align: center;                      /* 文字中央揃え */
      box-shadow: 0 4px 12px rgba(0,0,0,0.5);  /* 影 */
    }

    /* ===== テキスト背景付きで視認性向上 ===== */
    .text-bg {
      background-color: rgba(0, 0, 0, 0.7);    /* 文字背景 */
      display: inline-block;
      padding: 0.5rem 1rem;
      border-radius: 5px;
      line-height: 1.4;
      margin-bottom: 1rem;
    }

    /* ===== 画面表示制御 ===== */
    #title-screen, #game-screen, #result-screen {
      display: none;                           /* デフォルト非表示 */
    }
    #title-screen.active,
    #game-screen.active,
    #result-screen.active {
      display: block;                          /* activeクラスで表示 */
    }

    /* ===== タイトル画面の画像 ===== */
    #title-screen img {
      display: block;
      margin: 0 auto 1rem;
      max-width: 80%;
      height: auto;
    }

    /* ===== ボタン共通スタイル ===== */
    button {
      padding: 0.75rem 2rem;
      font-size: 1rem;
      border: none;
      border-radius: 5px;
      cursor: pointer;
      transition: background-color 0.3s ease;
    }
    button:hover {
      opacity: 0.9;
    }

    /* ===== スタート&リターンボタン ===== */
    #start-button,
    #return-button {
      background-color: #32CD32;
      color: #fff;
      display: block;
      margin: 1rem auto 0;
    }

    /* ===== 次へボタン ===== */
    #next-button {
      background-color: #1E90FF;
      color: #fff;
      display: none;
      margin: 1rem auto 0;
    }

    /* ===== 選択肢ボタン ===== */
    #choices-container button {
      width: 100%;
      margin: 0.75rem 0;
      padding: 0.75rem;
      font-size: 1rem;
      background-color: #FFD700;
      color: #000;
    }
    #choices-container button:hover {
      background-color: #FFA500;
    }

    /* ===== 絵文字表示 ===== */
    #emoji-display {
      font-size: 3rem;
      margin: 1.5rem 0;
    }
  </style>
</head>
<body>
  <div id="quiz-container">
    <!-- ===== タイトル画面 ===== -->
    <div id="title-screen" class="active">
      <!-- タイトル画像 -->
      <img src="prefecture_quiz_title.png" alt="都道府県クイズ タイトル画像">
      <!-- タイトルロゴ -->
      <h1 class="text-bg">🌸 都道府県クイズ 🗾</h1>
      <!-- ルール説明 -->
      <p class="text-bg">
        名産品・名所・文化を表す絵文字から<br>
        対応する都道府県を当ててね!
      </p>
      <!-- スタートボタン(ルール説明の下) -->
      <button id="start-button">▶️ スタート</button>
    </div>

    <!-- ===== ゲーム画面 ===== -->
    <div id="game-screen">
      <!-- 問題番号 -->
      <h2 id="question-number" class="text-bg"></h2>
      <!-- 出題文 -->
      <p id="question-text" class="text-bg">下の絵文字列から連想される都道府県を選んでください。</p>
      <!-- 絵文字表示 -->
      <div id="emoji-display" class="text-bg"></div>
      <!-- 選択肢 -->
      <div id="choices-container"></div>
      <!-- フィードバック -->
      <p id="feedback" class="text-bg"></p>
      <!-- 次へボタン(フィードバックの下) -->
      <button id="next-button">➡️ 次へ</button>
    </div>

    <!-- ===== 結果画面 ===== -->
    <div id="result-screen">
      <!-- 正答率 -->
      <p id="result-message" class="text-bg"></p>
      <!-- タイトルへ戻るボタン(正答率の下) -->
      <button id="return-button">🔄 タイトルへ戻る</button>
    </div>
  </div>

  <script>
    // ====================================================================
    // 都道府県データ定義(絵文字列と都道府県名のペア)
    // ====================================================================
    const prefectures = [
      { emoji: '⛄🐄🐟', name: '北海道' },
      { emoji: '🍎',     name: '青森県' },
      { emoji: '🐕❄️',   name: '秋田県' },
      { emoji: '🐮🏞️',   name: '岩手県' },
      { emoji: '🥟🌊',   name: '宮城県' },
      { emoji: '🍒',     name: '山形県' },
      { emoji: '🍑',     name: '福島県' },
      { emoji: '🌰',     name: '茨城県' },
      { emoji: '🍓',     name: '栃木県' },
      { emoji: '🧖‍♀️♨️',name: '群馬県' },
      { emoji: '🛤️🏙️', name: '埼玉県' },
      { emoji: '🛳️🌊', name: '千葉県' },
      { emoji: '🗼🗾🏙️',name: '東京都' },
      { emoji: '⚓🛥️🌆', name: '神奈川県' },
      { emoji: '🍶❄️',   name: '新潟県' },
      { emoji: '🏔️🦐',   name: '富山県' },
      { emoji: '🏯🍵',   name: '石川県' },
      { emoji: '🦖🏞️', name: '福井県' },
      { emoji: '🗻🍇',   name: '山梨県' },
      { emoji: '⛷️🏔️', name: '長野県' },
      { emoji: '🏘️🏔️', name: '岐阜県' },
      { emoji: '🗻🍵',   name: '静岡県' },
      { emoji: '🚅🍤',   name: '愛知県' },
      { emoji: '🐚⛩️', name: '三重県' },
      { emoji: '🦆🌊',   name: '滋賀県' },
      { emoji: '⛩️👘🍵',name: '京都府' },
      { emoji: '🐙🍜🏯', name: '大阪府' },
      { emoji: '⚓🎭',   name: '兵庫県' },
      { emoji: '🦌⛩️', name: '奈良県' },
      { emoji: '🍊⛩️', name: '和歌山県' },
      { emoji: '🐫⛰️', name: '鳥取県' }
    ];

    // ====================================================================
    // クイズ用の変数
    // ====================================================================
    let quizList = [];      // 出題順リスト(5問)
    let currentIndex = 0;   // 現在の問題インデックス
    let correctCount = 0;   // 正解数カウント

    // ====================================================================
    // DOM 要素取得
    // ====================================================================
    const titleScreen   = document.getElementById('title-screen');
    const gameScreen    = document.getElementById('game-screen');
    const resultScreen  = document.getElementById('result-screen');
    const startButton   = document.getElementById('start-button');
    const questionNumEl = document.getElementById('question-number');
    const questionTextEl= document.getElementById('question-text');
    const emojiDisplay  = document.getElementById('emoji-display');
    const choicesEl     = document.getElementById('choices-container');
    const feedbackEl    = document.getElementById('feedback');
    const nextButton    = document.getElementById('next-button');
    const resultMsgEl   = document.getElementById('result-message');
    const returnButton  = document.getElementById('return-button');

    // ====================================================================
    // 配列をシャッフルする関数 (Fisher–Yates アルゴリズム)
    // ====================================================================
    function shuffle(array) {
      for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
      }
    }

    // ====================================================================
    // ゲーム開始処理
    // ====================================================================
    function startGame() {
      // 都道府県データをシャッフルし、先頭5件を出題リストに
      quizList = [...prefectures];
      shuffle(quizList);
      quizList = quizList.slice(0, 5);

      // カウンタ初期化
      currentIndex = 0;
      correctCount = 0;

      // 画面切り替え:タイトル画面を非表示、ゲーム画面を表示
      titleScreen.classList.remove('active');
      resultScreen.classList.remove('active');
      gameScreen.classList.add('active');

      // 第1問を表示
      showQuestion();
    }

    // ====================================================================
    // 問題表示処理
    // ====================================================================
    function showQuestion() {
      // 現在の問題データ取得
      const { emoji, name } = quizList[currentIndex];

      // 問題番号表示
      questionNumEl.textContent = `問題 ${currentIndex + 1} / 5`;

      // 出題文設定
      questionTextEl.textContent = '下の絵文字列から連想される都道府県を選んでください。';

      // 絵文字表示
      emojiDisplay.textContent = emoji;

      // 選択肢生成:正解+ランダム3件の不正解
      const choices = [name];
      const others = prefectures.filter(p => p.name !== name);
      shuffle(others);
      for (let i = 0; i < 3; i++) {
        choices.push(others[i].name);
      }
      shuffle(choices);

      // ボタンクリア&生成
      choicesEl.innerHTML = '';
      choices.forEach(choice => {
        const btn = document.createElement('button');
        btn.textContent = choice;
        btn.addEventListener('click', () => selectAnswer(choice, name));
        choicesEl.appendChild(btn);
      });

      // フィードバック&次へボタンリセット
      feedbackEl.textContent = '';
      nextButton.style.display = 'none';
    }

    // ====================================================================
    // 回答選択時処理
    // ====================================================================
    function selectAnswer(selected, correct) {
      if (selected === correct) {
        feedbackEl.textContent = '✅ 正解!';
        correctCount++;   // 正解数カウントアップ
      } else {
        feedbackEl.textContent = `❌ 不正解… 正解は「${correct}」です。`;
      }
      // 次へボタン表示
      nextButton.style.display = 'block';
    }

    // ====================================================================
    // 次の問題 or 終了判定
    // ====================================================================
    function nextQuestion() {
      currentIndex++;
      if (currentIndex < quizList.length) {
        showQuestion();  // 次の問題表示
      } else {
        endGame();       // 全問終了 → 結果表示
      }
    }

    // ====================================================================
    // 終了処理:結果画面表示
    // ====================================================================
    function endGame() {
      gameScreen.classList.remove('active');
      resultScreen.classList.add('active');
      // 正答率計算&表示
      const rate = Math.round((correctCount / quizList.length) * 100);
      resultMsgEl.textContent = `🎉 正答率は ${rate}% です!`;
    }

    // ====================================================================
    // イベントリスナー登録
    // ====================================================================
    startButton.addEventListener('click', startGame);
    nextButton.addEventListener('click', nextQuestion);
    returnButton.addEventListener('click', () => {
      // タイトル画面へ戻る
      resultScreen.classList.remove('active');
      titleScreen.classList.add('active');
    });
  </script>
</body>
</html>

アルゴリズムの流れ

ステップ処理内容主な関数・命令
1. データシャッフルprefectures 配列をシャッフルし、先頭5件を quizList に抽出shuffle()slice(0,5)
2. 問題表示問題番号・絵文字・選択肢(正解+ランダム3つ)を画面描画showQuestion()
3. 回答判定選択したボタンのテキストと正解名を比較し、フィードバックselectAnswer()
4. 次へ or 終了判定currentIndex をインクリメントし、次問表示 or endGame()nextQuestion()
5. 結果表示正答率を計算し、結果画面に表示endGame()

関数の詳しい解説

関数名説明
shuffle(array)Fisher–Yates アルゴリズムで配列要素をランダムに並び替える
startGame()クイズリストの初期化・カウンタリセット・画面切り替え・第1問表示
showQuestion()quizList[currentIndex] から絵文字と正解を取得し、選択肢を生成してボタン設置、UIをリセット
selectAnswer()プレイヤーの選択と正解を比較、フィードバック表示+正解数カウント
nextQuestion()問題インデックスを進め、showQuestion() または endGame() を呼び出す
endGame()ゲーム画面を閉じ、正答率を計算して結果画面に反映

改造のポイント

  • 出題数/社択数変更quizList = quizList.slice(0,5) の数字を変え、問題数を増減。選択肢の数もランダム抽出ループの回数を変更して調整。
  • 絵文字→画像切り替え:絵文字表示部を <img> タグに変更し、県の写真やアイコンを使った出題に。
  • タイマー導入:各問題に制限時間を設け、時間切れで不正解扱いにすることで緊張感アップ。
  • スコアボード機能localStorage に記録した最高正答率を表示するランキング画面を追加。
  • 多言語対応:英語名や他言語名を併記して、学習ツールとしても活用。

アドバイス:出題データを外部JSONに分離し、運営側で簡単に編集・追加できる構成にするとメンテナンス性が向上します。また、スマホでのプレイを考慮してレスポンシブ対応やタッチ操作を強化すると、ユーザー体験がさらに良くなります。