addEventListener запускается несколько раз после рекурсии - PullRequest
0 голосов
/ 08 мая 2020

Я новичок в JavaScript и делаю простую игру «Камень, ножницы, бумага». Я использую addEventListener, чтобы дождаться нажатия кнопки Rock, бумажной кнопки или кнопки ножниц, а затем запустит игру. Проблема в том, что когда я нажимаю кнопку перезапуска игры и запускаю новую игру, функция нажатия кнопки из addEventListener выполняется дважды. Таким образом, он играет раунд 2 раза по 1 нажатию кнопки. Если я перезапускаю игру снова, функция addEventListener выполняется 3 раза и так далее. Функция перезапуска сбрасывает счет до 0 и вызывает игровую функцию main (). Я думаю, что эта проблема связана с повторным запуском addEventListener, когда main () рекурсивно запускается в функции restart (). Как это исправить?

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>
        

Изменить: если вы запустите фрагмент кода, вы увидите, что после нажатия кнопки «Перезапустить» код внутри кнопки addEventListener выполняется дважды.

Ответы [ 2 ]

1 голос
/ 08 мая 2020

Каждый раз, когда вы вызываете main(), он снова добавляет прослушиватели событий, что означает, что нажатие кнопок вызовет многократное срабатывание события.

Либо удалите прослушиватели событий перед их добавлением, либо просто добавьте их только один раз, за ​​пределами вашего main().

0 голосов
/ 08 мая 2020

Функция addEventListener была добавлена ​​в DOM API специально для устранения ограничений обработчиков событий типа on... Он предназначен для добавления, а не замены обработчиков событий, поэтому каждый раз, когда вы его вызываете, он сохраняет старые прослушиватели событий и добавляет новый, чтобы элемент теперь запускал несколько прослушивателей событий, точно так же, как вы наблюдаете.

Один очень простой, кроссбраузерный и надежный способ решить эту проблему, если вы хотите, чтобы кнопка только когда-либо имела единственный обработчик событий (что составляет 90% от того, что я лично делаю), - не использовать addEventListener и использовать гораздо более старый и широко поддерживаемый обработчик событий on..:

button.onclick = function() { ...
...