You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

数字点击游戏开发问题:最后一步输出undefined而非'Done!'

问题排查与优化建议:"Tap the numbers"数字点击游戏

核心问题分析

点击最后一个数字时控制台输出undefined而非"Done!",主要有两个原因:

  1. playGame函数的完成判断逻辑完全失效:函数内的counter是局部变量,每次调用都会重置为0,永远无法等于gCells.length;且gCells在else块内才定义,if判断时会触发未声明错误。
  2. 最后一次调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 02:57:06