Use of logical and comparison operators in conditions (javascript) - javascript

I want the user to input his answer in a rock-paper-scissors game in the following line of code.
userChoice = prompt("Do you choose rock, paper or scissors?");
However, in case the user writes something other than exactly "rock", "paper" or "scissors", he is supposed to choose again, which I tried to do with this piece of code:
while (userChoice !== "rock" || "paper" || "scissors") {
userChoice = prompt("Invalid choice. Please change your answer.");
};
The problem I have is that the program keeps recognizing the given input as invalid, even if it is "rock", "paper" or "scissors".
While typing this, I managed to find a solution on my own.
while (userChoice !== "rock" && userChoice !== "paper" && userChoice !== "scissors") {
userChoice = prompt("Invalid choice. Please change your answer.");
};
That way does make sense and the first condition probably didn't work because even if you type a correct answer (e.g. "paper"), it still doesn't equal the other two answers (in this case "rock" and "scissors"), which is why the program kept saying the answer has been invalid, right? Or is it a syntax error?
Now (with the working condition), the choice of the user has to be neither "rock" nor "paper" nor "scissors" and thus it works properly.
Also, is there possibly an easier and shorter way of writing that condition?
Note: I hope it's fine that parts of the solution are already included as they could help other coders.

Two examples
One with an array and Array.prototype.indexOf():
var userChoice;
while (!~['rock', 'paper', 'scissors'].indexOf(userChoice)) {
userChoice = prompt("Invalid choice. Please change your answer.");
};
And another with an object and the in operator:
The in operator returns true if the specified property is in the specified object.
var userChoice;
while (!(userChoice in {rock: 1, paper: 1, scissors: 1})) {
userChoice = prompt("Invalid choice. Please change your answer.");
};

