-1

Here is a simple code snippet where I am ensuring the user input is a number and is between 1-3

do{
var choice = parseInt(prompt("Please select one of the following:\n1.ROCK\n2.PAPER\n3.SCISSORS\n[NOTE: Choose your selection by pressing a number between 1,2 or 3.]"));
}while(isNaN(choice) && (choice === 1 || choice === 2 || choice === 3));

While debugging I see the debugger does not even evaluate the part after && where I am keeping a check on the input to be among 1, 2 or 3

Weirdly enough, the do-while construct works fine if I just have :

do{
var choice = parseInt(prompt("Please select one of the following:\n1.ROCK\n2.PAPER\n3.SCISSORS\n[NOTE: Choose your selection by pressing a number between 1,2 or 3.]"));
}while(isNaN(choice));

Can someone tell me what am I missing here or doing wrong?

Boann
  • 48,794
  • 16
  • 117
  • 146

4 Answers4

3

As your code looks now, you are looping as long as it's not a number and it's either 1, 2, or 3. Since those three are all valid numbers, the overall condition can never be true - if it's not a number then it won't be 1, 2 or 3, and if it's 1, 2 or 3 it won't be "not a number" (since it's a number).

From what you wrote, you want to keep looping if it's not a number or not one of those three:

do {
  var choice = parseInt(prompt("Please select one of the following:\n1.ROCK\n2.PAPER\n3.SCISSORS\n[NOTE: Choose your selection by pressing a number between 1,2 or 3.]"));
} while (isNaN(choice) || !(choice === 1 || choice === 2 || choice === 3));

(I changed && to || and added a ! before the second part of the condition.)

However, since you are limiting it to three exact options anyway, you don't even need to check for NaN anymore, because as mentioned before, if it's 1, 2 or 3 it means it's not NaN anyway:

do {
  var choice = parseInt(prompt("Please select one of the following:\n1.ROCK\n2.PAPER\n3.SCISSORS\n[NOTE: Choose your selection by pressing a number between 1,2 or 3.]"));
} while (!(choice === 1 || choice === 2 || choice === 3));

This becomes a bit easier to read by getting rid of the negation in the front, replacing === by !== and || by &&:

do {
  var choice = parseInt(prompt("Please select one of the following:\n1.ROCK\n2.PAPER\n3.SCISSORS\n[NOTE: Choose your selection by pressing a number between 1,2 or 3.]"));
} while (choice !== 1 && choice !== 2 && choice !== 3);

An alternative way to simplify the previous code is to create an array with valid values and loop as long as this array doesn't include the actual input number:

do {
  var choice = parseInt(prompt("Please select one of the following:\n1.ROCK\n2.PAPER\n3.SCISSORS\n[NOTE: Choose your selection by pressing a number between 1,2 or 3.]"));
} while (![1, 2, 3].includes(choice));
CherryDT
  • 25,571
  • 5
  • 49
  • 74
  • Wow, now I get what I was doing wrong exactly. I'll mark yours as an acceptable answer. Although others also helped me understand what I can do alternatively. Thank you sir – CamelCaseDev Jul 03 '21 at 12:02
1

Assume that when you prompt a non-nan value e.g. a number, isNaN evaluates false, thereby going into short-circuit evaluation. However, I think you want to accept one of 1,2, or 3 values. So shouldn't it be like !(choice === 1 || choice === 2 || choice === 3)? If one of them equals that value, no need to loop again.

1

When the first statement of the while loop is false the compiler doesnt compile the other statements after && here in this example (choice === 1 || choice === 2 || choice === 3) because it doesn`t matter what the other statements result is. The while loop is not executed at all.

This is compiler optimation (Short-circuit evaluation) for more information look at this article: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND

Marci
  • 302
  • 5
  • 12
1

A less complicated approach (avoiding parseInt, isNaN and multiple boolean checks) may be (snippet for the whole game ;):

Play it here

document.querySelector('button')
  .addEventListener( 'click', () => location.reload() );

let choices = ['ROCK', 'PAPER', 'SCISSORS']
let choice = 0;

while ( !choices[+choice-1] ) {
  choice = prompt(
    `1. ROCK; 2. PAPER; 3. SCISSORS`, `Enter 1, 2 or 3`);
}

const values = {
  yours: choices[choice-1], 
  mine: choices[Math.floor(Math.random() * 3 )]};
const tie = values.yours === values.mine;
const iWin = values.yours === 'SCISSORS' && values.mine === 'ROCK' ||
  values.yours === 'ROCK' && values.mine === 'PAPER' ||
  values.yours === 'PAPER' && values.mine === 'SCISSORS';

console.log(`your choice: ${values.yours}, against: ${values.mine}. ${
  tie ? 'Tied...' : iWin ? 'You lost' : 'You win!'}` );
<button>Again...</button>
KooiInc
  • 119,216
  • 31
  • 141
  • 177