skip to Main Content

I want to create a scoring board for darts.
In this game, a number of players take turns in throwing 3 darts. Every dart scores an amount of points.
I’ve created buttons which correspond to the actual targets thrown on the dart board.
Example of such a button:
Player throws 1, so this button is clicked: 1.

My problem is combining the event listeners on the buttons with automatically switching to the next player when the turn is over.

With the code below, it seems that the button clicks remain associated to the previouos player, so when the second player throws, these throws are also counted for the first player…

So after the first round (every player has thrown 3 times, so 12 button clicks, player1 has totalArrows = 21, which is wrong obviously, this should be 3.

I’ve tried to extract the handleClick function from the event listener, but then I can’t seem to pass the button as a parameter, which is needed for the score.

My code:

// Player
//  remaining = how much of the score remains after each throw.
//  totalArrows = how many arrows has player thrown.
let player1 = { name: 'Steven', remaining: 501, totalArrows: 0};
let player2 = { name: 'Tom', remaining: 501, totalArrows: 0};
let player3 = { name: 'Nico', remaining: 501, totalArrows: 0};
let players = [player1, player2, player3];

// The buttons that can be clicked for scoring
const targetButtons = document.querySelectorAll(".target");

let playersIndex = 0;
let throws = 0;

function playerTurn() {
    let currentPlayer = players[playersIndex];
        
    targetButtons.forEach((button) => {
    
        button.addEventListener('click', function handleClick() {
        
            if (throws < 3 ) {
                currentPlayer.totalArrows++;
                const scoreThisThrow = parseInt(this.textContent);
                currentPlayer.remaining -= scoreThisThrow:
                throws++;
                
                if (throws === 3) {
                    button.removeEventListener("click", handleClick);
                    playersIndex = (playersIndex + 1) % players.length;
                    throws = 0;
                    playerTurn()
                }
            }
        });
    });
}

// Start the game
playerTurn()

2

Answers


  1. Chosen as BEST ANSWER

    I have managed to make it work. The code absolutley needs optimizing/cleaning, but the game is working in regards to automatically proceeding to the next player after three throws, without any arrow or remaining points issues.

    I've incorporated the scoring system normally used in a darts X01 game:

    • A game is won when a certain amount of sets are won.
    • A set is won when a certain amount of legs are won.
    • A leg is won when a player reaches 0 or less.

    The code below:

    // remaining = how much of the score remains after each throw.
    // totalArrows = how many arrows has player thrown.
    // legs = number of legs won.
    // sets = number of sets won.
    const player1 = { name: 'Steven', remaining: 501, totalArrows: 0, legs: 0, sets: 0};
    const player2 = { name: 'Tom', remaining: 501, totalArrows: 0, legs: 0, sets: 0};
    const player3 = { name: 'Nico', remaining: 501, totalArrows: 0, legs: 0, sets: 0};
    const players = [player1, player2, player3];
    
    // The buttons that can be clicked for scoring
    const targetButtons = document.querySelectorAll(".target");
    const numPlayers = players.length;
    const totalLegs = 3;
    const totalSets = 3;
    let playersIndex = 0;
    let currentPlayer = players[playersIndex];
    let throws = 0;
    let gameFinished = false
    
    function playerTurn() {
                    
        targetButtons.forEach((button) => {
        
            button.addEventListener('click', function handleClick() {
            
                if (throws < 3 ) {
                    currentPlayer.totalArrows += 1;
                    const scoreThisThrow = parseInt(this.textContent);
                    currentPlayer.remaining -= scoreThisThrow:
                    throws++;
                    
                    if (throws === 3 || currentPlayer.remaining < 1) {
                        // TODO: Bust rule
                        // TODO: Double out
                        if (currentPlayer.remaining < 1) {    // Player wins leg
                            currentPlayer.legs += 1;
                            if (currentPlayer.legs === totalLegs) {    // Player wins set
                                currentPlayer.sets += 1;
                                // Reset leg count
                                players.forEach((player) => {
                                    player.legs = 0
                                });
                                if (player.sets === totalSets) {    // Player wins the game
                                    gameFinished = true;
                                } else {
                                    playersIndex = (playersIndex + 1) % numPlayers;
                                    currentPlayer = players[playersIndex];
                                    throws = 0;
                                    return;
                                }
                            }
                            playersIndex = (playersIndex + 1) % numPlayers;
                            currentPlayer = players[playersIndex];
                            throws = 0;
                            return;
                        }
                        if (throws === 3) {
                            playersIndex = (playersIndex + 1) % players.length;
                            currentPlayer = players[playersIndex];
                            throws = 0;
                            return;
                        }
                        if (!gameFinished) {
                            playerTurn();
                        }
                    }
                }
            });
        });
    }
        
    playerTurn()
    

  2. Your logic is off. As you have it, you only evaluate whether players === 3 when players < 3. Which, of course, can never happen: players
    can never equal 3 if players is less than 3. So take your if players === 3 out of the other if block.

    That should solve your problem, and without having to remove your event listener. I’m also not seeing what you are doing with your totalArrows property. I’m presuming that its use is outside of the scope of the problem you’ve defined here. But if all you were using it for was to attempt to figure out why only one player was getting all the throws, then you can safely remove it.

    By the way, if you are not calling handleClick specifically from outside your addEventListener setup, you don’t need to give it a name: button.addEventListener('click', function(e) { and so on.

    Note that it is also usual to add a parameter to the function, usually e or event. This gives a reference to the Event object that the button element implements. So, for example, if you want to prevent the normal behavior for the event, you can put e.preventDefault. A common example of when you do this is when you have a button of type submit inside a form, and want to override the default behavior of the button.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search