数字点击游戏开发问题:最后一步输出undefined而非'Done!'
问题排查与优化建议:"Tap the numbers"数字点击游戏
核心问题分析
点击最后一个数字时控制台输出undefined而非"Done!",主要有两个原因:
playGame函数的完成判断逻辑完全失效:函数内的counter是局部变量,每次调用都会重置为0,永远无法等于gCells.length;且gCells在else块内才定义,if判断时会触发未声明错误。- 最后一次调用
drawNum时数组为空:当最后一个数字被点击后,gNumbers通过splice被清空,此时drawNum从空数组取值,返回undefined,导致控制台输出The chosen number is undefined! Tap it!。
修复后的关键代码
修正playGame函数
function playGame() { // 直接通过gNumbers的长度判断是否完成所有数字点击 if (gNumbers.length === 0) { console.log('Done!') return } const gCells = document.querySelectorAll('td') chosenNum = drawNum() console.log(`The chosen number is ${chosenNum}! Tap it!`) const idxOfCell = gNumbers.indexOf(chosenNum) // 移除无效的counter判断逻辑,因为点击正确数字后才会进入playGame,无需额外计数 gNumbers.splice(idxOfCell, 1) }
清理displayBoard函数的重复变量定义
function displayBoard(numOfCells) { chosenLength = parseInt(numOfCells.innerText) gTable.style.display = 'table' // 移除重复的var chosenLength声明 addNumbers(chosenLength) var counter = 0 var strHTML = '' strHTML += `<tbody>` const gridSize = Math.sqrt(chosenLength) // 提取重复计算为变量 for (var i = 0; i < gridSize; i++) { strHTML += `<tr>` for (var j = 0; j < gridSize; j++) { strHTML += `<td data-location="${i}${j}" onclick="cellClicked(this)">${gNumbers[counter]}</td>` counter++ } strHTML += `</tr>` } strHTML += `</tbody>` gTable.innerHTML = strHTML playGame() }
额外优化建议
- 替换
var为let/const:全局变量chosenNum、chosenLength改用let,局部变量优先用const,避免变量提升导致的意外问题。 - 集中管理全局状态:把全局变量封装到一个对象中,减少全局污染:
const gameState = { container: document.querySelector(".container"), table: document.querySelector('table'), numbers: [], chosenNum: null, chosenLength: null } - 优化随机数生成:
addNumbers函数用Set生成不重复随机数,逻辑更简洁高效:function addNumbers(numOfCells) { const numSet = new Set() while (numSet.size < numOfCells) { const randNum = Math.floor(Math.random() * 49) + 1 numSet.add(randNum) } gameState.numbers = Array.from(numSet) } - 分离样式与逻辑:把内联的
<h1>样式移到CSS文件中,保持代码结构清晰。 - 事件绑定优化:避免在
innerHTML中直接写onclick,改用事件委托:// 在init或displayBoard中绑定事件 gameState.table.addEventListener('click', (e) => { if (e.target.tagName === 'TD') { cellClicked(e.target) } })
内容的提问来源于stack exchange,提问作者Manoon
相关产品推荐
相关产品推荐

