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

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

Related

Trying to make my first JavaScript project work, full function is displayed in the "console" instead of the actual result I want from the code

I'm doing my first JS project which is a simple Rock, Paper, Scissor game that should work in the console.
I think my code is quite correct, but when I "console.log" my function (playRound) I get the following snippet in the "console": "You both played undefined It's a Draw!". I'm not sure what I'm missing so if someone could take a look then that would be very much appreciated!
Here is my script:
function computerPlay (){
const choices = ["Rock", "Paper", "Scissor"];
const randomChoice = choices[Math.floor(Math.random() * choices.length)];
return(randomChoice);
}
console.log(computerPlay()) //just to show "computerPlay" works
function playRound(playerSelection, computerPlay) { //This is the actual round
if (playerSelection == computerPlay) {
result = `You both played ${computerPlay} It's a Draw!`;
} else if ((playerSelection == "Paper" && computerPlay == "Rock") ||
(playerSelection == "Rock" && computerPlay == "Scissor") ||
(playerSelection == "Scissor" && computerPlay == "Paper")) {
result = `${playerSelection} beats ${computerSelection} You Win!`;
} else {
result = `${computerPlay} beats ${playerSelection} You Loose!`;
}
return (result);
}
let playerSelection = 'rock'
console.log(playRound()) // to test if "playRound" works
Thanks for checking!
Kind regards,
A coding newbie
Once you define the function, you should call it with parameters to see the result.
The playRound function has 2 parameters, so please replace console.log(playRound) with console.log(playRound(playerSelection, computerPlay())).
You have not called the function you are just printing the content inside your function using console.log.
Try like below :
function computerPlay() {
const choices = ["Rock", "Paper", "Scissor"];
const randomChoice = choices[Math.floor(Math.random() * choices.length)];
return (randomChoice);
}
computerPlay();//call it
function playRound(playerSelection, computerPlay) { //This is the actual round
if (playerSelection == computerPlay) {
result = `You both played ${computerPlay} It's a Draw!`;
} else if ((playerSelection == "Paper" && computerPlay == "Rock") ||
(playerSelection == "Rock" && computerPlay == "Scissor") ||
(playerSelection == "Scissor" && computerPlay == "Paper")) {
result = `${playerSelection} beats ${computerSelection} You Win!`;
} else {
result = `${computerPlay} beats ${playerSelection} You Loose!`;
}
return (result);
}
let playerSelection = 'rock'
playRound(playerSelection, playerSelection);//pass parameter in calling funciton
console.log(result) // to test if "result" is accurate

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

