2025年4月16日水曜日

漢字と読みのペアを当てるゲーム

 はい、HTMLとJavaScriptを使って、ご要望の漢字と読みのペアを当てるゲームを作成します。以下にコードと解説を示します。

HTML (index.html):

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>
        body {
            font-family: sans-serif;
        }
        table {
            border-collapse: collapse;
            margin-bottom: 20px;
        }
        th, td {
            border: 1px solid #ccc;
            padding: 10px;
            text-align: center;
            font-size: 1.5em;
            cursor: pointer;
            opacity: 1;
            transition: opacity 0.5s ease-in-out;
        }
        .faded-out {
            opacity: 0.3;
            pointer-events: none;
        }
        #message {
            margin-bottom: 10px;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <h1>漢字と読みのペア当てゲーム</h1>
    <div id="message"></div>
    <table id="gameTable">
        </table>
    <div id="timer">時間: 0秒</div>

    <script>
        const gameTable = document.getElementById('gameTable');
        const messageDiv = document.getElementById('message');
        const timerDiv = document.getElementById('timer');

        const kanjiReadings = [
            { kanji: '漢字', reading: 'かんじ' },
            { kanji: '簡単', reading: 'かんたん' },
            { kanji: '勉強', reading: 'べんきょう' },
            { kanji: '理解', reading: 'りかい' },
            { kanji: '挑戦', reading: 'ちょうせん' }
        ];

        let firstClickedCell = null;
        let startTime = null;
        let timerInterval;
        let matchedPairs = 0;

        function shuffleArray(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 formatTime(milliseconds) {
            const seconds = Math.floor(milliseconds / 1000);
            return `${seconds}秒`;
        }

        function updateTimer() {
            const currentTime = new Date().getTime();
            const elapsedTime = currentTime - startTime;
            timerDiv.textContent = `時間: ${formatTime(elapsedTime)}`;
        }

        function createTable() {
            const shuffledPairs = [...kanjiReadings];
            shuffleArray(shuffledPairs);

            const tableBody = document.createElement('tbody');
            for (let i = 0; i < 5; i++) {
                const rowData = [
                    { type: 'kanji', value: shuffledPairs[i].kanji, pairIndex: i },
                    { type: 'reading', value: shuffledPairs[i].reading, pairIndex: i }
                ];
                shuffleArray(rowData); // 各行内で漢字と読みの配置をランダムにする

                const row = document.createElement('tr');
                for (let j = 0; j < 2; j++) {
                    const cell = document.createElement('td');
                    cell.textContent = rowData[j].value;
                    cell.dataset.type = rowData[j].type;
                    cell.dataset.pairIndex = rowData[j].pairIndex;
                    cell.addEventListener('click', handleCellClick);
                    row.appendChild(cell);
                }
                tableBody.appendChild(row);
            }
            gameTable.appendChild(tableBody);
        }

        function handleCellClick(event) {
            const clickedCell = event.target;

            if (clickedCell.classList.contains('faded-out')) {
                return;
            }

            if (!startTime) {
                startTime = new Date().getTime();
                timerInterval = setInterval(updateTimer, 1000);
            }

            if (!firstClickedCell) {
                firstClickedCell = clickedCell;
                firstClickedCell.classList.add('selected'); // 選択されたことを示す視覚的なフィードバック
            } else if (firstClickedCell !== clickedCell) {
                const firstType = firstClickedCell.dataset.type;
                const firstPairIndex = firstClickedCell.dataset.pairIndex;
                const secondType = clickedCell.dataset.type;
                const secondPairIndex = clickedCell.dataset.pairIndex;

                firstClickedCell.classList.remove('selected');

                if (firstType !== secondType && firstPairIndex === secondPairIndex) {
                    // 正しいペア
                    firstClickedCell.classList.add('faded-out');
                    clickedCell.classList.add('faded-out');
                    matchedPairs++;
                    messageDiv.textContent = '';
                    if (matchedPairs === kanjiReadings.length) {
                        clearInterval(timerInterval);
                        const endTime = new Date().getTime();
                        const totalTime = endTime - startTime;
                        messageDiv.textContent = `クリア! タイム: ${formatTime(totalTime)}`;
                    }
                } else {
                    // 間違ったペア
                    messageDiv.textContent = '違います!';
                    // 少し遅れてメッセージを消す
                    setTimeout(() => {
                        messageDiv.textContent = '';
                    }, 1000);
                }
                firstClickedCell = null;
            }
        }

        // ゲームの初期化
        createTable();
    </script>
</body>
</html>

JavaScript コードの解説:

  1. kanjiReadings 配列: 漢字とその読みのペアをオブジェクトとして格納した配列です。
  2. 変数:
    • firstClickedCell: 最初にクリックされたセルを保持します。
    • startTime: ゲーム開始時のタイムスタンプを保持します。
    • timerInterval: タイマーを更新するためのインターバルIDを保持します。
    • matchedPairs: 正しくマッチしたペアの数をカウントします。
  3. shuffleArray(array) 関数: 配列の要素をシャッフルする関数です。
  4. formatTime(milliseconds) 関数: ミリ秒を「X秒」という形式にフォーマットする関数です。
  5. updateTimer() 関数: 経過時間を計算し、タイマー表示を更新する関数です。
  6. createTable() 関数:
    • kanjiReadings をシャッフルします。
    • <table> 要素の中に <tbody> 要素を作成します。
    • 5行のテーブルを作成し、各行に漢字と読みをランダムに配置します。
    • 各セルには、どのタイプの情報(漢字または読み)かを示す data-type 属性と、どのペアに属するかを示す data-pair-index 属性を設定します。
    • 各セルにクリックイベントリスナー (handleCellClick) を追加します。
    • 作成した <tbody> をテーブルに追加します。
  7. handleCellClick(event) 関数:
    • クリックされたセルを取得します。
    • すでにフェードアウトしているセルは無視します。
    • 最初のクリックの場合、クリックされたセルを firstClickedCell に保存し、タイマーを開始します。
    • 2回目のクリックの場合:
      • 最初にクリックされたセルと今回クリックされたセルが同じでないことを確認します。
      • data-typedata-pair-index を比較して、正しいペアかどうかを判定します。
      • 正しいペアの場合、両方のセルに faded-out クラスを追加してフェードアウトさせ、matchedPairs をインクリメントします。すべてのペアがマッチしたら、タイマーを停止し、クリアメッセージと時間を表示します。
      • 間違ったペアの場合、「違います!」というメッセージを表示し、少し遅れてメッセージを消します。
      • firstClickedCellnull にリセットします。
  8. ゲームの初期化: ページの読み込み時に createTable() 関数を呼び出してゲームを開始します。

使い方:

  1. 上記の HTML コードを index.html という名前のファイルに保存します。
  2. 保存した index.html ファイルをブラウザで開きます。
  3. テーブル内の漢字と読みのペアをマウスでクリックして選択します。
  4. 正しいペアをクリックすると、そのペアの文字が薄くなります。
  5. 間違ったペアをクリックすると、「違います!」というメッセージが表示されます。
  6. すべてのペアを正しくクリックすると、「クリア!」というメッセージと共に操作時間が表示されます。

改善点:

  • CSS アニメーションの調整: フェードアウトの速度やイージングを調整できます。
  • 視覚的なフィードバック: セルがクリックされたときに、選択状態を示すようなスタイル(例: 枠線の変更)を追加すると、より分かりやすくなります。
  • 難易度調整: kanjiReadings 配列の要素数を増やすことで、ゲームの難易度を上げることができます。
  • リプレイ機能: ゲーム終了後に、もう一度プレイするためのボタンを追加できます。
  • デザインの改善: CSS を使用して、テーブルやメッセージのスタイルをより魅力的にすることができます。

0 件のコメント:

コメントを投稿