【ゲーム】JavaScript:22 県庁所在地クイズ

 「県庁所在地クイズ」は、名産品や名所、文化をあらわす絵文字の組み合わせから、対応する都道府県の県庁所在地を4択で当てる知識クイズゲームです。30件のデータからランダムに5問出題され、効果音付きで正誤判定、最終的に正答率を表示します。

遊び方・操作方法

  • スタート:タイトル画面の「▶️ スタート」ボタンをクリック
  • 問題表示:絵文字の組み合わせを見て連想
  • 選択:4つの選択肢ボタンから正しい県庁所在地名をクリック
  • フィードバック:正解時は「✅ 正解!」+効果音、
          不正解時は「❌ 不正解… 正解は『○○』です。」+効果音
  • 次へ:フィードバック後に現れる「➡️ 次へ」ボタンをクリック
  • 結果:5問回答後、正答率をパーセントで表示
  • 再挑戦:結果画面の「🔄 タイトルへ戻る」ボタンでタイトル画面へ

ルール

  1. 全30件の県庁所在地データをシャッフルし、先頭5問を出題
  2. 各問題は一度だけ回答可能
  3. 回答後すぐに正誤フィードバックと効果音を再生
  4. 5問回答後に正答率を計算して結果画面に表示
  5. 「タイトルへ戻る」でいつでも再挑戦可

🎮ゲームプレイ

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

22 県庁所在地クイズ

素材のダウンロード

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

効果音:魔王魂

capital1_quiz_title.pngcapital1_quiz_bg.png

ゲーム画面イメージ

