【ゲーム】JavaScript:02 歴史クイズ

 「📜 歴史クイズゲーム 🏛️」は、日本史・世界史からランダムに出題される10~20問の選択式クイズにチャレンジし、正解率を競うミニゲームです。問題文と4つの選択肢が表示され、正しい答えをクリックすると「正解」「不正解」を判定。すべての問題に回答し終えると、正解率(%)と正答数が表示されます。

遊び方

 ページを開くと最初の問題が表示されます。問題文の下に並ぶボタンから自分が正しいと思う選択肢をクリックしてください。回答後、結果が表示され「次の問題 ➡️」ボタンが出現するので、クリックして次へ進みます。最後の問題に回答し終わると、正解率と正答数がまとめて表示されます。

ルール

  • 各問題に対し一度だけ回答可能。
  • 正解すると「✅ 正解!」が、不正解だと「❌ 不正解… 正解は『~』」とフィードバックが出ます。
  • 回答後は次の問題に進むまで選択肢を変更できません。
  • 全問終了後、正解率(小数点第一位)と「正解数/総問題数」が表示されます。

🎮ゲームプレイ

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

02 歴史クイズ

素材のダウンロード

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

history_quiz_bg.png

ゲーム画面イメージ

プログラム全文(history_quiz.html)

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>📜 歴史クイズゲーム 🏰</title>
    <style>
        /* 全体リセット */
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            font-family: 'Arial', sans-serif;
            background-color: #f4f4f9;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            text-align: center;
            background-image: url('history_quiz_bg.png');
            background-size: cover;
            background-position: center;
            color: #fff;
        }
        /* クイズコンテナ */
        #quiz-container {
            background-color: rgba(0, 0, 0, 0.75);
            padding: 30px;
            border-radius: 10px;
            width: 90%;
            max-width: 600px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.3);
        }
        /* タイトル */
        h1 {
            font-size: 2.2rem;
            color: #FFD700;
            margin-bottom: 20px;
        }
        /* 問題文 */
        #question-container {
            font-size: 1.4rem;
            color: #FFD;
            margin-bottom: 20px;
            line-height: 1.4;
        }
        /* 選択肢ボタン */
        #answers-container {
            display: flex;
            flex-direction: column;
            gap: 12px;
            margin-bottom: 20px;
        }
        #answers-container button {
            padding: 12px;
            font-size: 1.1rem;
            border: none;
            border-radius: 5px;
            background-color: #1E90FF;
            color: #fff;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }
        #answers-container button:hover { background-color: #104E8B; }
        /* 結果表示 */
        #result {
            font-size: 1.2rem;
            font-weight: bold;
            margin-bottom: 20px;
        }
        /* 次へボタン */
        #next-button {
            padding: 10px 24px;
            font-size: 1rem;
            border: none;
            border-radius: 5px;
            background-color: #32CD32;
            color: #fff;
            cursor: pointer;
            transition: background-color 0.3s ease;
            display: none;
        }
        #next-button:hover { background-color: #228B22; }
    </style>
