Is there a more efficient loop than this?


#1

Hi, I found this way to allow the user and computer to choose again when they get a tie. But I'm sure there is a cleaner simpler way to achieve this loop.

I thought about making the first block of code a function, then call it again if it's a tie but it doesn't run initially.

Would love some feedback for improvements.

var userChoice = prompt("Do you choose rock, paper or scissors?");
var computerChoice = Math.random();
if (computerChoice < 0.34) {
	computerChoice = "rock";
} else if(computerChoice <= 0.67) {
	computerChoice = "paper";
} else {
	computerChoice = "scissors";
} 

for (;userChoice === computerChoice;) {
    var userChoice = prompt("you tied, try again. Rock, paper or scissors?");
    var computerChoice = Math.random();
if (computerChoice < 0.34) {
    computerChoice = "rock";
} else if(computerChoice <= 0.67) {
    computerChoice = "paper";
} else {
    computerChoice = "scissors";
} 
}

#2

I thought about making the first block of code a function

Actually a good idea. Did you call it or what went wrong?
Also loops are a good idea but I'd prefer a while or do/while loop here.


#3

Hi, thanks for the reply.
I couldn't work out how to call it because i'm not passing any data into it. Basically nothing happened when I loaded the page.

would the do while be something like do the userChoice and computerChoice block, while the condition is they equal each other?
I get a choice1 undefined, because that doesn't come until the compare function. Bit stuck on what to do, and what the condition would be.


#4

Well you call it by name +() if there is not parameter in the () after function then you need no arguments in the () after the function name.

The do while loop runs while the condition in the () after while is true with the specialty that it runs at least once even when the condition is false. So it would let you choose at least once and if userChoice is equal to computerChoice you're thrown in the loop again otherwise you're allowed to move on. Could you post the updated code?


#5

I managed to get this working as a do while - however it no longer tells you it's a tie, if the "choices" are the same. Was just trying to work that bit out but failed.

