2

I want to prompt the user for an input and if it isn't a valid option reprompt until a valid input is entered.

Right now it always reprompts not matter the input, correct or not.

Here is the code:

var userChoice = prompt("Do you choose rock, paper, scissors or rope?");
while (userChoice != "rock" || "paper" || "scissors" || "rope") {
    userChoice = prompt("Sorry invalid input, please enter either: rock, paper,scissors, or rope.");
}

Seems like it should be a simple thing to do, am I misunderstanding how to use while loops? maybe the operators are wrong? haven't been able to find anything useful, any help is appreciated!

1
  • 1
    @djechlin For hanging yourself after you get terminally bored of the game, instant loss. ;-) Commented Jan 4, 2016 at 21:39

6 Answers 6

5

You could also use an array and indexOf

var userChoice = prompt("rock, paper, scissors, rope?").toLowerCase();
while (["rock", "paper", "scissors", "rope"].indexOf(userChoice) === -1) {
    userChoice = prompt("Please choose: rock, paper, scissors, rope?").toLowerCase();
}

alert("You chose '" + userChoice + "'");
Sign up to request clarification or add additional context in comments.

3 Comments

First off thanks for the help, so let me try an interpret your code, I really am that new to this ha! The initial prompt asks for the choice (which will all display in lowercase), then in the while loop you created an array using the string "rock" etc, "rock" being 0, "paper" being 1 in that array? then indexof(userchoice) searches for the inputs I want aka the parameters of the array. the -1 means if it is not any of the correct answers it will reprompt and if correct will display the choice with the alert? That right?
and just looked up .indexOf so can see the -1 means unsuccessful search, are there any meaningful differences between .indexOf and str.search? They both appear to provide similar functions
To your first comment that sounds like a correct understanding of the code. Strings have an indexOf function which provides functionality comparable to that of array's indexOf (providing the offset of the found item, or -1 if no match).
4

The syntax "rock" || "paper" is valid, but the OR will bind later than the equality check, so basically you write:

while ((userChoice != "rock") || "paper" || "scissors" || "rope") {
    //...
}

Now since you use such or's, you basically do an effectiveness check and at least "paper" is effective. You can however get the behavior you aim, by using explicit checks and using the && operator instead of the ||:

while (userChoice !== "rock" && userChoice !== "paper" && userChoice !== "scissors" && userChoice !== "rope") {
    //...
}

Comments

2

While userChoice does not equal any of the choices... so AND

while (userChoice != "rock" && userChoice != "paper" && userChoice != "scissors" && userChoice != "rope") {

Comments

2

Maybe an array is smarter to use with Array.prototype.indexOf().

var userChoice;
while (!~["rock", "paper", "scissors", "rope"].indexOf(userChoice)) {
    userChoice = prompt("Sorry invalid input, please enter either: rock, paper,scissors, or rope.");
}

Comments

2

for more complicated rules (such as ignoring case sensitivity), it is possible to use regular expressions, e.g. match:

while( ! userChoice.match(/^\s*(?:rock|paper|scissors|rope)\s*$/i)) { ... }

(see explanation of the regex on https://regex101.com/r/sV3tJ1/1#javascript)

note: thanks Willem Van Onsem for suggesting regex


also avaliable are object literals:

var validChoices = {rock: true,
                    paper: true,
                    scissors: true,
                    rope: true},
    userChoice = ...
while ( ! validChoices.hasOwnProperty(userChoice)) {
  ...
}

or ES6 Set for the newest browsers as of 2016: new Set(["rock", "paper", ...])

2 Comments

In case you want to check against a huge set of values, a regex will probably be more efficient. Nevertheless +1 for creativity ;)
@WillemVanOnsem actually, regex will be better even for a case insensitive solution accepting stray spaces in this particular problem, thanks for the suggestion
0

I'll try a more generic answer:

The while loop runs while whatever in the brackets is TRUE.

The way || works, it will evaluate to TRUE if at least one of the operands is TRUE.

So in your case even if you select

userChoice = "rock";
userChoice != "rock" => FALSE

whatever comes after || will still evaluate to TRUE because

"rock" != "paper" => TRUE 

and thus your whole condition in the brackets will evaluate to TRUE.

So in order to break out of the loop, you need to have the condition in the brackets evaluate to FALSE.

The way && works, it will evaluate to FALSE if at least one of the operands evaluates to FALSE.

And since

userChoice = "rock";
userChoice != "rock" => FALSE

the loop does not even check the rest of the conditions you might have and breaks out of the loop.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.