Use indexOf
while (["rock", "paper", "scissors"].indexOf(userChoice) > -1) {
Your first attempt
while (userChoice !== "rock" || "paper" || "scissors") {
is technically an infinite loop because
|| "paper"
for example, technically evaluates to true or a truthy value

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Rock Papper Scissors Game</title>
</head>
<body>
<h1>Play Rock Papper Scissors?</h1>
<button id="start">Play?</button>
<script>
function rpsGame() {
var computerChoice = Math.random(),
userChoice = prompt('Do you choose rock, paper, or scissors');
function getComputerChoice() {
if (computerChoice <= 0.33) {
computerChoice = 'rock';
} else if (computerChoice <= 0.66 && computerChoice >= 0.33) {
computerChoice = 'paper';
} else {
computerChoice = 'scissors';
}
}
function playAgain() {
var restart = prompt('Would you like to play again, yes or no?').toLowerCase();
switch(restart) {
case 'yes':
rpsGame();
break;
default:
alert('Okay, see you later!');
}
}
function compare() {
var choice1 = userChoice.toLowerCase(),
choice2 = computerChoice,
tie = "The computer chose " + choice2 + ", and you chose " + choice1 + ". The result is a tie!",
win = "The computer chose " + choice2 + ", and you chose " + choice1 + ". You win!",
lose = "The computer chose " + choice2 + ", and you chose " + choice1 + ". The computer wins!";
switch (choice1) {
case "":
alert("You didn't enter anything. Maybe we can play later!");
break;
case 'rock':
if (choice2 === 'scissors') {
alert(win);
} else if (choice2 === 'rock') {
alert(tie);
} else {
alert(lose);
}
playAgain();
break;
case 'paper':
if (choice2 === 'rock') {
alert(win);
} else if (choice2 === 'paper') {
alert(tie);
} else {
alert(lose);
}
playAgain();
break;
case 'scissors':
if (choice2 === 'paper') {
alert(win);
} else if (choice2 === 'scissors') {
alert(tie);
} else {
alert(lose);
}
playAgain();
break;
default:
alert(choice1.substring(0,1).toUpperCase() + choice1.substring(1, choice1.length).toLowerCase() + " is an invalid choice. Please change your answer.");
rpsGame();
}
}
getComputerChoice();
compare();
}
document.getElementById('start').addEventListener('click', rpsGame);
</script>
</body>
</html>

Related

How do I get a new value from the same JavaScript function each time I use it?

This question is directly related to The Odin Project Rock Paper Scissors JavaScript Fundamentals course.
I have successfully made a function which randomly picks "rock," "paper," or "scissors" for the computer, called "computerPlay."
function computerPlay() {
const gameArray = ['Rock', 'Paper', 'Scissors'];
const random = Math.floor(Math.random() * gameArray.length);
return gameArray[random];
}
I have made another function to accept the player's input of "rock," "paper," "scissors" (or 1, 2, 3 respectively) with no respect for casing in another function, called "playerPlay."
function playerPlay() {
console.log ("Do you choose 'Rock' (1), 'Paper' (2), or 'Scissors' (3)?");
let playerChoice = prompt("Do you choose 'Rock' (1), 'Paper' (2), or 'Scissors' (3)?");
if (playerChoice.toLowerCase() === "rock" || parseInt(playerChoice) === 1) {
playerChoice = "Rock";
} else if (playerChoice.toLowerCase() === "paper" || parseInt(playerChoice) === 2) {
playerChoice = "Paper";
}
else if (playerChoice.toLowerCase() === "scissors" || parseInt(playerChoice) === 3) {
playerChoice = "Scissors";
}
else if (playerChoice.toLowerCase() !== "rock" || "scissors" || "paper" || parseInt(playerChoice) !== 1 || 2 || 3) {
alert("Please try to enter your value again :)")
playerSelection();
}
else {
console.log("Not sure what's going on, hold on to yer butts ;)")
}
return playerChoice;
}
The function playerPlay() is saved into the const variable playerSelection, and the frunction computerPlay() is saved into the const variable computerSelection.
// Create a variable to store player's choice
const playerSelection = playerPlay();
// Create a variable to store computer's choice
const computerSelection = computerPlay();
These two const variables are then used in the playRound() function which runs a set of comparisons to see and then console.log and return whether the player or computer won the round of rock, papers, scissors.
/* Write a function that plays a single round of Rock Paper Scissors. The function should take two parameters - the playerSelection and
computerSelection - and then return a string that declares the winner of the round like so: "You Lose! Paper beats Rock" */
function playRound(playerSelection, computerSelection) {
if (computerSelection.toLowerCase() === playerSelection.toLowerCase()) {
console.log("It's a draw!");
return("Your Choice: " + playerSelection + ". " + "Computer: " + computerSelection);
} else if (computerSelection.toLowerCase() === "rock" && playerSelection.toLowerCase() === "scissors") {
console.log("Rock beats scissors! You lose :(");
return("Your Choice: " + playerSelection + ". " + "Computer: " + computerSelection);
} else if (computerSelection.toLowerCase() === "scissors" && playerSelection.toLowerCase() === "rock") {
console.log("Rock beats scissors! You win :D");
return("Your Choice: " + playerSelection + ". " + "Computer: " + computerSelection);
} else if (computerSelection.toLowerCase() === "scissors" && playerSelection.toLowerCase() === "paper") {
console.log("Scissors beats paper! You lose :(");
return("Your Choice: " + playerSelection + ". " + "Computer: " + computerSelection);
} else if (computerSelection.toLowerCase() === "paper" && playerSelection.toLowerCase() === "scissors") {
console.log("Scissors beats paper! You win :D");
return("Your Choice: " + playerSelection + ". " + "Computer: " + computerSelection);
} else if (computerSelection.toLowerCase() === "paper" && playerSelection.toLowerCase() === "rock") {
console.log("Paper beats rock! You lose :(");
return("Your Choice: " + playerSelection + ". " + "Computer: " + computerSelection);
} else if (computerSelection.toLowerCase() === "rock" && playerSelection.toLowerCase() === "paper") {
console.log("Paper beats rock! You win :D");
return("Your Choice: " + playerSelection + ". " + "Computer: " + computerSelection);
} else {
console.log("I'm not sure what, but something went worng :(");
}
}
My issue comes from when I need to repeat the playRound() function 5 times, and have each round be different.
/* Write a NEW function called game(). Use the previous function inside of this one to play a 5 round game that keeps score and reports
a winner or loser at the end. */
// Define function / rule for winning and keeping track of score and determining winner for 5 rounds of game
// Make each round reset the computer choice and get new input from the player.
function game() {
roundOne;
roundTwo;
roundThree;
roundFour;
roundFive;
}
const roundOne = playRound(playerSelection, computerSelection);
const roundTwo = playRound(playerSelection, computerSelection);
const roundThree = playRound(playerSelection, computerSelection);
const roundFour = playRound(playerSelection, computerSelection);
const roundFive = playRound(playerSelection, computerSelection);
// Print results of game round
console.log(game(playerSelection, computerSelection));
I recently tried to make 5 new const variables (roundOne, roundTwo... roundFive) to contain the "playRound(playerSelection, computerSelection);" function. I tried also changing the playerSelection and computerSelection const variables to let, thinking the const nature could be locking the values in place until I reload the page. I thought it might be a scope issue, but I am not understanding where exactly it is -- which is why I thought to ask here. The main issue is that the player-entered value and the computer randomly-generated value are always the same for the 5 repeated rounds. How do I get a different value to print for each repeated round? Does it maybe have to do with how I use "gameArray" (in computerPlay() function) and "playerChoice" (in playerPlay() function)?
I apologize if this much longer than it needs to be. I will continue looking into things as well. Thank you very much in advance.
(This is my first actual JavaScript creation/project of any kind, so any feedback in general, or in how I posted/asked this question as well, would also be greatly appreciated. Thank you!)
From what I can tell, you only set your consts playerSelection and computerSelection once (and they are consts, so can't be modified). You then pass these into your playRound function which processes the same consts 5 times. Consider removing these consts altogether and writing your game function like this:
function game() {
//Play game 5 times
for (let i = 0; i < 5; i++) {
const playerSelection = playerPlay();
const computerSelection = computerPlay();
// Call playRound function, passing in newly returned values
// from the playerPlay and computerPlay functions
const currentRound = playRound(playerSelection, computerSelection);
// Log our result
console.log(currentRound);
}
}
Or, more succinctly:
function game() {
//Play game 5 times
for (let i = 0; i < 5; i++) {
// Call playRound function, passing in newly returned values
// from the playerPlay and computerPlay functions and log to console
console.log(playRound(playerPlay(), computerPlay()));
}
}

Building a Rock/Paper/Scissors game with HTML/Javascript but not getting the desired output

I am pretty new to coding still, so I apologize in advance if this seems super basic. I've been doing The Odin Project and have made it to the RPS assignment. Now, I've kind of been playing with different iterations of the code just to get a better idea as to how things could work.
Right now I am just putting script tags in an html file to get the desired result and running the function through a console.log() in my browser. The issue I am having is that even when I run the function with the right inputs - I sometimes get the final else statement. I'll post the code below and then try to explain in greater detail what I mean.
<script>
function game(playerSelection) {
playerSelection = playerSelection.toLowerCase();
function computerSelection() {
let cAnswer = Math.floor(Math.random() * 3 + 1);
if (cAnswer == 1) {
return 'rock';
} else if (cAnswer == 2) {
return 'paper';
} else {
return 'scissors';
}
}
if (playerSelection == computerSelection()) {
return 'It\'s a tie! Try again.'
} else if (playerSelection == 'rock' && computerSelection() == 'scissors') {
return 'Rock beats scissors, you win!'
} else if (playerSelection == 'rock' && computerSelection() == 'paper') {
return 'Paper beats rock, you lose!'
} else if (playerSelection == 'paper' && computerSelection() == 'scissors') {
return 'Scissors beats scissors, you lose!'
} else if (playerSelection == 'paper' && computerSelection() == 'rock') {
return 'Paper beats rock, you win!'
} else if (playerSelection == 'scissors' && computerSelection() == 'paper') {
return 'Scissors beats paper, you win!'
} else if (playerSelection == 'scissors' && computerSelection() == 'rock') {
return 'Rock beats scissors, you lose!'
} else {
return 'It doesn\'t seem like you typed a valid option. Please type \'Rock\', \'Paper\', or \'Scissors\''
}
}
</script>
Whenever I run console.log(game('scissors')) for instance, I still occasionally get the final else statement from my if ... else block. Shouldn't that be impossible? When I go through it - as long as I type rock, paper, or scissors, I thought I should be hitting one of the other if statements before reaching the final else in the block. But still, sometimes the output I get in my console is 'It doesn't seem like you typed a valid option. Please type 'Rock', 'Paper', or 'Scissors
I imagine I didn't explain this very well so please let me know if I can help clarify.
Thank you!
You're running computerSelection every time in the if checks - every time the interpreter comes across the function call computerSelection(), a new computer answer is generated.
Generate the computer's answer just once instead:
const computerSelection = (() => {
let cAnswer = Math.floor(Math.random() * 3 + 1);
if (cAnswer == 1) {
return 'rock';
} else if (cAnswer == 2) {
return 'paper';
} else {
return 'scissors';
}
})();
if (playerSelection == computerSelection) {
return 'It\'s a tie! Try again.'
} else if (playerSelection == 'rock' && computerSelection == 'scissors') {
// etc
Or, less repetitively:
const computerSelection = ['rock', 'paper', 'scissors'][Math.floor(Math.random() * 3));

Validate user input string passed into Javascript prompt method

Homework help vampire alert. I'm trying to add a user input string validation function to the "Rock, paper, scissors" game on Codecademy. The text editor on the Codecademy site validates my code as correct, but I'm not getting the expected behavior, which is to return an alert if the user fails to enter either a "rock", "paper", or "scissors" string.
I've piped together the conditions in the if statement below:
var userChoice = prompt("Do you choose rock, paper or scissors?");
function validateUserChoice(userChoice) {
if (userChoice !== "rock" || userChoice !== "paper" || userChoice !== "scissors") {
alert("You can only select rock, paper or scissors!");
return false;
}
};
And here's the rest of the game. When the preceding function is invoked, it appears that the compare function below is bypassed and whatever string the user typed into the prompt is printed to the screen (see console.log("User Choice: " + userChoice); at the bottom). Otherwise, the game returns the expected behavior when the function above is commented out:
var computerChoice = Math.random();
if (computerChoice < 0.34) {
computerChoice = "rock";
} else if(computerChoice <= 0.67) {
computerChoice = "paper";
} else {
computerChoice = "scissors";
};
var compare = function(userChoice, computerChoice) {
if (userChoice === computerChoice) {
return "The result is a tie!";
};
if (userChoice === "paper") {
if (computerChoice === "rock") {
return "paper wins";
} else {
if (computerChoice === "scissors") {
return "scissors wins";
}
}
};
if (userChoice === "scissors") {
if (computerChoice === "rock") {
return "rock wins";
} else {
if (computerChoice === "paper") {
return "scissors wins";
}
}
}
};
console.log("User Choice: " + userChoice);
console.log("Computer Choice: " + computerChoice);
compare(userChoice, computerChoice);
Try changing the condition like below,
function validateUserChoice(userChoice) {
if (userChoice !== "rock" && userChoice !== "paper" && userChoice !== "scissors") {
alert("You can only select rock, paper or scissors!");
return false;
}
};

Javascript Codeacademy query

So i built a rock paper scissors game on codecademy and was tweaking it. The thing that i tweaked is that when the user writes an inappropriate choice, the code stops.
Everything worked but when i write "rock, paper or scissor" it still says inappropriate choice.
var userChoice = prompt("Do you choose rock, paper or scissors?");
//tweaking starts here
if (userChoice!=="rock") {
console.log("inappropriate choice");
}
else if (userChoice!=="paper") {
console.log("inappropriate choice");
}
else if (userChoice!=="scissors") {
console.log("inappropriate choice");
};
// tweaking ends here
var computerChoice = Math.random();
if (computerChoice < 0.34) {
computerChoice = "rock";
} else if(computerChoice <= 0.67) {
computerChoice = "paper";
} else {
computerChoice = "scissors";
}
console.log("Computer: " + computerChoice);
var compare = function(choice1,choice2) {
if (choice1===choice2) {
return "The result is a tie!";
}
else if (choice1 === "rock") {
if (choice2==="scissors") {
return "rock wins";
}
else {
return "paper wins";
}
}
else if (choice1 === "paper") {
if (choice2 === "rock") {
return "paper wins";
}
else {
return "scissors wins";
}
}
else if (choice1 === "scissors") {
if (choice2 === "rock") {
return "rock wins";
}
else {
return "scissors wins";
}
};
};
compare(userChoice,computerChoice);
<!-- end snippet -->
This is a classic if else if ladder problem.
As mentioned in the Java Tutorial here
However, once a condition is satisfied, the appropriate statements are executed [...] and the remaining conditions are not evaluated.
In your case, when you enter "paper" or "scissor", it breaks out at the first branch as userChoice != "rock". If you enter "rock", it breaks out at the second branch as userChoice != "paper".
Ultimately it doesn't make it through the if-else-if ladder and eventually prints the inappropriate choice message.
In order to validate the input such that the user doesn't enter anything but the strings, "rock", "paper" or "scissor", change your tweaking code as follows:
//tweaking starts here
if (userChoice!=="rock" && userChoice!=="paper" && userChoice!=="scissors"){
console.log("inappropriate choice");
}
}; // tweaking ends here
Always remember:
Only one branch of the ladder gets executed...!!! In case multiple
conditions are true, the branch first encountered alone shall be
executed.
Here's an example that might help you see how your if statement logic was incorrect:
var userChoice = prompt("Do you choose rock, paper or scissors?");
if ((userChoice != "rock") && (userChoice != "paper") && (userChoice != "scissors")) {
console.log("inappropriate choice");
} else {
console.log("appropriate choice!");
}
Here's a JSFiddle: https://jsfiddle.net/j66to3x0/2/

Noobish JavaScript Nested If-Else Statement Help/Advice/Pointers/YouNameIt

I just started learning JavaScript (Today actually) and I'd really appreciate some help with nested if-else statements. I thought I'd write a simple program to practice, and it seems that every if-else statement in my if blocks executes regardless of which parameter I put in. Any pointers or even things you notice that aren't germane to the problem at hand are appreciated. Thanks again. My code is below.
EDIT: I've gotten it now, and learned the error of my ways. Thanks to everyone who commented and gave advice so quickly.
var playerOne = prompt('Choose rock, paper, or scissors');
var playerTwo = prompt('Choose rock, paper, or scissors');
var fight = function (playerOne, playerTwo)
{
if( playerOne == 'rock' || 'Rock')
{
if (playerTwo == 'paper' || 'Paper')
{
alert('Player Two Wins!');
}
else if (playerTwo == 'rock' || 'Rock')
{
alert('Tie!');
}
else
{
alert('Player One wins!');
}
}
if(playerOne == 'paper' || 'Paper')
{
if (playerTwo == 'paper' || 'Paper')
{
alert('Tie!');
}
else if (playerTwo == 'rock' || 'Rock')
{
alert('Player One Wins!');
}
else
{
alert('Player Two wins!');
}
}
if (playerOne == 'scissors' || 'Scissors')
{
if (playerTwo == 'paper' || 'Paper')
{
alert('Player One Wins!');
}
else if (playerTwo == 'rock' || 'Rock')
{
alert('Player Two Wins!');
}
else
{
alert('Tie!');
}
}
};
fight(playerOne, playerTwo);
As several people have pointed out, your if statements need to be in the form of:
if (playerOne == 'paper' || playerOne == 'Paper')
or the more succinct:
if (playerOne.toLowerCase() == 'paper')
The problem is that playerOne == 'paper' || 'Paper' will always return a "Truthy" value (see http://11heavens.com/falsy-and-truthy-in-javascript for more detail on Truthy and Falsy values).
As an aside, while there's absolutely nothing wrong with multiple if statements, if I were coding this exercise my way would involve less if statements (and look a little like this:
var playerOne = prompt('Choose rock, paper, or scissors');
var playerTwo = prompt('Choose rock, paper, or scissors');
var fists = {
"rock": {
"beats": "scissors",
"loses": "paper"
},
"paper": {
"beats": "rock",
"loses": "scissors"
},
"scissors": {
"beats": "paper",
"loses": "rock"
}
}
var fight = function (playerOne, playerTwo) {
playerOne = playerOne.toLowerCase();
playerTwo = playerTwo.toLowerCase();
if (fists[playerOne] === undefined || fists[playerTwo] === undefined) {
alert('Someone threw an unknown fist!');
} else if (fists[playerOne].beats === playerTwo) {
alert('Player One wins!');
} else if (fists[playerTwo].beats === playerOne) {
alert('Player Two Wins!');
} else {
alert('Tie!');
}
};
fight(playerOne, playerTwo);
By objectifying the rock/paper/scissors combinations, the code is IMO significantly easier to read.
The other comments and answer are great, so I won't repeat what they said. But you asked for advice, and mine is to not use so many if statements to begin with. A big part of programming is learning how to cut down on unnecessary or repeated code. Data structures like objects and arrays are good for this:
var win_conditions = { //simple object showing which hands beat which
'rock': 'scissors',
'paper': 'rock',
'scissors': 'paper'
}
var fight = function(p1, p2) {
var result;
if (!win_conditions.hasOwnProperty(p1) || !win_conditions.hasOwnProperty(p2)) {
result = false; //error! user typed something invalid
} else {
if (win_conditions[p1] == p2) {
result = 'Player One wins!';
} else if (win_conditions[p2] == p1) {
result = 'Player Two wins!';
} else {
result = 'Tie!';
}
}
return result;
}
var fight_result = false;
var prompt_text = 'Choose rock, paper, or scissors';
var playerOne = prompt(prompt_text);
var playerTwo = prompt(prompt_text);
//keep asking until the user types a valid option
while (!fight_result) {
fight_result = fight(playerOne.toLowerCase(), playerTwo.toLowerCase());
}
alert(fight_result);
I recommend you to use FireBug to debug your JavaScript Code. When you debug your code change the alert() to console.log() and probably playerOne/playerTwo to simple strings.
(Doesn't fit your question perfectly, but if you continue learning it's a good advice overall.)

Categories

Resources