diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..73300d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.superpowers \ No newline at end of file diff --git a/app.js b/app.js index 8e8ce20..fe62bbc 100644 --- a/app.js +++ b/app.js @@ -93,7 +93,7 @@ function sfxComplete() { const APP_VERSION = 2; var state = { sound: true, - bigFont: false, + theme: "ink", difficulty: 1, score: 0, combo: 0, @@ -123,7 +123,7 @@ function saveState() { "chengyu_s", JSON.stringify({ sound: state.sound, - bigFont: state.bigFont, + theme: state.theme, difficulty: state.difficulty, totalCount: state.totalCount, streak: state.streak, @@ -237,7 +237,7 @@ function loadState() { try { var s = JSON.parse(localStorage.getItem("chengyu_s") || "{}"); state.sound = s.sound !== undefined ? s.sound : true; - state.bigFont = s.bigFont || false; + state.theme = s.theme || "ink"; state.totalCount = s.totalCount || 0; state.streak = s.streak || 0; state.checkinDays = s.checkinDays || []; @@ -312,16 +312,15 @@ function pickIdiom() { return item; } var pool = IDIOMS.filter(function (i) { - return i.l <= state.difficulty; + return i.l <= state.difficulty && !state.usedIdiomIndices[i.w]; }); - var a = 0, - idx; - do { - idx = Math.floor(Math.random() * pool.length); - a++; - } while (state.usedIdiomIndices[pool[idx].w] && a < 100); - state.usedIdiomIndices[pool[idx].w] = 1; - return pool[idx]; + if (!pool.length) { + state.usedIdiomIndices = {}; + pool = IDIOMS.filter(function (i) { return i.l <= state.difficulty; }); + } + var item = pool[Math.floor(Math.random() * pool.length)]; + state.usedIdiomIndices[item.w] = 1; + return item; } function generateBlanks(w, d) { var n = d === 1 ? 1 : d === 2 ? 2 : 3; @@ -375,6 +374,11 @@ function renderStats() { document.getElementById("statCombo").textContent = state.combo; document.getElementById("statTotal").textContent = state.totalCount; document.getElementById("statStreak").textContent = state.streak; + var flame = document.getElementById("flameIcon"); + flame.className = ""; + if (state.combo >= 8) flame.className = "flame-high"; + else if (state.combo >= 5) flame.className = "flame-mid"; + else if (state.combo >= 3) flame.className = "flame-low"; } function renderProgress() { var bar = document.getElementById("progressBar"); @@ -455,6 +459,12 @@ function renderCombo() { "学富五车!", "梅子无人能挡!", "登峰造极!", + "出口成章!", + "满腹经纶!", + "博古通今!", + "梅子开挂了!", + "无可匹敌!", + "梅子是成语王!", ]; var i = Math.min(Math.floor((state.combo - 3) / 2), msgs.length - 1); var txt = "🔥 连击 ×" + state.combo + " " + msgs[i]; @@ -477,6 +487,7 @@ function renderCombo() { function startRound() { state.round = 0; state.roundResults = []; + state.usedIdiomIndices = {}; nextQuestion(); } function nextQuestion() { @@ -620,7 +631,19 @@ function showResult(ok, nc) { '">

' + - (ok ? "✅ 回答正确!" : "❌ 答错了~") + + (ok ? [ + "✅ 回答正确!", + "✅ 太棒了!", + "✅ 梅子答对了!", + "✅ 完全正确!", + "✅ 厉害!", + "✅ 对!梅子真棒!", + ][Math.floor(Math.random() * 6)] : [ + "❌ 答错了~", + "❌ 没关系,记住它!", + "❌ 这次没中,下次加油!", + "❌ 差一点点~", + ][Math.floor(Math.random() * 4)]) + (ok && state.combo >= 3 ? " 🔥" : "") + '

' + idiom.w + @@ -642,10 +665,25 @@ function finishRound() { state.reviewMode = false; var msg = c === ROUND_SIZE - ? "满分!梅子太厉害了!🎉" + ? [ + "满分!梅子太厉害了!🎉", + "完美!梅子真是成语达人!✨", + "全对!梅子今天状态绝佳!🌟", + "漂亮!一题不差,梅子威武!👏", + ][Math.floor(Math.random() * 4)] : c >= 3 - ? "梅子表现不错!继续加油~" - : "没关系梅子,多练习就会进步!💪"; + ? [ + "梅子表现不错!继续加油~", + "答得很好,梅子越来越厉害了!", + "不错不错,梅子进步了!🌸", + "梅子答题越来越顺了,加油!", + ][Math.floor(Math.random() * 4)] + : [ + "没关系梅子,多练习就会进步!💪", + "继续努力,梅子肯定能行!", + "不怕不怕,熟能生巧!加油梅子~", + "错了没关系,下次梅子一定更好!", + ][Math.floor(Math.random() * 4)]; var reviewBtn = wasReview && state.wrongBook.length ? '' @@ -743,11 +781,11 @@ function init() { loadState(); loadWrongBook(); renderWbBadge(); - if (state.bigFont) document.body.classList.add("big-font"); + document.documentElement.setAttribute("data-theme", state.theme); document.getElementById("btnSound").classList.toggle("active", state.sound); document.getElementById("btnSound").textContent = state.sound ? "🔊" : "🔇"; - if (state.bigFont) - document.getElementById("btnBigFont").classList.add("active"); + document.getElementById("btnTheme").textContent = state.theme === "ink" ? "🌙" : "☀️"; + showThemeTooltip(); document.querySelectorAll(".diff-btn").forEach(function (b) { b.classList.toggle("active", +b.dataset.diff === state.difficulty); }); @@ -761,10 +799,29 @@ document.getElementById("btnSound").addEventListener("click", function () { this.textContent = state.sound ? "🔊" : "🔇"; saveState(); }); -document.getElementById("btnBigFont").addEventListener("click", function () { - state.bigFont = !state.bigFont; - document.body.classList.toggle("big-font", state.bigFont); - this.classList.toggle("active", state.bigFont); +function showThemeTooltip() { + if (localStorage.getItem("chengyu_theme_tip")) return; + var tip = document.getElementById("themeTooltip"); + if (!tip) return; + setTimeout(function () { + tip.classList.add("show"); + var timer = setTimeout(dismissThemeTooltip, 5000); + tip.addEventListener("click", function () { + clearTimeout(timer); + dismissThemeTooltip(); + }, { once: true }); + }, 1200); +} +function dismissThemeTooltip() { + var tip = document.getElementById("themeTooltip"); + if (tip) tip.classList.remove("show"); + localStorage.setItem("chengyu_theme_tip", "1"); +} +document.getElementById("btnTheme").addEventListener("click", function () { + dismissThemeTooltip(); + state.theme = state.theme === "ink" ? "paper" : "ink"; + document.documentElement.setAttribute("data-theme", state.theme); + this.textContent = state.theme === "ink" ? "🌙" : "☀️"; saveState(); }); document diff --git a/index.html b/index.html index ee05be7..da04a95 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ - + 梅子的成语填字
- +
+ +
+ 新!点我切换白天/夜间模式 ✨ +
+
+
@@ -29,7 +35,7 @@
今日 0
- 🔥 0 连击 + 🔥 0 连击
@@ -65,7 +71,7 @@