Why does do-while not evaluate logical &&? - javascript

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?

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));

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

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.

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>

Related

While loop not displaying correct result Javascript

I'm working on a project for one of my classes where I need to use the users input to redirect them to a website. It requires that the users choice be validated using a loop, so I've chosen to use a while loop to check for if the users input differs from what it should be and if it is, the user is prompted to re-enter their answer. Here's the code:
var websitechoice;
websitechoice = parseInt(prompt("Which website would you like to go to? \n 1. google \n 2. gmail \n 3. youtube"))
while (websitechoice != 1 || 2 || 3) {
alert("you input an incorrect value")
websitechoice = parseInt(prompt("Which website would you like to go to? \n 1. google \n 2. gmail \n 3. youtube"))
}
if (websitechoice = 1) {
alert("you chose 1")
}
else if (websitechoice = 2) {
alert("you chose 2")
}
else {
alert("you chose 3")
}
So far it was just a quick mock up I made to check if it would work, but every time I try and run it, I always get back "you input an incorrect value" even when inputting 1, 2, or 3, and so far nothing I've tried had differed the results. if anyone could help I'd really appreciate it, thanks
You're using a definition in the if statement, in that you're telling the code that websitechoice is now equal to that number. You should use a comparator like so
if (websitechoice == 1) {
alert("you chose 1")
}
else if (websitechoice == 2) {
alert("you chose 2")
}
else {
alert("you chose 3")
}
For your while statement, you should change it to and statement, because you only want to run the code when it's not equal to one and not eqaul to two and not equal to three
while (websitechoice != 1 && websitechoice != 2 && websitechoice != 3) {
alert("you input an incorrect value")
websitechoice = parseInt(prompt("Which website would you like to go to? \n 1. google \n 2. gmail \n 3. youtube"))
}
You could also just say, if websitechoice > 3 then do the alert process
There are many flaws in your code. First of all, you should use AND operator instead of OR operator. Also, you need to break the comparison as beloe demonstrated.
Secondly, you have used assignment operator ( = ) in the if else statement. You need to use comparison operator ( == or === ) to compare otherwise it will return 1 everytime.
var websitechoice;
websitechoice = parseInt(prompt("Which website would you like to go to? \n 1. google \n 2. gmail \n 3. youtube"))
while (websitechoice !== 1 && websitechoice !== 2 && websitechoice !== 3) {
alert("you input an incorrect value")
websitechoice = parseInt(prompt("Which website would you like to go to? \n 1. google \n 2. gmail \n 3. youtube"))
}
if (websitechoice === 1) {
alert("you chose 1")
}
else if (websitechoice === 2) {
alert("you chose 2")
}
else {
alert("you chose 3")
}
Also, it will be easy to debug if you put your code in the snippet. Seems like you are quite new to developer community. Welcome to coder community !
The != has precedence over the || operator 1 so:
websitechoice != 1 || 2 || 3
will always evaluate to:
(websitechoice != 1) || 2 || 3
which is not what you want...
another issue is that:
websitechoice = 1
is an assignment not a comparison.
To fix your code without changing its structure:
var websitechoice;
websitechoice = parseInt(prompt("Which website would you like to go to? \n 1. google \n 2. gmail \n 3. youtube"))
while (websitechoice !== 1 && websitechoice !== 2 && websitechoice !== 3) {
alert("you input an incorrect value")
websitechoice = parseInt(prompt("Which website would you like to go to? \n 1. google \n 2. gmail \n 3. youtube"))
}
if (websitechoice === 1) {
alert("you chose 1")
}
else if (websitechoice === 2) {
alert("you chose 2")
}
else {
alert("you chose 3")
}
A cleaner way to check if your input is one of a list of values would probably be:
[1,2,3].includes(websitechoice)
which is cleaner and can scale easily to more values.
I've also replaced the == operators with ===, don't use == in JS unless you know what you are doing. 2

What can I do to make code be executed while the answer is one of a multiple conditions?

