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

石头剪刀布游戏Event Listener问题:PlayerChoice始终返回NULL

石头剪刀布游戏按钮交互问题修复方案

问题核心

使用addEventListener绑定按钮点击事件时,playerChoice始终返回初始值"NULL",无法正确获取玩家选择;虽然HTML中用onclick能勉强运行,但希望通过event listener的方式修复逻辑。

问题原因分析

  1. 事件绑定时机错误:getPlayerChoice函数每次被playRound调用时都会重复绑定事件,且绑定后立刻返回playerChoice——此时用户还未点击按钮,变量自然还是初始值"NULL"。
  2. 逻辑流程冲突:HTML按钮通过onclick触发playRound,但playRound又调用getPlayerChoice绑定点击事件,导致事件触发逻辑混乱。
  3. 分数类型错误:从innerHTML获取的分数是字符串类型,直接执行+1会变成字符串拼接(比如"0"+1变成"01"),而非数值累加。

修复步骤及代码实现

修改后的JavaScript代码

let playerScore = 0
let computerScore = 0

function getRandomInt(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1) + min);
}

function getComputerChoice() {
    let numChoice = getRandomInt(1,3);
    let computerChoice = "NULL"
    if (numChoice == 1) {
        computerChoice = "ROCK";
    } else if (numChoice == 2) {
        computerChoice = "PAPER";
    } else if (numChoice == 3){
        computerChoice = "SCISSORS";
    }
    return computerChoice
}

// 重构playRound,直接接收玩家选择作为参数
function playRound(playerChoice) {
    // 将分数转换为数字类型,避免字符串拼接错误
    let scoreComputer = Number(document.getElementById("computerScore").innerHTML)
    let scorePlayer = Number(document.getElementById("playerScore").innerHTML)
    const computerChoice = getComputerChoice()

    // 胜负判断逻辑
    if (computerChoice === "ROCK" && playerChoice === "PAPER") {
        scorePlayer += 1
    } else if (computerChoice === "ROCK" && playerChoice === "SCISSORS") {
        scoreComputer += 1
    } else if (computerChoice === "PAPER" && playerChoice === "SCISSORS") {
        scorePlayer += 1
    } else if (computerChoice === "PAPER" && playerChoice === "ROCK") {
        scoreComputer += 1
    } else if (computerChoice === "SCISSORS" && playerChoice === "PAPER") {
        scoreComputer += 1
    } else if (computerChoice === "SCISSORS" && playerChoice === "ROCK") {
        scorePlayer += 1
    }

    alert(`你的选择:${playerChoice},电脑选择:${computerChoice}`)

    // 更新页面分数
    document.getElementById("playerScore").innerHTML = scorePlayer
    document.getElementById("computerScore").innerHTML = scoreComputer

    // 提前加入先赢5局的逻辑(可根据需求调整)
    if (scorePlayer === 5) {
        alert("你赢了整个游戏!")
        resetGame()
    } else if (scoreComputer === 5) {
        alert("电脑赢了整个游戏!")
        resetGame()
    }
}

// 游戏重置函数
function resetGame() {
    playerScore = 0
    computerScore = 0
    document.getElementById("playerScore").innerHTML = 0
    document.getElementById("computerScore").innerHTML = 0
}

// 页面加载完成后一次性绑定事件
document.addEventListener('DOMContentLoaded', function() {
    document.getElementById("rockButton").addEventListener("click", () => playRound("ROCK"))
    document.getElementById("scissorsButton").addEventListener("click", () => playRound("SCISSORS"))
    document.getElementById("paperButton").addEventListener("click", () => playRound("PAPER"))
})

修改后的HTML代码(移除冗余属性)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Rock, Paper, Scissors</title>
</head>
<body>
    <div>
        <h1 style="display:flex; justify-content:center">Welcome To Rock, Paper Scissors.</h1>
        <h3 style="display:flex; justify-content: center;">The directions are simple. You will play against a computer in Rock, Paper, Scissors best out of 5. Choose a weapon from the menu, and hope that luck is on your side!</h3>
        <h2 style="display: flex; justify-content: center;font-weight: bold;"><br><br>Rock beats Scissors, Scissors beats Paper, Paper beats Rock</h2>
    </div>
    <br>
    <br>
    <br>
    <br>
    <div style="display: flex; justify-content: space-around;">
        <button id="rockButton" style="display: flex; flex-direction: column; justify-content: center;">
            <img src="./stone.png" alt="image of a rock" height="100px" width="auto">
            <p style="margin-left: auto; margin-right: auto">Rock</p>
        </button>
        <button id="paperButton" style="display: flex; flex-direction: column; justify-content: center;">
            <img src="./paper.png" alt="image of a Paper" height="100px" width="auto">
            <p style="margin-left: auto; margin-right: auto">Paper</p>
        </button>
        <button id="scissorsButton" style="display: flex; flex-direction: column; justify-content: center;">
            <img src="./scissors.png" alt="image of Scisors" height="100px" width="auto">
            <p style="margin-left: auto; margin-right: auto">Scissors</p>
        </button>
    </div>
    <div style="display: flex; justify-content: center;">
        <div style="display: flex; justify-content: space-around; white-space: nowrap; width: 70%;">
            <div style="display: flex; white-space: nowrap;">
                <h1><br><br><br>Your Score: <h1 id="playerScore" style="margin-left: 5%; margin-right: 5%;"><br><br><br>0</h1></h1>
            </div>
            <div style="display: flex; white-space: nowrap; justify-content: center;">
                <h1><br><br><br>Computer's Score: <h1 id="computerScore" style="margin-left: 5%; margin-right: 5%;"><br><br><br>0</h1></h1>
            </div>
        </div>
    </div>
    <div style="display: flex; justify-content: center;">
        <h1 style="font: 40px; display: flex;"><br>Game Result</h1>
        <h1 id="gameResult"></h1>
    </div>
    <script src="./script.js"></script>
</body>
</html>

关键修复点

  1. 事件绑定优化:将事件绑定移到DOMContentLoaded回调中,确保DOM元素加载完成后只绑定一次,避免重复绑定。
  2. 参数传递替代全局变量:通过箭头函数直接在点击时向playRound传递玩家选择,彻底解决异步点击导致的变量未更新问题。
  3. 分数类型修正:使用Number()将获取的字符串分数转换为数值,保证累加逻辑正确。
  4. 逻辑解耦:移除HTML中的onclick属性,统一用JavaScript管理事件绑定,代码逻辑更清晰。

内容的提问来源于stack exchange,提问作者Evan Grosso

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 03:50:26