Home > Blockchain >  How can I wait for a click to be executed?
How can I wait for a click to be executed?

Time:07-11

I am trying to figure out how I can update the playerValue for my Rock Scissor Paper game. I have a function that registers a button click and should then update the playerValue accordingly(1,2 or three depending on which button was clicked). The problem is, when I call the function, the playerValue remains 0 and I don't know what I need to change to fix that. playerValue itself is defined at the very beginning of my file. It starts out as 0.

Here is my JavaScript code(or at least the relevant part of it):

//register button click and:
function player_choose_value(){
    //check which button has been clicked -> rock 1, scissor 2 or paper 3
    btnRock.addEventListener("click", () =>{
        playerValue = 1;
    });

    btnScissor.addEventListener("click", () =>{
        playerValue = 2;
    });
    
    btnPaper.addEventListener("click", () =>{
        playerValue = 3;
    });
}

This here is where the playerValue is meant to be used. The playerValue is always 0. I think that is because the player_choose_value() function does not wait for the click event to happen. So the function is executed but the user does not have the chance to actually click a button, so it stays 0:

function play_round(){
    let computerValue = computer_choose_value();
    player_choose_value();//is always zero
    console.log(playerValue);
    won_tie_lost(computerValue, playerValue);
}

I was wondering how I could add a "wait for one of the three buttons to be clicked" functionality?

CodePudding user response:

In your case, player_choose_value doesn't wait until the player has actually picked a value.

You could probably do this using async await/promises:

function player_choose_value(){
  return new Promise(resolve => {
    bntRock.onclick = () => resolve(1)
    btnScissor.onclick = () => resolve(2)
    btnPaper.onclick = () => resolve(3)
  })
}

async function play_round(){
  let computerValue = computer_choose_value();
  const playerValue = await player_choose_value();
  console.log(playerValue);
  won_tie_lost(computerValue, playerValue);
}

;(async function main() {
  while (true) { // Keep repeating the game
    await play_round()
  }
})()

CodePudding user response:

Use promise.

function player_choose_value() {
  return new Promise((resolve, reject) => {
    //check which button has been clicked -> rock 1, scissor 2 or paper 3
    document.querySelector('#btn1').addEventListener("click", () => {
      resolve(1);
    });

    document.querySelector('#btn2').addEventListener("click", () => {
      resolve(2);
    });

    document.querySelector('#btn3').addEventListener("click", () => {
      resolve(3);
    });
  });
}

player_choose_value().then(
  play_value => {
    alert(play_value);
    // won_tie_lost...
    // other code 2...
  }
);

// other code 1...
<button id='btn1'>btn1</button>
<button id='btn2'>btn2</button>
<button id='btn3'>btn3</button>

player_choose_value will called first. It returns a promise that is pending.

The engine will continue to execute other code 1 and the code in then(play_value => { block will not be executed until one of the resolves is called (the promise is fulfilled).


Here is another pattern. I think it suits your needs better.

document.querySelectorAll('button').forEach((button, index) => {
  button.addEventListener('click', () => {
    let playerValue = index;
    let computerValue = computer_choose_value();
    play_round(playerValue, computerValue);
  })
});

function play_round(playerValue, computerValue) {
  // Disable the buttons if needed
  alert(`${playerValue} ${computerValue}`);
  // won_tie_lost(computerValue, playerValue);
}

function computer_choose_value() {
  return ~~(Math.random() * 3);
}

// start a round by enable the buttons
<button id='btn1'>btn1</button>
<button id='btn2'>btn2</button>
<button id='btn3'>btn3</button>

CodePudding user response:

You're going at it in a totally wrong way.

You should play_round be called by the button clicks, otherwise you will add event listeners on the button every single round.

btnRock.addEventListener("click", play_round);

btnScissor.addEventListener("click", play_round);

btnPaper.addEventListener("click", play_round);

function play_round(event){
  let playerValue = event.target.dataset.value;
  let computerValue = computer_choose_value();
  won_tie_lost(computerValue, playerValue);
}


function computer_choose_value() {
  return Math.floor(Math.random() * 3)   1;
}


function won_tie_lost(playerValue, computerValue) {
  console.log(`player: ${playerValue}, computer: ${computerValue}`);
}
<button id="btnRock"    data-value="1">Rock</button>
<button id="btnScissor" data-value="2">Scissor</button>
<button id="btnPaper"   data-value="3">Paper</button>

  • Related