do { 
    var userChoice = prompt("Do you choose rock, paper or scissors?");
    var computerChoice = Math.random();
    if (computerChoice < 0.34) {
    computerChoice = "rock";
    } else if(computerChoice <= 0.67) {
    computerChoice = "paper";
    } else {
    computerChoice = "scissors";
    } 
    console.log("Computer: " + computerChoice);
    console.log("You: " + userChoice);
    var compare = function (choice1,choice2){
if (choice1 === choice2){
    console.log ("The result is a tie!"); 
} while (userChoice === computerChoice);


var compare = function (choice1,choice2){
if (choice1 === choice2){
    console.log ("The result is a tie!"); 
   
    }
    else if (choice1==="rock") {
        if (choice2 ==="scissors") {
            console.log ("rock wins");
            return "rock wins";
                    } else {
            console.log ("paper wins");
            return "paper wins";

        }
    }
    else if (choice1 === "paper") {
        if (choice2 === "rock") {
            console.log ("paper wins");
            return "paper wins";
        } else {
            console.log ("scissors wins")
            return "scissors wins";
        }
    }   
    else if (choice1 === "scissors") {
        if (choice2 === "rock") {
            console.log ("rock wins");
            return "rock wins";
        } else {
            console.log ("scissors wins");
            return "scissors wins";
              
        }    
    }    
}

compare (userChoice, computerChoice)

#6

var compare = function (choice1,choice2){
    if (choice1 === choice2){
        console.log ("The result is a tie!"); 
    }

first of all I've the impression that } are missing here. Also what about putting the do/while loop after the "real" compare function and using a condition like this:

while(compare(userChoice,computerChoice) === "The result is a tie!");


#7

This is my next attempt. I created a function for the first block, then call it, and use the do while on the function. This crashes the browser though

var userChoice = prompt("Do you choose rock, paper or scissors?");
var computerChoice = computerChoice = Math.random();

var play = function() {
    if (computerChoice < 0.34) {
    computerChoice = "rock";
    } else if(computerChoice <= 0.67) {
    computerChoice = "paper";
    } else {
    computerChoice = "scissors";
    } 
    console.log("Computer: " + computerChoice);
    console.log("You: " + userChoice);
}

var compare = function (choice1,choice2){
if (choice1 === choice2){
    console.log ("The result is a tie!"); 
   
    }
    else if (choice1==="rock") {
        if (choice2 ==="scissors") {
            console.log ("rock wins");
            return "rock wins";
                    } else {
            console.log ("paper wins");
            return "paper wins";

        }
    }
    else if (choice1 === "paper") {
        if (choice2 === "rock") {
            console.log ("paper wins");
            return "paper wins";
        } else {
            console.log ("scissors wins")
            return "scissors wins";
        }
    }   
    else if (choice1 === "scissors") {
        if (choice2 === "rock") {
            console.log ("rock wins");
            return "rock wins";
        } else {
            console.log ("scissors wins");
            return "scissors wins";
              
        }    
    } 

    do {play ()
    }
    while (choice1 === choice2);
}

window.onload = play ();
compare (userChoice, computerChoice);

#8

The problem is that play() changes the value of computerChoice (btw pretty mean that the user is not allowed to chose again) the value of choice1 and choice2 are not effected by this, so you're trapped in an infinite loop. I'd really suggest that you don't do it inside of the compare function. Let the compare function just be a compare function and use what is returned from it. This way you also avoid confusion with different sets of variables as you stay in the same scope all the time.


#9

yeah the intention is that the user also chooses again, but I see now how that won't happen (in this failed code).
I want to try your suggestion, to use the returned value of compare.

I tried your suggestion above but it isn't loading the initial prompt.

I did it like this

do {
    var userChoice = prompt("Do you choose rock, paper or scissors?");
    var computerChoice = computerChoice = Math.random();
    if (computerChoice < 0.34) {
    computerChoice = "rock";
    } else if(computerChoice <= 0.67) {
    computerChoice = "paper";
    } else {
    computerChoice = "scissors";
    } 
    console.log("Computer: " + computerChoice);
    console.log("You: " + userChoice);
} while (compare(userChoice,computerChoice) === "The result is a tie!");

#10

Have you placed this part after the compare function? What isn't working here?


#11

no. It is before the compare function.
when I load the page, nothing happens, where it should display a prompt to enter rock paper etc...

I get an unexpected end of script error


#12

Well it should be after the compare function because otherwise you might get problems because this calls the compare function before there actually is a compare function. Could you post the full code?


#13

Yes I was just thinking that too.
Do I need to return the "the result is a tie" string as a value to use it in the while statement in that way?

do {
    var userChoice = prompt("Do you choose rock, paper or scissors?");
    var computerChoice = computerChoice = Math.random();
    if (computerChoice < 0.34) {
    computerChoice = "rock";
    } else if(computerChoice <= 0.67) {
    computerChoice = "paper";
    } else {
    computerChoice = "scissors";
    } 
    console.log("Computer: " + computerChoice);
    console.log("You: " + userChoice);
} while (compare(userChoice,computerChoice) === "The result is a tie!");

var compare = function (choice1,choice2){
if (choice1 === choice2){
    console.log ("The result is a tie!"); 
   
    }
    else if (choice1==="rock") {
        if (choice2 ==="scissors") {
            console.log ("rock wins");
            return "rock wins";
                    } else {
            console.log ("paper wins");
            return "paper wins";

        }
    }
    else if (choice1 === "paper") {
        if (choice2 === "rock") {
            console.log ("paper wins");
            return "paper wins";
        } else {
            console.log ("scissors wins")
            return "scissors wins";
        }
    }   
    else if (choice1 === "scissors") {
        if (choice2 === "rock") {
            console.log ("rock wins");
            return "rock wins";
        } else {
            console.log ("scissors wins");
            return "scissors wins";
              
        }    
    } 

compare (userChoice, computerChoice);

#14

fixed the end of script error - missing }
but now have this:
TypeError: undefined is not a function (evaluating 'compare(userChoice,computerChoice)')


#15

Yes as the returned value determines the value of the expression compare(userChoice,computerChoice). Also missing } at the end. And the one about calling undefined is probably because you call compare before it exists.


#16

can the while statement be inside the compare function? seems strange to do that.
I added it after the compare function, which ran, however when it tied, it didn't loop.

If I have it before the function, it's giving the undefined error. This is because the browser doesn't know about the Compare function yet right?

I'm not getting the logic I think.


#17

Yes you could, the thing is just that this would make the compare function more complex than it has to be. The idea of this compare function is just throw 2 values in and get a winner back, nothing else. If you split you're program in individual blocks you can easier determine which code is running correct and which is not if you smash everything into 1 function it might get confusing to figure this out.

I added it after the compare function, which ran, however when it tied, it didn't loop.

Have you replaced the console.log with the return statement? Otherwise you see the tie result but you return undefined (default if nothing is returned).

right.

Show what you think and I can tell you if it is possible or where you went wrong.


#18

thanks for your patience. Really appreciate it.

so I did this, which runs, but doesn't loop.

Same result if I just add the while statement after the whole function. Runs but no loop.

var compare = function (choice1,choice2){
if (choice1 === choice2){ 
    return "the result is a tie";
   
    }
    else if (choice1==="rock") {
        if (choice2 ==="scissors") {
            console.log ("rock wins");
            return "rock wins";
                    } else {
            console.log ("paper wins");
            return "paper wins";

        }
    }
    else if (choice1 === "paper") {
        if (choice2 === "rock") {
            console.log ("paper wins");
            return "paper wins";
        } else {
            console.log ("scissors wins")
            return "scissors wins";
        }
    }   
    else if (choice1 === "scissors") {
        if (choice2 === "rock") {
            console.log ("rock wins");
            return "rock wins";
        } else {
            console.log ("scissors wins");
            return "scissors wins";
              
        }    
    } 

}

do {
    var userChoice = prompt("Do you choose rock, paper or scissors?");
    var computerChoice = computerChoice = Math.random();
    if (computerChoice < 0.34) {
    computerChoice = "rock";
    } else if(computerChoice <= 0.67) {
    computerChoice = "paper";
    } else {
    computerChoice = "scissors";
    } 
    console.log("Computer: " + computerChoice);
    console.log("You: " + userChoice);
} while (compare(userChoice===computerChoice) === "The result is a tie!"); 


compare (userChoice, computerChoice);

#19

Ok, this doesn't work. The problem is this:

compare(userChoice===computerChoice)

this:

userChoice===computerChoice

compares userChoice to computerChoice so it is either true or false. But whatever it is it is only 1 parameter so choice1 would be set to true/false and choice2 would be undefined. Obviously this will not be able to pick the tie case and therefore you exit the loop and instead run the outer compare function call.

So instead just call it like this:

while (compare(userChoice,computerChoice) === "The result is a tie!");

and maybe add a console.log statement to the tie case as well as you did it for the other cases.


#20

oh, yes that was a mistake. I was trying variations.
I have tried it as you showed above, and it runs, but no loop when it ties.

do {
    var userChoice = prompt("Do you choose rock, paper or scissors?");
    var computerChoice = computerChoice = Math.random();
    if (computerChoice < 0.34) {
    computerChoice = "rock";
    } else if(computerChoice <= 0.67) {
    computerChoice = "paper";
    } else {
    computerChoice = "scissors";
    } 
    console.log("Computer: " + computerChoice);
    console.log("You: " + userChoice);


var compare = function (choice1,choice2){
if (choice1 === choice2){ 
    console.log ("the result is a tie");
    return "the result is a tie";
   
    }
    else if (choice1==="rock") {
        if (choice2 ==="scissors") {
            console.log ("rock wins");
            return "rock wins";
                    } else {
            console.log ("paper wins");
            return "paper wins";

        }
    }
    else if (choice1 === "paper") {
        if (choice2 === "rock") {
            console.log ("paper wins");
            return "paper wins";
        } else {
            console.log ("scissors wins")
            return "scissors wins";
        }
    }   
    else if (choice1 === "scissors") {
        if (choice2 === "rock") {
            console.log ("rock wins");
            return "rock wins";
        } else {
            console.log ("scissors wins");
            return "scissors wins";
              
        }    
    } 
}
} while (compare(userChoice,computerChoice) === "The result is a tie!");