无需刷新页面重置JavaScript游戏功能的问题排查
问题修复:重置游戏功能正常运行的解决方案
核心问题分析
- 事件监听重复绑定:每次调用
randomSword()都会给按钮添加新的click事件,导致点击一次触发多次逻辑,出现错误的类添加(比如正确猜测也加fel类)。 - 失败判断逻辑错误:原代码用
correctGuesses !== allaSvärd.length判断失败,但allaSvärd是包含6把剑的数组,当前游戏仅显示3把,应该与当前显示的剑数量(swordImages.length)比较。 - UI重置不完整:重置时未恢复按钮行的初始
osynlig(隐藏)状态,导致重置后按钮直接显示,不符合初始交互逻辑。
修复后的完整JavaScript代码
const eu = "europeiskt"; const jpn = "japanskt"; const fantasy = "fantasi"; function Svärd(typ, bild) { this.typ = typ; this.bild = bild; } let allaSvärd = [ new Svärd(eu, "img/european/1.jpg"), new Svärd(eu, "img/european/2.jpg"), new Svärd(jpn, "img/japanese/1.jpg"), new Svärd(jpn, "img/japanese/2.jpg"), new Svärd(fantasy, "img/fantasy/1.jpg"), new Svärd(fantasy, "img/fantasy/2.jpg"), ]; const wrongAnswerDiv = document.getElementById("felsvar"); const wrongAnswerOkButton = wrongAnswerDiv.querySelector("button.osynlig"); const swordImages = document.querySelectorAll(".svärdbild"); const buttonRows = document.querySelectorAll(".knapprad"); const swordWrappers = document.querySelectorAll(".svärdwrapper"); const congratMessage = document.getElementById("grattis"); const statisticsDiv = document.getElementById("statistik"); let correctGuesses = 0; // 存储当前轮的剑数据,避免作用域问题 let currentSwords = []; // 初始化鼠标悬停事件 for (let i = 0; i < swordWrappers.length; i++) { swordWrappers[i].addEventListener("mouseover", () => buttonRows[i].classList.replace("osynlig", "synlig") ); swordWrappers[i].addEventListener("mouseleave", () => buttonRows[i].classList.replace("synlig", "osynlig") ); } // 按钮点击处理函数,提取为独立函数,避免重复绑定 function handleButtonClick(i, event) { const gissning = event.target.dataset.gissning; const currentSword = currentSwords[i]; if (currentSword.typ === gissning) { swordImages[i].classList.add("rätt"); correctGuesses++; } else { swordImages[i].classList.add("fel"); } buttonRows[i].style.display = "none"; // 判断是否全部猜对 if (correctGuesses === swordImages.length) { congratMessage.classList.remove("osynlig"); } // 判断是否最后一个且未全部猜对 else if (i === swordImages.length - 1) { wrongAnswerDiv.classList.remove("osynlig"); wrongAnswerOkButton.classList.remove("osynlig"); } } function resetGame() { // 重置图片样式 swordImages.forEach((image) => { image.classList.remove("rätt"); image.classList.remove("fel"); }); // 重置猜对计数 correctGuesses = 0; // 重置按钮行状态:显示+隐藏(恢复初始状态) buttonRows.forEach((row) => { row.style.display = "block"; row.classList.add("osynlig"); }); // 隐藏弹窗 congratMessage.classList.add("osynlig"); statisticsDiv.classList.add("osynlig"); wrongAnswerDiv.classList.add("osynlig"); wrongAnswerOkButton.classList.add("osynlig"); // 重新加载新剑 randomSword(); } wrongAnswerOkButton.addEventListener("click", resetGame); async function randomSword() { const idsResponse = await fetch("http://127.0.0.1:5500/sword/"); const ids = await idsResponse.json(); currentSwords = []; for (let i = 0; i < swordImages.length; i++) { const randomId = ids[Math.floor(Math.random() * ids.length)]; const swordResponse = await fetch( `http://127.0.0.1:5500/sword/${randomId}` ); const svard = await swordResponse.json(); const newSvärd = new Svärd(svard.typ, svard.bild); currentSwords.push(newSvärd); swordImages[i].src = newSvärd.bild; // 先移除旧事件,再绑定新事件 const buttons = buttonRows[i].querySelectorAll("button"); buttons.forEach((button) => { button.removeEventListener("click", handleButtonClick.bind(null, i)); button.addEventListener("click", handleButtonClick.bind(null, i)); }); } } randomSword();
关键修改说明
- 提取按钮点击逻辑为独立函数:将按钮点击处理逻辑提取为
handleButtonClick,避免每次randomSword都生成新的匿名函数,方便移除旧事件。 - 存储当前轮剑数据:新增
currentSwords数组存储当前显示的剑信息,解决原代码中newSvärd作用域导致的判断错误问题。 - 移除旧事件再绑定新事件:每次调用
randomSword时,先移除按钮上的旧点击事件,再绑定新事件,避免事件叠加。 - 修正失败判断逻辑:将失败判断中的
correctGuesses !== allaSvärd.length改为直接判断是否为最后一个元素,结合后续的correctGuesses是否等于总数量来触发失败弹窗。 - 完善UI重置:重置时给按钮行添加
osynlig类,恢复初始隐藏状态,同时隐藏失败弹窗和按钮。
内容的提问来源于stack exchange,提问作者esle98
相关产品推荐
相关产品推荐