Use of logical and comparison operators in conditions (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>

Sending a string/result from JS to HTML-page

I'm working on a simple rock, paper, scissors game of HTML + JS.
Here are the full codes (CSS, JS, HTML): http://jsfiddle.net/fJw4R/
(too long to past here I thought). Here you can see it with pictures: http://shinebrightmedia.se/rps/rockpaperscissors.html
As you can see, the .math-module works, and when you choose rock, paper or scissor the computer randomizes a choice.
However, I now would like to have a textstring underneath the computer/monitor, and I'm wondering what the easiest way to do that. I want it to either say YOU WIN! or YOU LOSE!
I started on a function looking like this:
function theWinnerIs(userChoice, computerChoice) {
if (userChoice === computerChoice ) {
return 'No winner, it is a draw';
}
if ((userChoice === 'rock') && (computerChoice === 'scissor')) {
return 'human';
}
if ((userChoice === 'rock') && (computerChoice === 'paper')) {
return 'computer';
}
if ((userChoice === 'paper') && (computerChoice === 'scissor')) {
return 'computer';
}
if ((userChoice === 'paper') && (computerChoice === 'rock')) {
return 'human';
}
if ((userChoice === 'scissor') && (computerChoice === 'rock')) {
return 'computer';
}
if ((userChoice === 'scissor') && (computerChoice === 'paper')) {
return 'human';
}
}
What is the easiest way to send the return to the index-file? ie. YOU WIN! or YOU LOSE!
Thanks for any help.
No need to use this block of ifs - here's very compact alternative:
var choices = { rock: -1, paper: 0, scissors: 1 };
var score = choices[userChoice] - choices[computerChoice];
score = score - (score/2|0) * 3;
... which will give you -1 if user loses the round, 1 if they win, 0 in case of draw.
Now you can just send the output to any prepared container by filling its innerHTML property:
var results = {
'-1': 'YOU LOSE',
'1': 'YOU WIN',
'0': 'IT\'S A DRAW'
};
var resultContainer = document.getElementById('result');
resultContainer.innerHTML = results[score];
Here's a small demo to illustrate both those concepts.
From what I understand, you would like to display some text depending on the outcome of your "theWinnerIs" method. I would suggest you create a div on your page and set its content with JavaScript. There are numerous ways to accomplish your goal, however.
So you want to add a div to your page, something like <div id="output"></div>. You can then update the text here with the following
var outputElement = document.getElementById("output");
outputElement.innerHTML = theWinnerIs(userChoice, computerChoice);
Here's an updated version of your code for perspective, though raina77ow's solution is much nicer.

Javascript not running - no error message

I've set up this rock, paper scissors game. However, the Javascript is not running and I'm not receiving any errors. Any suggestions?
function play(humanScore) {
var computerScore = getcomputerScore();
if (humanScore == "rock") {
if (computerScore == "rock") {
} else if (computerScore == "scissors") {
human++
} else if (computerScore == "paper") {
computer++
}
} else if (humanScore == "scissors") {
if (computerScore == "scissors") {
} else if (computerScore == "paper") {
human++
} else if (computerScore == "rock") {
computer++
}
} else if (humanScore == "paper") {
if (computerScore == "paper") {
} else if (computerScore == "scissors") {
computer++
} else if (computerScore == "rock") {
human++
}
}
}
function getcomputerScore() {
var randomplay = ["rock", "paper", "scissors"];
var play = randomplay[Math.floor(Math.random() * myArray.length)];
return play
}
This is the code setting up humanScore:
var human = 0;
var computer = 0;
document.getElementById("rock").onClick = pickRock;
document.getElementById("scissors").onClick = pickScissors;
document.getElementById("paper").onClick = pickPaper;
function pickRock() {
play("rock");
}
function pickScissors() {
play("scissors");
}
function pickPaper() {
play("paper");
}
The name of the property is onclick, not onClick; note the lowercase c.
There’s at least one other error (myArray.length, as #RobG points out), but this will make them actually throw.
Probably better suited to a code review section, but here goes…
function play(humanScore) {
var computerScore = getcomputerScore();
variables humanScore and computerScore aren't actually scores, they are symbols the players have chosen to play, so the variables might be better as humanChoice and computerChoice. This also means that the globals human and computer can be better named as humanScore and computerScore.
if (humanScore == "rock") {
if (computerScore == "rock") {
} else if (computerScore == "scissors") {
Rather than leaving a blank block, better to either insert a comment to say "no adjustment". Better to test equivalent choices up front, then you're left with binary choices, so you can do something like:
var humanScore = 0;
var computerScore = 0;
function play(humanChoice) {
// IE tends to play with capitalisation of values
humanChoice = humanChoice.toLowerCase();
var computerChoice = getComputerChoice();
// If same choice, no change of score
if (computerChoice == humanChoice) {
return;
}
// Only binary win/lose choices left
if (humanChoice == 'rock') {
computerChoice == 'paper'? ++computerScore : ++humanScore;
} else if (humanChoice == 'paper') {
computerChoice == 'scissors'? ++computerScore : ++humanScore;
} else if (humanChoice == 'scissors') {
computerChoice == 'rock'? ++computerScore : ++humanScore;
}
}
There was an error in this function too:
function getComputerChoice() {
var choices = ['rock','paper','scissors'];
return choices[Math.random()*choices.length | 0];
}
Lastly, make sure the buttons are in the page before adding the listener, and make sure the property names have the correct case (it doesn't matter for HTML attributes, but it does for javascript property names):
window.onload = function() {
document.getElementById("rock").onclick = pickRock;
document.getElementById("scissors").onclick = pickScissors;
document.getElementById("paper").onclick = pickPaper;
}

Categories

Resources