ことばさがし

katayamawp




コード公開

        
        



CSS

section.wrapper { font-family: "Comic Sans MS", "Comic Sans", cursive, sans-serif; max-width: 900px; /* PC幅対応に広げる */ margin: 30px auto; padding: 40px 50px; /* 横の余白を多めに */ text-align: center; background: linear-gradient(135deg, #87ceeb, #3b5998); color: #fff; user-select: none; border-radius: 12px; box-shadow: 0 0 40px rgba(0, 0, 0, 0.5); min-height: 100vh; /* 縦の余白確保 */ box-sizing: border-box; } .word { font-size: 3rem; /* 少し大きく */ letter-spacing: 0.7em; margin-bottom: 10px; /* 風船を近くにするため */ text-shadow: 1px 1px 6px #000a; } /* 風船はwordDisplayのすぐ下に配置 */ .balloons { margin: 10px 0 30px 0; /* 上を狭く、下を広く */ text-align: center; } .balloon { display: inline-block; font-size: 3.5rem; /* さらに大きく */ margin: 0 10px; color: #ff3366; user-select: none; transition: opacity 0.3s ease; animation: float 3s ease-in-out infinite; filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.4)); vertical-align: middle; } .balloon:nth-child(odd) { animation-duration: 3.5s; } .balloon.burst { opacity: 0.3; text-decoration: line-through; animation: none; color: #888888; filter: none; } /* 文字ボタンは横並びいっぱい使う */ .letters { margin: 20px 0; max-width: 100%; display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; } button.letter-btn { flex: 1 1 50px; /* 幅50px以上で伸縮 */ max-width: 60px; margin: 5px; padding: 14px 0; font-size: 1.5rem; cursor: pointer; border-radius: 8px; border: none; background: linear-gradient(145deg, #ffcc66, #ffb347); box-shadow: 0 5px #c68e17; transition: all 0.2s ease; color: #442a00; font-weight: bold; user-select: none; } button.letter-btn:hover:not(:disabled) { background: linear-gradient(145deg, #ffd977, #ffc866); box-shadow: 0 7px #db9e3a; transform: translateY(-3px); } button.letter-btn:active:not(:disabled) { box-shadow: 0 2px #a5700d; transform: translateY(1px); } button.letter-btn:disabled { background: #555555; box-shadow: none; cursor: default; color: #ccc; } .message { font-weight: bold; margin-top: 40px; font-size: 1.8rem; color: #ffe066; text-shadow: 1px 1px 5px #0008; user-select: none; } .difficulty { margin-bottom: 25px; font-size: 1.3rem; color: #ffe066; text-shadow: 1px 1px 3px #000a; user-select: none; } input[type="radio"] { transform: scale(1.3); margin-right: 6px; cursor: pointer; } @keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-15px); } }

JS

document.addEventListener("DOMContentLoaded", function() { // 難易度別単語リスト(文字数を考慮して分ける) const wordListByDifficulty = { easy: [ "りんご", "さかな", "うみべ", "はなび", "すいか", "とけい", "くつした" ], medium: [ "さくらんぼ", "にほんご", "おちゃわん", "がっこう", "しゃしん", "ぴあの", "やまのぼり" ], hard: [ "てんきよほう", "たいよう", "つきみ", "やきゅう", "ちず", "かばん", "みずうみ" ] }; // ひらがな+濁点・半濁点も含めた候補文字 const hiragana = [ "あ", "い", "う", "え", "お", "か", "き", "く", "け", "こ", "さ", "し", "す", "せ", "そ", "た", "ち", "つ", "て", "と", "な", "に", "ぬ", "ね", "の", "は", "ひ", "ふ", "へ", "ほ", "ま", "み", "む", "め", "も", "や", "ゆ", "よ", "ら", "り", "る", "れ", "ろ", "わ", "を", "ん", "が", "ぎ", "ぐ", "げ", "ご", "ざ", "じ", "ず", "ぜ", "ぞ", "だ", "ぢ", "づ", "で", "ど", "ば", "び", "ぶ", "べ", "ぼ", "ぱ", "ぴ", "ぷ", "ぺ", "ぽ" ]; // 難易度ごとの設定 const difficultySettings = { easy: { disableCount: 20, // かんたんは20文字無効化(選べない) balloonMultiplier: 3 // 風船の数は文字数×3 }, medium: { disableCount: 15, balloonMultiplier: 2 // 文字数×2 }, hard: { disableCount: 10, balloonMultiplier: 2 } }; // ゲーム状態 let word = ""; let maxBalloons = 0; let foundLetters = new Set(); let missed = 0; // 要素取得 const wordDisplay = document.getElementById("wordDisplay"); const lettersContainer = document.getElementById("lettersContainer"); const balloonsContainer = document.getElementById("balloonsContainer"); const message = document.getElementById("message"); const startBtn = document.getElementById("startBtn"); // 風船を描く function drawBalloons() { balloonsContainer.innerHTML = ""; for (let i = 0; i < maxBalloons; i++) { const span = document.createElement("span"); span.className = "balloon"; span.textContent = "🎈"; if (i < missed) { span.classList.add("burst"); span.textContent = "💥"; } balloonsContainer.appendChild(span); } } // 単語の表示(隠された文字は■) function drawWord() { let display = ""; for (let char of word) { if (foundLetters.has(char)) { display += char + " "; } else { display += "■ "; } } wordDisplay.textContent = display.trim(); } // 文字ボタンを作る function createLetterButtons(disableCount) { lettersContainer.innerHTML = ""; // まず、無効化候補を決める // → 単語に含まれない文字の中からdisableCount個をランダム選択 const charsNotInWord = hiragana.filter(c => !word.includes(c)); shuffleArray(charsNotInWord); const disabledLetters = charsNotInWord.slice(0, disableCount); for (let char of hiragana) { const btn = document.createElement("button"); btn.textContent = char; btn.className = "letter-btn"; // 単語に含まれていない && ランダムに選ばれた無効化文字ならdisabled if (disabledLetters.includes(char)) { btn.disabled = true; } btn.addEventListener("click", () => { if (missed >= maxBalloons) return; // ゲーム終了 btn.disabled = true; if (word.includes(char)) { foundLetters.add(char); drawWord(); checkWin(); } else { missed++; drawBalloons(); checkLose(); } }); lettersContainer.appendChild(btn); } } // 勝利判定 function checkWin() { for (let char of word) { if (!foundLetters.has(char)) return; } message.textContent = "🎉 クリア!おめでとう!"; disableAllButtons(); } // 敗北判定 function checkLose() { if (missed >= maxBalloons) { message.textContent = "💥 風船が全部割れました。ゲームオーバー!"; revealWord(); disableAllButtons(); } } // 全文字を見せる function revealWord() { let reveal = ""; for (let char of word) { reveal += char + " "; } wordDisplay.textContent = reveal.trim(); } // すべてのボタンを無効化 function disableAllButtons() { const btns = lettersContainer.querySelectorAll("button"); btns.forEach(btn => btn.disabled = true); } // 配列をシャッフル(Fisher–Yatesアルゴリズム) function shuffleArray(arr) { for (let i = arr.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [arr[i], arr[j]] = [arr[j], arr[i]]; } } // 難易度に応じて単語を選ぶ function chooseWord(difficulty) { const candidates = wordListByDifficulty[difficulty] || []; if (candidates.length === 0) { // 万一空なら全体からランダム選択 const allWords = [].concat(...Object.values(wordListByDifficulty)); return allWords[Math.floor(Math.random() * allWords.length)]; } return candidates[Math.floor(Math.random() * candidates.length)]; } // ゲーム初期化 function initGame() { foundLetters.clear(); missed = 0; message.textContent = ""; wordDisplay.textContent = ""; balloonsContainer.textContent = ""; lettersContainer.textContent = ""; const difficulty = document.querySelector('input[name="difficulty"]:checked').value; word = chooseWord(difficulty); maxBalloons = word.length * difficultySettings[difficulty].balloonMultiplier; drawWord(); createLetterButtons(difficultySettings[difficulty].disableCount); drawBalloons(); } startBtn.addEventListener("click", initGame); });
記事URLをコピーしました