プログラム全体(capital1_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('capital1_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%;
      max-width: 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;
      margin-bottom: 1rem;
      line-height: 1.4;
    }

    /* ===== 画面切り替え ===== */
    #title-screen, #game-screen, #result-screen {
      display: none;
    }
    #title-screen.active, #game-screen.active, #result-screen.active {
      display: block;
    }

    /* ===== タイトル画面画像 ===== */
    #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="capital1_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>

  <!-- 効果音 -->
  <audio id="audio-correct" src="maoudamashii-capital1_quiz_correct.mp3"></audio>
  <audio id="audio-incorrect" src="maoudamashii-capital1_quiz_incorrect.mp3"></audio>

  <script>
    // ====================================================
    // 県庁所在地データ:絵文字+県名+首都名
    // ====================================================
    const prefectures = [
      { emoji:'⛄🐄🐟', prefecture:'北海道', capital:'札幌市' },
      { emoji:'🍎',     prefecture:'青森県', capital:'青森市' },
      { emoji:'🐕❄️',   prefecture:'秋田県', capital:'秋田市' },
      { emoji:'🐮🏞️',   prefecture:'岩手県', capital:'盛岡市' },
      { emoji:'🥟🌊',   prefecture:'宮城県', capital:'仙台市' },
      { emoji:'🍒',     prefecture:'山形県', capital:'山形市' },
      { emoji:'🍑',     prefecture:'福島県', capital:'福島市' },
      { emoji:'🌰',     prefecture:'茨城県', capital:'水戸市' },
      { emoji:'🍓',     prefecture:'栃木県', capital:'宇都宮市' },
      { emoji:'🧖‍♀️♨️',prefecture:'群馬県', capital:'前橋市' },
      { emoji:'🛤️🏙️', prefecture:'埼玉県', capital:'さいたま市' },
      { emoji:'🛳️🌊', prefecture:'千葉県', capital:'千葉市' },
      { emoji:'🌆🏙️', prefecture:'東京都', capital:'東京'      },
      { emoji:'⚓🛥️', prefecture:'神奈川県', capital:'横浜市' },
      { emoji:'🍶❄️',   prefecture:'新潟県', capital:'新潟市' },
      { emoji:'🏔️🦐',   prefecture:'富山県', capital:'富山市' },
      { emoji:'🏯🍵',   prefecture:'石川県', capital:'金沢市' },
      { emoji:'🦖🏞️', prefecture:'福井県', capital:'福井市' },
      { emoji:'🗻🍇',   prefecture:'山梨県', capital:'甲府市' },
      { emoji:'⛷️🏔️', prefecture:'長野県', capital:'長野市' },
      { emoji:'🏘️🏔️', prefecture:'岐阜県', capital:'岐阜市' },
      { emoji:'🗻🍵',   prefecture:'静岡県', capital:'静岡市' },
      { emoji:'🚅🍤',   prefecture:'愛知県', capital:'名古屋市' },
      { emoji:'🐚⛩️', prefecture:'三重県', capital:'津市'    },
      { emoji:'🦆🌊',   prefecture:'滋賀県', capital:'大津市'  },
      { emoji:'⛩️👘', prefecture:'京都府', capital:'京都市'  },
      { emoji:'🐙🍜', prefecture:'大阪府', capital:'大阪市'  },
      { emoji:'⚓🎭',   prefecture:'兵庫県', capital:'神戸市'  },
      { emoji:'🦌⛩️', prefecture:'奈良県', capital:'奈良市'  },
      { emoji:'🍊⛩️', prefecture:'和歌山県', capital:'和歌山市'}
    ];

    // ====================================================
    // クイズ管理変数
    // ====================================================
    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');
    const audioCorrect  = document.getElementById('audio-correct');
    const audioIncorrect= document.getElementById('audio-incorrect');

    // ====================================================
    // 配列シャッフル関数 (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, capital } = quizList[currentIndex];

      // 問題番号セット
      questionNumEl.textContent = `問題 ${currentIndex + 1} / 5`;

      // 出題文セット
      questionTextEl.textContent = '下の絵文字列から連想される県庁所在地を選んでください。';

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

      // 選択肢生成:正解 + 他3件
      const choices = [capital];
      const others = prefectures
        .filter(p => p.capital !== capital)
        .map(p => p.capital);
      shuffle(others);
      choices.push(others[0], others[1], others[2]);
      shuffle(choices);

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

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

    // ====================================================
    // 回答選択処理
    // ====================================================
    function selectAnswer(selected, correct) {
      if (selected === correct) {
        // 正解時
        feedbackEl.textContent = '✅ 正解!';
        correctCount++;
        audioCorrect.play();    // 効果音再生
      } else {
        // 不正解時
        feedbackEl.textContent = `❌ 不正解… 正解は「${correct}」です。`;
        audioIncorrect.play();  // 効果音再生
      }
      // 次へボタン表示
      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 を進め、showQuestion() または endGame() を呼出nextQuestion()
5. 正答率計算&結果表示全問終了後、正答率を計算し、結果画面に反映endGame()

関数の詳しい解説

関数名説明
shuffle(array)Fisher–Yates アルゴリズムで配列要素をランダムに並び替える
startGame()クイズリスト初期化、カウンタ0リセット、画面切り替え、第1問表示
showQuestion()現在の出題データから絵文字・選択肢を生成し、ボタン配置、UIリセット
selectAnswer()選択ボタンのテキストと正解を比較、フィードバック表示、効果音再生、次へボタン表示
nextQuestion()問題インデックスを進め、次問表示 or 終了処理を実行
endGame()正答率を計算し結果画面にセット、ゲーム画面を非表示

改造のポイント

  • 出題数変更quizList = quizList.slice(0,5) の数値を変え、問題数を増減可能。
  • 選択肢数変更:他解答の取り出し数(others[0]~others[2])を増やせば5択以上に対応。
  • 画像出題化:絵文字の代わりに県庁所在地の写真や地図を <img> で表示するよう改修。
  • 制限時間導入:各問題にタイマーを設置し、時間切れで自動で不正解扱い。
  • ランキング機能localStorage に正答率やクリアタイムを保存し、ハイスコア画面を追加。
  • 多言語対応:UIテキストを外部JSON化し、多言語版を実現すると学習アプリ化が進む。

アドバイス:効果音やアニメーションをさらに充実させると、学習意欲が高まる演出になります。出題データを外部ファイル化して差し替えや追加がラクになるよう構成しておくと、今後のメンテナンスが簡単になります。