I tried to make that a code runs when x, determinated by a prompt is one of the four answers. With only one possibility it works well, but when I add more using && the program do nothing. (At the end of the program i put a break to execute the code only one time)
That's a short version of how the programm works...
var x = prompt("Ready?");
while(x == "yes"){
window.alert("...Example...");
break;
}
And how I want to make it but doesn't works...
var x = prompt("Ready?")
while(x == "Yes" && x == "yes" && x == "yeS" && x == "YES")
window.alert("...Example...");
break;
}
How can I do to make it works?
I would just use .toLowerCase() before the comparison so you don't have to deal with all different ways to capitalize a word.
var input = prompt("Ready?");
var x = input.toLowerCase();
while( x == "yes" )
window.alert("...Example...");
break;
}
Then again, if you only need yes or no as options, I'd use a window.confirm instead of a window.prompt.
Edit: Hmm, if the question is that the answer HAS to be yes written in one of those 4 ways, I'd go for the array approach so you can add other options later on:
var allowed_answers = [ 'yes', 'Yes', 'yeS', 'YES' ];
if ( allowed_answers.includes( x ) ) {
}
Use || instead of &&, and there's no need for a while statement, use if instead:
var x = prompt("Ready?")
if (x === "Yes" || x === "yes" || x == "yeS" || x == "YES") {
window.alert("...Example...");
}
|| means “or”, i.e. at least one of the conditions has to be true. If you use “and”, it means all of the conditions need to be true, which cannot possibly work.
Maybe you're trying to do this
do{
var x = prompt("Ready?").toLowerCase();
//toLowerCase() method convert (YES, Yes, yeS, etc) to (yes)
if(x === "yes"){
//If the condition is true, the loop breaks
window.alert("...Example...");
break;
}
}while(true)

javascript or operation returns unexpected result

I am very new to javascript. I have a programm like:
var a = 2
if(a !=2 || a != 3){
console.log("not")
}
Here I have set the variable a value to 2.
In my condition I have set if a is not 2 or a is not 3 it should print not
But here a's value being 2 it is printing not.
It always give not whatever the value is
I can check this is python easily like:
if not a == 2 or not a== 3
Whats wrong in here ??
var a = 2
a is now 2.
a !=2
This is false, so we look on the other side of the or
a != 3
This is true. So one of the two sides of the or test is true. Therefore the or test is true.
If you want to test if a value is not 2 and it is also not 3, then you need to use an && operator.
Maybe you want this:
if(a !=2 && a != 3){
console.log("not")
}
In other words, if a is not 2 AND a is not 3.
This is just how boolean logic works. In your example, because a does not equal 3, the condition is true.
Please read how logical operators work.
Your condition evaluates to true if a is not 2 or a is not 3, that means that is will be false only when a is both 2 and 3 at the same time which isn't possible - this condition will always be true.
You might be also interested in reading something on mathematical logic and negations.
If you want to ensure that a is not 2 or 3 then you should change it to
if((a != 2) && (a != 3)){
as in a is not 2 and a is not 3 - keep in mind that you are working with 2 statements.
Simple explanation
false || true = true
a != 2 //returns false
a != 3 //returns true
In python:
not a == 2 // returns false
not a == 3 //returns true
"OR" in the condition means that the statement in the if block will get executed if any one of the equations out of
(a != 2)
and
(a != 3)
returns true.
In your code snippet
(a != 3)
is true and hence the statement
console.log("not");
gets executed.
This is very expected behaviour and it work same in python and javascript
a = 2
if not a == 2 or not a== 3:
print ("not")
is equivalent to
var a = 2
if(a !=2 || a != 3){
console.log("not")
}
in or expression conditions check while one of theme be come true or until there was no condition.

Number Validation Not Working

I have an input field thats only supposed to take numbers inbetween 1 and 4. If the number is inbetween 1 and 4, it runs some code. If not, it shoots an alert that tells the user to try again with a number between 1 and 4. Here is my code
var number = document.getElementById("num").value;
if(Number(number) === 1 || Number(number) === 2 || Number(number) === 3 || Number(number) === 4 ){
//success code here///
}
else if(Number(number) !== 1 || Number(number) !== 2 || Number(number) !== 3 || Number(number) !== 4) {
} alert("Please type a whole number between(and including) 1 and 4 into the input field.");
I learned that the '.value;' function returns a string, even if the value is a number. So I put the var 'number' in the Number(); function that converts it to a number.
The problem is, when I type 1 into the input field. It shoots the alert even though it equals 1. None of the other numbers work either. I checked the console, and there are no syntax errors(also according to DreamWeaver). Help would be highly appreciated :)
I think you made a simple mistake of putting your alert outside the else if clause.
However there are a few other things you can do to make that a little more readable and efficient.
// Call Number() here so you only have to do it once
var number = Number(document.getElementById("num").value);
// You can also do something like parseInt(document.getElementById("num").value)
// Now check to see if Number() or parseInt() actually parsed an integer out of their input
// and then check that if it's outside your number range
if (isNaN(number) || number < 1 || number > 4) {
alert("Please type a whole number between(and including) 1 and 4 into the input field.");
} else {
// Do Successful code
}
we can write like this also
var patt1 = /[1-4]/g;
if(patt1.test(number)){
//success code here///
}
else{
alert("Please type a whole number between(and including) 1 and 4 into the input field.");
}