</head>
<body>
    <div id="quiz-container">
        <!-- タイトル見出し -->
        <h1>📜 歴史クイズゲーム 🏛️</h1>
        <!-- 問題表示領域 -->
        <div id="question-container"></div>
        <!-- 回答ボタン領域 -->
        <div id="answers-container"></div>
        <!-- 次の問題ボタン -->
        <button id="next-button" onclick="nextQuestion()">次の問題 ➡️</button>
        <!-- 結果表示 -->
        <p id="result"></p>
    </div>

    <script>
        /****************************************************/
        /*                  クイズデータ定義                */
        /****************************************************/
        const quizData = [
            // 日本史の問題
            { question: "織田信長が桶狭間の戦いで今川義元を破った年は?", answers: ["1560年","1575年","1582年","1550年"], correct: 0 },
            { question: "江戸幕府を開いたのは誰?", answers: ["徳川家康","豊臣秀吉","織田信長","足利義満"], correct: 0 },
            { question: "大化の改新が行われたのは西暦何年?", answers: ["593年","645年","701年","710年"], correct: 1 },
            { question: "奈良時代の都であったのはどこ?", answers: ["平城京","平安京","長安","大津京"], correct: 0 },
            { question: "明治維新が正式に始まった年は?", answers: ["1868年","1871年","1853年","1889年"], correct: 0 },
            { question: "第二次世界大戦で日本が降伏した年は?", answers: ["1944年","1945年","1946年","1947年"], correct: 1 },
            { question: "大坂の役で豊臣氏が滅亡したのは何年?", answers: ["1614年","1603年","1615年","1598年"], correct: 2 },
            { question: "平安時代の初期に成立した日本最古の歴史書は?", answers: ["日本書紀","古事記","続日本紀","万葉集"], correct: 1 },
            { question: "鎌倉幕府の征夷大将軍初代は?", answers: ["源頼朝","源義経","北条時政","源義家"], correct: 0 },
            { question: "秀吉が朝鮮出兵したのは何という戦役?", answers: ["文禄・慶長の役","応仁の乱","壬申の乱","太平洋戦争"], correct: 0 },
            // 世界史の問題を10問追加
            { question: "古代エジプト文明の中心に位置した都市は?", answers: ["メンフィス","カルナック","テーベ","アレクサンドリア"], correct: 0 },
            { question: "ローマ帝国が西ローマと東ローマに分裂したのは何年?", answers: ["395年","410年","476年","330年"], correct: 0 },
            { question: "フランス革命が勃発した年は?", answers: ["1789年","1776年","1815年","1799年"], correct: 0 },
            { question: "ナポレオンがワーテルローで敗北した年は?", answers: ["1812年","1815年","1821年","1804年"], correct: 1 },
            { question: "ベルリンの壁が崩壊したのは何年?", answers: ["1987年","1989年","1991年","1985年"], correct: 1 },
            { question: "第一次世界大戦が始まった年は?", answers: ["1914年","1918年","1939年","1905年"], correct: 0 },
            { question: "第二次世界大戦が始まった年は?", answers: ["1939年","1941年","1945年","1933年"], correct: 0 },
            { question: "キューバ危機が起こった年は?", answers: ["1962年","1956年","1968年","1973年"], correct: 0 },
            { question: "オスマン帝国が解体されたのは何年?", answers: ["1918年","1923年","1919年","1920年"], correct: 1 },
            { question: "中国の文化大革命が始まった年は?", answers: ["1966年","1958年","1976年","1962年"], correct: 0 }
        ];

        let currentQuestionIndex = 0;
        let correctAnswers = 0;

        /****************************************************/
        /*                問題表示関数                    */
        /****************************************************/
        function displayQuestion() {
            const q = quizData[currentQuestionIndex];
            document.getElementById("question-container").textContent = `❓ ${q.question}`;
            const container = document.getElementById("answers-container");
            container.innerHTML = "";
            q.answers.forEach((ans, idx) => {
                const btn = document.createElement("button");
                btn.textContent = ans;
                btn.addEventListener("click", () => checkAnswer(idx));
                container.appendChild(btn);
            });
            document.getElementById("result").textContent = "";
            document.getElementById("next-button").style.display = "none";
        }

        /****************************************************/
        /*                回答チェック関数                  */
        /****************************************************/
        function checkAnswer(selected) {
            const resEl = document.getElementById("result");
            const correctIdx = quizData[currentQuestionIndex].correct;
            if (selected === correctIdx) {
                resEl.textContent = "✅ 正解!";
                resEl.style.color = "#2ecc71";
                correctAnswers++;
            } else {
                resEl.textContent = `❌ 不正解… 正解は「${quizData[currentQuestionIndex].answers[correctIdx]}」`;
                resEl.style.color = "#e74c3c";
            }
            document.getElementById("next-button").style.display = "inline-block";
        }

        /****************************************************/
        /*                次の問題へ移動                   */
        /****************************************************/
        function nextQuestion() {
            currentQuestionIndex++;
            if (currentQuestionIndex >= quizData.length) {
                displayFinalResult();
            } else {
                displayQuestion();
            }
        }

        /****************************************************/
        /*              最終結果表示関数                   */
        /****************************************************/
        function displayFinalResult() {
            document.getElementById("question-container").textContent = "🏁 クイズ終了!";
            document.getElementById("answers-container").innerHTML = "";
            const rate = ((correctAnswers / quizData.length) * 100).toFixed(1);
            const resEl = document.getElementById("result");
            resEl.textContent = `🎉 正解率: ${rate}% (${correctAnswers} / ${quizData.length})`;
            resEl.style.color = "#FFD700";
            document.getElementById("next-button").style.display = "none";
        }

        // 初回表示
        displayQuestion();
    </script>
</body>
</html>

アルゴリズムの流れ

ステップ処理内容
1. 初回表示ページ読み込み時に displayQuestion() を呼び出し、最初の問題を表示
2. 問題表示displayQuestion() で問題文をセットし、選択肢ボタンを動的生成
3. 回答受付・判定選択肢ボタンクリックで checkAnswer(idx) → 正誤チェック・スコア更新 → 結果表示
4. 次へ移動「次の問題」ボタンで nextQuestion() → インデックス増加 → 問題表示 or 最終結果表示
5. 最終結果表示displayFinalResult() で正解率と正答数を計算・表示

主要な組み込み命令・メソッド

命令/メソッド説明
document.createElement新しい DOM 要素(button)を生成
element.addEventListenerユーザーのクリックイベントを監視・ハンドリング
element.appendChild親要素に子要素を追加
textContent要素内のテキストを安全に更新
innerHTML要素内の HTML を一度に置き換え
Array.forEach配列の各要素を順に処理
toFixed(1)数値を小数点以下1桁で文字列化

関数の詳細

関数名機能・処理内容
displayQuestion()現在の問題(quizData[currentQuestionIndex])を画面に描画し、回答ボタンを動的に生成。結果表示欄と「次へ」ボタンをリセット。
checkAnswer(idx)ユーザーが選んだ選択肢 idx と正解インデックスを比較。正誤メッセージを更新し、正解数をカウントアップ。次への遷移ボタンを表示。
nextQuestion()問題インデックスをインクリメントし、残問があれば displayQuestion()、なければ displayFinalResult() を呼び出し。
displayFinalResult()全問終了後に問題文・選択肢をクリアし、正解率と正答数を計算して最終結果を表示。次へボタンを非表示。

改造のポイント

  • 問題追加・カテゴリ分け
    quizData に任意のジャンル・出題を追加したり、ジャンルごとにフィルターを実装。
  • 制限時間の導入
    各問題にタイマーを設け、setInterval で残り時間をカウントダウンし、時間切れで不正解扱い。
  • 効果音・演出
    正解・不正解時に new Audio('correct.mp3').play() などを追加し臨場感をアップ。
  • ハイスコア保存
    localStorage を使ってベストスコアや正解率を永続化。
  • スマホ・タブレット最適化
    ボタンサイズやフォントサイズ、レイアウトをレスポンシブ対応に。
  • UIカスタマイズ
    正解時にアニメーションやエフェクトを追加、背景画像・配色を変更して雰囲気を一新。

これらのポイントを参考に、自分好みの歴史クイズゲームへ拡張してみてください!