在递归后多次触发addEventListener

我还是个新手,我正在制作一个简单的石头、布、剪刀游戏。我正在使用addEventListener等待岩石按钮、布按钮或剪刀按钮被按下,然后它将执行游戏。问题是,当我按下重新启动游戏按钮并开始一个新游戏时,addEventListener中的按钮单击函数被执行两次。所以它只需点击一次按钮就可以播放这一轮两次。如果我再次重新启动游戏,则addEventListener函数将执行3次,依此类推。重新启动函数将分数重置为0并调用main()游戏函数。我认为这个问题与在Restart()函数中递归运行main()时再次执行addEventListener有关。我如何修复此问题?

数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假">
const myScoreLabel = document.querySelector('.myScore');
            const compScoreLabel = document.querySelector('.compScore');
            const resultLabel = document.querySelector('.result');
            const winnerLabel = document.querySelector('.winner');
            let myscore = 0;
            let computerscore = 0;
            
            function computerPlay() {
                let choices = ["Rock", "Paper", "Scissors"];
                let index = Math.floor(Math.random() * 3);
                let move = choices[index];
                return move;
            }

            function playRound(playerSelection, computerSelection) {
                let player = playerSelection.toLowerCase();
                let computer = computerSelection.toLowerCase();
                switch(player) {
                    case "rock":
                        switch(computer){
                            case "rock":
                               return "Draw! Try again..."; 
                               break;
                            case "paper":
                                return "You lose! Try again...";
                                break;
                            case "scissors": 
                                return "You win!";
                                break;
                        }
                        break;

                    case "paper":
                        switch(computer){
                            case "rock":
                                return "You win!";
                                break;
                            case "paper":
                                return "Draw! Try again...";
                                break;
                            case "scissors": 
                                return "You lose! Try again...";
                                break;
                        }
                        break;

                    case "scissors":
                        switch(computer){
                            case "rock":
                                return "You lose! Try again...";
                                break;
                            case "paper":
                                return "You win!";
                                break;
                            case "scissors": 
                                return "Draw! Try again...";
                                break;
                        }
                        break;
                }
            }

            function main() {
                myScoreLabel.textContent = myscore;
                compScoreLabel.textContent = computerscore;
                resultLabel.textContent = "";
                winnerLabel.textContent = "";
                
                const buttons = document.querySelectorAll('button');
                buttons.forEach((button) => {
                    button.addEventListener('click', function() {
                        let playerSelection = this.value;
                        let computerSelection = computerPlay();
                        let result = playRound(playerSelection, computerSelection);
                        const resultLabel = document.querySelector('.result');
                        resultLabel.textContent = result;
                        console.log(result);

                        if(result == "You win!") {  //Win
                            myscore++;
                            myScoreLabel.textContent = myscore.toString();
                            console.log("Your score: " + myscore);
                            console.log("Computer's score: " + computerscore);
                            console.log("");
                            if(myscore == 5){
                                winnerLabel.textContent = "You won the game!";
                                alert("Click Restart to play a new game");
                            }
                        }
                        else if(result == "You lose! Try again..."){    //Lose
                            computerscore++;
                            compScoreLabel.textContent = computerscore.toString();
                            console.log("Your score: " + myscore);
                            console.log("Computer's score: " + computerscore);
                            console.log("");
                            if(computerscore == 5) {
                                winnerLabel.textContent = "You lost the game!";
                                alert("Click Restart to play a new game");
                            }
                        }
                        else{   //Draw 
                            console.log("Your score: " + myscore);
                            console.log("Computer's score: " + computerscore);
                            console.log("");
                        }
                    });
                });
            }  

            function restart() {
                myscore = 0;
                computerscore = 0;
                main();
            }
            
            main();
<div class="score">
            <h2 class="myScore"></h2>
            <span>:</span>
            <h2 class="compScore"></h2>

        </div>
        <div class="choice">
            <button class="rock" value="rock">
                Rock
            </button>
            <button class="paper" value="paper">
                Paper
            </button>
            <button class="scissors" value="scissors">
                Scissors
            </button>
            <input id="restartSettings" type="button" value="Restart" onclick="restart()" />
        </div>
        <h2 class="result"></h2>
        <h1 class="winner"></h1>
        

编辑:如果运行代码片段,可以看到在单击Restart之后,按钮addEventListener内的代码被执行两次。


解决方案

每次您调用main()时,它会再次添加事件监听器,这意味着单击这些按钮将导致事件多次触发。

在添加事件侦听器之前删除它们,或者只在main()之外添加一次。

相关文章