patternjavascriptMinor
Index mechanics for Rock Paper Scissors
Viewed 0 times
paperscissorsmechanicsrockforindex
Problem
I just went through a very easy online example creating a Rock-Paper-Scissors game, but it seemed like it was not a great use of computing power.
It seemed like I was writing out results for every possible outcome instead of declaring properties or attributes for variables that will dictate the results depending on the situation.
Could an index or something be used to set up the variables?
Player 1 could select a variable, then player 2 could select a string in the index, and the position of the selection in the index would determine the winner (0 = tie, 1 = p1Loss, 2 = p1Win). Is this possible?
I think the code in the example below would start to get messy and bloated if you were to expand on the choices/options. i.e. Instead of 3 options you have 9, any one of which will beat 4 options and loose to the other 4.
I guess I'm just wondering if there is a better way to do this that would scale better with larger numbers.
I've included the code from the example below:
```
var user1Choice = prompt("Do you choose rock, paper or scissors?");
var user2Choice = prompt("Do you choose rock, paper or scissors?");
var compare = function(choice1, choice2) {
if (choice1 === choice2) {
return "its 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 === "paper") {
return "scissors wins";
}
else {
return "paper wins";
}
}
}
compare(user1Choice, user2Choice
It seemed like I was writing out results for every possible outcome instead of declaring properties or attributes for variables that will dictate the results depending on the situation.
Could an index or something be used to set up the variables?
var rock = ["rock", "paper", "scissors"];
var paper = ["paper", "scissors", "rock"];
var scissors = ["scissors", "rock", "paper"];
index 0 1 2Player 1 could select a variable, then player 2 could select a string in the index, and the position of the selection in the index would determine the winner (0 = tie, 1 = p1Loss, 2 = p1Win). Is this possible?
I think the code in the example below would start to get messy and bloated if you were to expand on the choices/options. i.e. Instead of 3 options you have 9, any one of which will beat 4 options and loose to the other 4.
I guess I'm just wondering if there is a better way to do this that would scale better with larger numbers.
I've included the code from the example below:
```
var user1Choice = prompt("Do you choose rock, paper or scissors?");
var user2Choice = prompt("Do you choose rock, paper or scissors?");
var compare = function(choice1, choice2) {
if (choice1 === choice2) {
return "its 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 === "paper") {
return "scissors wins";
}
else {
return "paper wins";
}
}
}
compare(user1Choice, user2Choice
Solution
Your idea
Your idea is nice, but it will cause problems when extending the game. For example, we will add spock and lizard:
Now, index 1 and 2 mean p1Loss, and index 3 and 4 mean p1Win. This can easily cause bugs in the future.
Maybe a better idea
You could instead maintain arrays that say what items beat. For example:
Then, check at the beginning if the input of the users is equal, return "tie" if it is. If it is not, find the appropriate array for user1 (I would use a switch instead of many if-else) and see if it contains the choice of user2.
In this case, extending the game is easier. New item? Add a new array and a new switch option, and add the item to some of the other arrays.
In case you really want to extend the game (I mean like adding a couple dozen or more options), this approach too would become somewhat annoying. In that case you might want to read up on graph theory, as this is basically just a directed graph. I think that an adjacency matrix might work well then.
For rock, paper, scissor, the matrix would look like this (it contains duplicate information, but I don't think that memory is a concern and removing it would make it harder to use):
And you use it like this:
Player1 plays paper, Player2 plays rock.
Look in the paper row for the value under rock. it is 1 and player1 wins. -1 would mean they lose, and 0 means tie.
For just rock, paper, scissors this is overkill, but for a lot more options this might work well.
Comments on current code
Your idea is nice, but it will cause problems when extending the game. For example, we will add spock and lizard:
var spock = ["spock", "paper", "lizard", "scissors", "rock"];Now, index 1 and 2 mean p1Loss, and index 3 and 4 mean p1Win. This can easily cause bugs in the future.
Maybe a better idea
You could instead maintain arrays that say what items beat. For example:
var spockBeats = ["scissor", "rock"];Then, check at the beginning if the input of the users is equal, return "tie" if it is. If it is not, find the appropriate array for user1 (I would use a switch instead of many if-else) and see if it contains the choice of user2.
In this case, extending the game is easier. New item? Add a new array and a new switch option, and add the item to some of the other arrays.
In case you really want to extend the game (I mean like adding a couple dozen or more options), this approach too would become somewhat annoying. In that case you might want to read up on graph theory, as this is basically just a directed graph. I think that an adjacency matrix might work well then.
For rock, paper, scissor, the matrix would look like this (it contains duplicate information, but I don't think that memory is a concern and removing it would make it harder to use):
R P S
R 0 -1 1
P 1 0 -1
S -1 1 0And you use it like this:
Player1 plays paper, Player2 plays rock.
Look in the paper row for the value under rock. it is 1 and player1 wins. -1 would mean they lose, and 0 means tie.
For just rock, paper, scissors this is overkill, but for a lot more options this might work well.
Comments on current code
- I would save the strings (rock, paper, scissors) in fields at the top of the file. It's an easy source of bugs because of typos
- I would return which player won, not with what choice they won. Or both, but the current way seems just odd to me
Code Snippets
var spock = ["spock", "paper", "lizard", "scissors", "rock"];var spockBeats = ["scissor", "rock"];R P S
R 0 -1 1
P 1 0 -1
S -1 1 0Context
StackExchange Code Review Q#59160, answer score: 8
Revisions (0)
No revisions yet.