JavaScript logical operators questions?

I just don't understand how && and || work. I wrote up a small code to help myself out and it just doesn't make any sense to me. You would click a button and the startGame() would be called.
var startGame = function() {
var quizAnswers = {
name: prompt("What is your name?").toUpperCase(),
age: prompt("What is your age?"),
snack: prompt("What is your favorite type of snack out of the following: ice cream, apple, chips, cookies?").toUpperCase()
};
quizAnswers.confirmAge = function () {
while (isNaN(this.age) === true) {
this.age = prompt("The age that you entered- " + this.age + " -is not a number. Please enter a number.");
};
};
quizAnswers.confirmAge();
quizAnswers.confirmSnack = function () {
while ((this.snack !== "ICE CREAM") && (this.snack !== "APPLE") && (this.snack !== "CHIPS") && (this.snack !== "COOKIES")) {
this.snack = prompt("The snack you entered- " + this.snack + " -is unrecognized. Please enter: ice cream, apple, chips, or cookies.").toUpperCase();
};
};
quizAnswers.confirmSnack();
It would get name, age, and favorite snack and then check to see if the age is a number and the snack entered is one of the listed options. After messing with the while loop in the confirmSnack function, I figured out how to make it work, which is displayed above. But why is it && and not ||. And is there a way to shorten it like:
while (this.snack !== ("ICE CREAM" && "APPLE" && "CHIPS" && "COOKIES")) {
this.snack = prompt("The snack you entered- " + this.snack + " -is invalid. Please enter: ice cream, apple, chips, or cookies.").toUpperCase();
};
So the questions are to explain why &&(and) is used instead of ||(or) and if there is a way to shorten this code so i don't have to enter "this.snack !==" four times. I'm not an expert so please try to keep it simple.
The && operator is working just fine. This is actually a question of logic, not javascript.
You are asking the question while the answer is different from ALL of the possible answers.
It could be rewritten with || as the follwing:
while (!(this.snack == "ICE CREAM" || this.snack == "APPLE" || this.snack == "CHIPS" || this.snack == "COOKIES"))
Notice the ! operator in the beginning.
A shorter form to write it would be:
answers = ["ICE CREAM", "APPLE", "CHIPS", "COOKIES"];
while (answers.indexOf(this.snack) < 0) { ... }
Here you define a list of possible answers and you want to accept, and check if the answer is among them.
The && and || operators compare boolean values. (Boolean means true/false). That means if you execute 5 == 5 && 6 + 1 == 7 the interpreter does the following things:
Evaluate 5 == 5. The == operator returns true if both sides are equal (as you probably know). Since 5 == 5 is true, we look at the next value (if it were false, because of short circuit operators, it would return false immediately).
Evaluate 6 + 1 == 7. This is also true, so the returned value is true.
The && operator does not compare regular values such as "ICE CREAM" (well it does, but it converts it into a boolean value).
Now let's look at the code you provided:
this.snack !== ("ICE CREAM" && "APPLE" && "CHIPS" && "COOKIES")
First, the javascript interpreter executes ("ICE CREAM" && "APPLE" && "CHIPS" && "COOKIES"). Since all of those values are true, the value of that expression is true. So this comparison is essentially checking this.snack !== true, which is not what you want.
To solve your problem, I would suggest using indexOf. This checks if an element is in an array and returns -1 if there is no element. For example:
var validSnacks = ["ICE CREAM", "APPLE", "CHIPS", "COOKIES"];
while (validSnacks.indexOf(this.snack) === -1) {
// Do something
}
If you use or(||), if any of the sub-statements (e.g. this.snack !== "ICE CREAM") evaluate to true, the entire statement will be true, causing the prompt to be shown.
On the other hand, using and(&&), all of the sub-statements must be true for the entire statement to evaluate as true, which is the behaviour that you want - you only want the prompt to show if snack is not one of the 4 options.
There is no way to shorten the code in the way you suggest. One thing you could do would be to make an array with the 4 options in it and check if that array contains snack.

Categories

Resources