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

控制台石头剪刀布转GUI时,getPlayerSelection函数返回undefined问题

问题:GUI版石头剪刀布无法正确获取用户选择,函数返回undefined

我正在把控制台版石头剪刀布改成GUI版本,用按钮作为用户输入渠道,但写的getPlayerSelection函数始终返回undefined。这个函数本来要获取点击按钮的文本内容作为用户选择,虽然console.log(input)能打出正确的字符串,但函数的返回值就是不对。我试过给每个按钮单独设置类名和事件监听,问题还是没解决。

HTML代码

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Rock Paper Scissors!</title>
</head>
<body>

    <section id="choices">
    <button class="button">Rock!</button>
    <button class="button">Paper!</button>
    <button class="button">Scissors!</button>
    </section>

    <script src="javascript.js" defer></script>
</body>

JavaScript代码

// player input
function getPlayerSelection(){
    const buttons = document.getElementsByClassName('button');
    let input = '';
        
    for (const btn of buttons) {
        btn.addEventListener('click', () => {
            input =  btn.textContent;
            console.log(input);
        })
    }
    return input;
}

// computer input
function getComputerChoice(){
    let randomChoice = Math.floor(Math.random() * 3);
        
    if(randomChoice === 0){
        return("Rock!")
    } else if(randomChoice === 1){
        return("Paper!")
    } else {
        return("Scissors!")
    }
}

function playRound(playerSelection, computerSelection) {
    playerSelection = getPlayerSelection();
    computerSelection = getComputerChoice();
    // ... 后续逻辑
}

尝试的其他代码

const rockBtn = document.querySelector('.rockButton');
rockBtn.addEventListener('click', () => {
    return 'Rock!';
});

const paperBtn = document.querySelector('.paperButton');
paperBtn.addEventListener('click', () => {
    return 'Paper!';
});

const scissorsBtn = document.querySelector('.scissorsButton');
scissorsBtn.addEventListener('click', () => {
    return 'Scissors!';
});

问题原因与解决方法

核心原因

  • 事件监听是异步触发的:getPlayerSelection执行时只是给按钮绑定了点击事件,随后立刻返回了初始值'',此时用户还没点击按钮,自然拿不到有效选择。用户点击按钮的动作是在函数执行完之后才会触发,这时候修改input变量已经无法改变函数的返回值了。
  • 第二种尝试的写法里,事件回调的返回值不会被外部捕获,根本无法传递给playRound函数,所以完全起不到作用。

解决方法

方法1:用Promise封装用户选择(保留原有函数结构)

把getPlayerSelection改成返回Promise,当用户点击按钮时resolve对应的值:

function getPlayerSelection(){
    return new Promise((resolve) => {
        const buttons = document.getElementsByClassName('button');
        for (const btn of buttons) {
            btn.addEventListener('click', () => {
                resolve(btn.textContent);
            }, { once: true }); // 确保每个按钮只触发一次,避免重复绑定
        }
    });
}

// 调用时需要用async/await处理异步
async function playRound() {
    const playerSelection = await getPlayerSelection();
    const computerSelection = getComputerChoice();
    // 这里写判断胜负的逻辑
    console.log(`玩家选择:${playerSelection},电脑选择:${computerSelection}`);
}

// 初始化调用游戏
playRound();

方法2:直接把游戏逻辑绑定到按钮点击事件(更简单直观)

不需要单独的getPlayerSelection函数,直接在按钮点击时触发一轮游戏:

function getComputerChoice(){
    let randomChoice = Math.floor(Math.random() * 3);
    if(randomChoice === 0){
        return("Rock!")
    } else if(randomChoice === 1){
        return("Paper!")
    } else {
        return("Scissors!")
    }
}

function playRound(playerSelection) {
    const computerSelection = getComputerChoice();
    // 胜负判断逻辑
    let result = '';
    if (playerSelection === computerSelection) {
        result = '平局!';
    } else if (
        (playerSelection === 'Rock!' && computerSelection === 'Scissors!') ||
        (playerSelection === 'Paper!' && computerSelection === 'Rock!') ||
        (playerSelection === 'Scissors!' && computerSelection === 'Paper!')
    ) {
        result = '你赢了!';
    } else {
        result = '你输了!';
    }
    console.log(`${result} 玩家:${playerSelection},电脑:${computerSelection}`);
}

// 给所有按钮绑定点击事件
const buttons = document.getElementsByClassName('button');
for (const btn of buttons) {
    btn.addEventListener('click', () => {
        playRound(btn.textContent);
    });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 07:16:09