More efficient choice comparison for Rock Paper Scissors
up vote
14
down vote
favorite
This is an ongoing school project that I would like to improve. The point is to make the code as efficient (or short) as possible. I would like to reduce it by finding an alternative to all the else ifs when comparing the computer's choice with the user's choice.
Here is the code:
let weapons = ["Rock", "Paper", "Scissors"];
let random = Math.floor(Math.random()*3);
let chosenOne = weapons[random];
let rps = prompt("Welcome to Rock, Paper, Scissors. Would you like to play?"
+ 'n' + "If you do, enter number 1." + 'n' + "If you don't, enter number
2.");
if (rps === "1") {
alert("Remember:" + 'n' + " - Rock beats the scissors" + 'n' + " -
Paper beats the rock" + 'n' + " - The scissors cut the paper");
let weapon = prompt("Make your choice:" + 'n' + "Rock, Paper, Scissors");
weapon = weapon.charAt(0).toUpperCase() + weapon.slice(1).toLowerCase();
alert("You chose: " + weapon + 'n' + "The computer chose: " +
chosenOne);
if (weapon === chosenOne) {
alert("It's a tie! Try again to win!");
} else if (weapon === "Rock" && chosenOne === "Paper") {
alert("You lost! Paper beats the rock.");
} else if (weapon === "Paper" && chosenOne === "Scissors") {
alert("You lost! The scissors cut the paper.");
} else if (weapon === "Scissors" && chosenOne === "Rock") {
alert("You lost! The rock beats the scissors.");
} else if (weapon === "Scissors" && chosenOne === "Paper") {
alert("You won! Scissors cut the paper.");
} else if (weapon === "Paper" && chosenOne === "Rock") {
alert("You won! Paper beats the rock.");
} else if (weapon === "Rock" && chosenOne === "Scissors") {
alert("You won! The rock beats the scissors.");
}
} else if (rps === "2") {
alert("Thanks for visiting! See you later.");
} else if (rps !== "1" || rps !== "2") {
alert("Invalid option. Closing game.");
}
I have thought about using switch statements, but since we are still beginners, I haven't grasped the subject fully. Any help is appreciated.
javascript
add a comment |
up vote
14
down vote
favorite
This is an ongoing school project that I would like to improve. The point is to make the code as efficient (or short) as possible. I would like to reduce it by finding an alternative to all the else ifs when comparing the computer's choice with the user's choice.
Here is the code:
let weapons = ["Rock", "Paper", "Scissors"];
let random = Math.floor(Math.random()*3);
let chosenOne = weapons[random];
let rps = prompt("Welcome to Rock, Paper, Scissors. Would you like to play?"
+ 'n' + "If you do, enter number 1." + 'n' + "If you don't, enter number
2.");
if (rps === "1") {
alert("Remember:" + 'n' + " - Rock beats the scissors" + 'n' + " -
Paper beats the rock" + 'n' + " - The scissors cut the paper");
let weapon = prompt("Make your choice:" + 'n' + "Rock, Paper, Scissors");
weapon = weapon.charAt(0).toUpperCase() + weapon.slice(1).toLowerCase();
alert("You chose: " + weapon + 'n' + "The computer chose: " +
chosenOne);
if (weapon === chosenOne) {
alert("It's a tie! Try again to win!");
} else if (weapon === "Rock" && chosenOne === "Paper") {
alert("You lost! Paper beats the rock.");
} else if (weapon === "Paper" && chosenOne === "Scissors") {
alert("You lost! The scissors cut the paper.");
} else if (weapon === "Scissors" && chosenOne === "Rock") {
alert("You lost! The rock beats the scissors.");
} else if (weapon === "Scissors" && chosenOne === "Paper") {
alert("You won! Scissors cut the paper.");
} else if (weapon === "Paper" && chosenOne === "Rock") {
alert("You won! Paper beats the rock.");
} else if (weapon === "Rock" && chosenOne === "Scissors") {
alert("You won! The rock beats the scissors.");
}
} else if (rps === "2") {
alert("Thanks for visiting! See you later.");
} else if (rps !== "1" || rps !== "2") {
alert("Invalid option. Closing game.");
}
I have thought about using switch statements, but since we are still beginners, I haven't grasped the subject fully. Any help is appreciated.
javascript
I don't think that string comparisons are the most optimal way to do this either. You could replace the strings with enums.
– Kapten-N
Dec 13 at 8:30
add a comment |
up vote
14
down vote
favorite
up vote
14
down vote
favorite
This is an ongoing school project that I would like to improve. The point is to make the code as efficient (or short) as possible. I would like to reduce it by finding an alternative to all the else ifs when comparing the computer's choice with the user's choice.
Here is the code:
let weapons = ["Rock", "Paper", "Scissors"];
let random = Math.floor(Math.random()*3);
let chosenOne = weapons[random];
let rps = prompt("Welcome to Rock, Paper, Scissors. Would you like to play?"
+ 'n' + "If you do, enter number 1." + 'n' + "If you don't, enter number
2.");
if (rps === "1") {
alert("Remember:" + 'n' + " - Rock beats the scissors" + 'n' + " -
Paper beats the rock" + 'n' + " - The scissors cut the paper");
let weapon = prompt("Make your choice:" + 'n' + "Rock, Paper, Scissors");
weapon = weapon.charAt(0).toUpperCase() + weapon.slice(1).toLowerCase();
alert("You chose: " + weapon + 'n' + "The computer chose: " +
chosenOne);
if (weapon === chosenOne) {
alert("It's a tie! Try again to win!");
} else if (weapon === "Rock" && chosenOne === "Paper") {
alert("You lost! Paper beats the rock.");
} else if (weapon === "Paper" && chosenOne === "Scissors") {
alert("You lost! The scissors cut the paper.");
} else if (weapon === "Scissors" && chosenOne === "Rock") {
alert("You lost! The rock beats the scissors.");
} else if (weapon === "Scissors" && chosenOne === "Paper") {
alert("You won! Scissors cut the paper.");
} else if (weapon === "Paper" && chosenOne === "Rock") {
alert("You won! Paper beats the rock.");
} else if (weapon === "Rock" && chosenOne === "Scissors") {
alert("You won! The rock beats the scissors.");
}
} else if (rps === "2") {
alert("Thanks for visiting! See you later.");
} else if (rps !== "1" || rps !== "2") {
alert("Invalid option. Closing game.");
}
I have thought about using switch statements, but since we are still beginners, I haven't grasped the subject fully. Any help is appreciated.
javascript
This is an ongoing school project that I would like to improve. The point is to make the code as efficient (or short) as possible. I would like to reduce it by finding an alternative to all the else ifs when comparing the computer's choice with the user's choice.
Here is the code:
let weapons = ["Rock", "Paper", "Scissors"];
let random = Math.floor(Math.random()*3);
let chosenOne = weapons[random];
let rps = prompt("Welcome to Rock, Paper, Scissors. Would you like to play?"
+ 'n' + "If you do, enter number 1." + 'n' + "If you don't, enter number
2.");
if (rps === "1") {
alert("Remember:" + 'n' + " - Rock beats the scissors" + 'n' + " -
Paper beats the rock" + 'n' + " - The scissors cut the paper");
let weapon = prompt("Make your choice:" + 'n' + "Rock, Paper, Scissors");
weapon = weapon.charAt(0).toUpperCase() + weapon.slice(1).toLowerCase();
alert("You chose: " + weapon + 'n' + "The computer chose: " +
chosenOne);
if (weapon === chosenOne) {
alert("It's a tie! Try again to win!");
} else if (weapon === "Rock" && chosenOne === "Paper") {
alert("You lost! Paper beats the rock.");
} else if (weapon === "Paper" && chosenOne === "Scissors") {
alert("You lost! The scissors cut the paper.");
} else if (weapon === "Scissors" && chosenOne === "Rock") {
alert("You lost! The rock beats the scissors.");
} else if (weapon === "Scissors" && chosenOne === "Paper") {
alert("You won! Scissors cut the paper.");
} else if (weapon === "Paper" && chosenOne === "Rock") {
alert("You won! Paper beats the rock.");
} else if (weapon === "Rock" && chosenOne === "Scissors") {
alert("You won! The rock beats the scissors.");
}
} else if (rps === "2") {
alert("Thanks for visiting! See you later.");
} else if (rps !== "1" || rps !== "2") {
alert("Invalid option. Closing game.");
}
I have thought about using switch statements, but since we are still beginners, I haven't grasped the subject fully. Any help is appreciated.
javascript
javascript
asked Dec 11 at 19:14
TBG
763
763
I don't think that string comparisons are the most optimal way to do this either. You could replace the strings with enums.
– Kapten-N
Dec 13 at 8:30
add a comment |
I don't think that string comparisons are the most optimal way to do this either. You could replace the strings with enums.
– Kapten-N
Dec 13 at 8:30
I don't think that string comparisons are the most optimal way to do this either. You could replace the strings with enums.
– Kapten-N
Dec 13 at 8:30
I don't think that string comparisons are the most optimal way to do this either. You could replace the strings with enums.
– Kapten-N
Dec 13 at 8:30
add a comment |
5 Answers
5
active
oldest
votes
up vote
25
down vote
accepted
You can define an object that define if your move is weak or strong against another. Example:
const myChoice = 'Rock'
const enemyChoice = 'Scissors'
const weapons = {
Rock: {weakTo: 'Paper', strongTo: 'Scissors'},
Paper: {weakTo: 'Scissors', strongTo: 'Rock'},
Scissors: {weakTo: 'Rock', strongTo: 'Paper'}
}
if (weapons[myChoice].strongTo === enemyChoice) {
// I won
return;
}
if (weapons[myChoice].weakTo === enemyChoice) {
// I Lost
return;
}
// tie
1
This also allows you to include custom messages within the data structure for use in your alerts. Eg,Rock: {weakTo: 'Paper', strongTo: 'Scissors', strongMsg: 'Rock smashes scissors', weakMsg: 'Paper wraps rock'}
. Then within the if (beforereturn
) you can doalert(weapons[myChoice].strongMsg)
oralert(weapons[myChoice].weakMsg)
.
– Son of a Beach
Dec 12 at 5:27
Would caching the array-lookup result,weapons[myChoice]
, to avoid having to look it up twice tend to be faster in JavaScript? Also, you could shorten this and make a tad more efficient by checking for the tie condition first. That'd allow you to omit the data forweakTo
orstrongTo
, plus the property resolution.
– Nat
Dec 12 at 10:58
add a comment |
up vote
3
down vote
You can also use an array to check the winner. Order the array so that the winner is always on the right side. Then compare if the machine's choise is the one next to user's choise, like so:
var weapons = ['paper', 'scissors', 'rock'],
user = 'scissors',
machine = 'paper',
uIdx = weapons.indexOf(user),
mIdx = weapons.indexOf(machine),
winner;
if (uIdx !== mIdx) {
winner = (mIdx === (uIdx + 1) % 3) ? 'machine' : 'user';
} else {
winner = 'tie';
}
console.log(winner);
A fiddle to play with.
The modulo operator makes the magic at the end of the array. If user has chosen "rock", the next to it would be undefined, but the modulo operator of 3 % 3
returns 0, hence "paper" is compared to "rock".
add a comment |
up vote
0
down vote
Switch statements goes like that.
Try to look at the e.g i gave you and try to understand the flow of the code.
Best way to learn is with your hands!
Random switch eg:
switch(expression) {
case x:
code block
break; // after every statement e.g: (console.log) you need to use
"break"
case y:
code block
break;
default:
code block
}
Your code:
switch (weapon) {
case chosenOne:
return console.log(alert("It's a tie! Try again to win!"));
break;
case "Rock":
case "Paper":
alert("You lost! Paper beats the rock.");
break;
case "Paper":
case "Scissors":
console.log(alert("You lost! The scissors cut the paper."))
break;
case "Scissors":
case "Rock":
console.log(alert("You lost! The rock beats the scissors."))
break;
case "Scissors":
case "Paper" :
alert("You won! Scissors cut the paper.");
break;
case "Paper":
case "Rock":
console.log(alert("You won! Paper beats the rock."))
break;
case "Rock":
case "Scissors":
alert("You won! The rock beats the scissors.");
default:
return "somthing went wrong"
break;
add a comment |
up vote
0
down vote
I removed some of your variables and combined some, just to make it shorter. I also got rid of the bulk of the if/else
since it's not really needed here. For more info on how a switch
works, check out https://javascript.info/switch.
I also changed up your choices so that you can add multiple win or loss conditions for each choice, in case you wanted to upgrade to Rock,Paper,Scissors,Lizard,Spock ( https://www.youtube.com/watch?v=cSLeBKT7-s ).
// Set up our various choices, how they rank, and their action (can also be array if desired).
const choices = {
Rock : { win:["Scissors"] , action:"beats" } ,
Paper : { win:["Rock"] , action:"beats" } ,
Scissors : { win:["Paper"] , action:"cuts" } ,
Spock : { win:["Rock","Scissors"] , action:"beats" }
} ;
// Use the keys in choices as our selectable items.
const weapons = Object.keys(choices) ;
// Our basic intro.
const rps = prompt("Welcome to Rock, Paper, Scissors. Would you like to play?" + 'n' + "If you do, enter number 1." + 'n' + "If you don't, enter number 2.");
// Set the computer choice.
const chosenOne = weapons[Math.floor(Math.random()*3)];
// This is an example of your switch.
switch (rps) {
case "1" : // Since we used text input, we have to evaluate for a text "number".
alert("Remember:" + 'n' + " - Rock beats the scissors" + 'n' + " - Paper beats the rock" + 'n' + " - The scissors cut the paper");
// Make your choice.
let weapon = prompt("Make your choice:" + 'n' + weapons, "");
// Is our choice valid?
if ( !weapons.includes(weapon) ) {
alert("Invalid choice. Closing Game."); break;
} else {
alert("You chose: " + weapon + 'n' + "The computer chose: " + chosenOne);
}
// Did I win?
alert( compareRPS(weapon,chosenOne) ) ;
break ; // This will break out of the switch. Otherwise will fall through to next case.
case "2":
alert("Thanks for visiting! See you later.");
break ;
default :
alert("Invalid option. Closing game.");
// No break needed here since this is the end of the switch.
}
// I broke the check-you-vs-cpu functionality out into its own function.
function compareRPS(youC,cpuC) {
if ( youC === cpuC ) {
return "It's a tie! Try again to win." ;
}
if (choices[youC].win.includes(cpuC)) {
return "You won! " + youC + " " + choices[youC].action + " " + cpuC + "." ;
} else {
return "You lost! " + cpuC + " " + choices[cpuC].action + " " + youC + "." ;
}
}
NOTE: I also switch between const
and let
. See https://codeburst.io/part-2-var-vs-const-vs-let-69ea73fe76c1 for differences. I mostly use const
to indicate a variable I won't change and let
to be one that I can (within its proper scope). There's also var
, but I didn't need it here.
add a comment |
up vote
-1
down vote
Since more strightforward answers were already provided, I wrote you an alternative using more advance features of javascript. These features are an overkill for the problem at hand, but are useful as a learning exercise.
// Create an array 'battle' as a result from mapping over the given options
const battle = ["Rock", "Paper", "Scissors"].map(
/* The resulting array is conformed of tuples (arrays of 2 values).
The first value is the weapon of choice and the second value is a function.
That function will receive as an argument another weapon and will return the outcome of battling the first option with the second.
Positive number is win, 0 is tie and negative number is loose. */
(weapon, index, array) => [weapon, enemy => {
const res = index - array.findIndex(x => x === enemy)
return !!(res%2)? res : res * -1
}]
/* The reduce transform the array of tuples into an object,
with each choice as a property key and each function as the property value */
).reduce((accumulator, current) => {accumulator[current[0]] = current[1]; return accumulator}, {})
/* Output is just a function that receives your weapon.
It returns a function that receives your enemy's weapon.
Which in turn uses the previous object with functions to get the result.
Finally it uses the result to print one sentence or other, using template strings. */
const output = mine => enemy => {
const result = battle[mine](enemy)
return result > 0 ? `You won! ${mine} beats ${enemy}`
: result < 0 ? `You lost! ${enemy} beats ${mine}`
: "It's a tie! Try again to win"
}
console.log(output("Rock")("Paper"))
3
"not the clearest code, but it's instructional" is an oxymoron, in my opinion.
– Logan Pickup
Dec 12 at 4:01
Not really. It's instructional if you take the time to understand it. Not every lesson needs to be a step by step tutorial. If it is an "ongoing school project", trying new things is more valuable than just solving the problem one way.
– jorbuedo
Dec 12 at 5:52
1
Since OP has declared that they are a new user, some explanation of what this code is doing would be much more instructional. I added an upvote, because I didn't think the downvotes were fair for a correct answer. But, even though it's correct, it's not going to be understandable (or even followable) by a new user.
– Shawn
Dec 13 at 2:13
Fair enough. I edited my answer.
– jorbuedo
Dec 13 at 12:39
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53730900%2fmore-efficient-choice-comparison-for-rock-paper-scissors%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
25
down vote
accepted
You can define an object that define if your move is weak or strong against another. Example:
const myChoice = 'Rock'
const enemyChoice = 'Scissors'
const weapons = {
Rock: {weakTo: 'Paper', strongTo: 'Scissors'},
Paper: {weakTo: 'Scissors', strongTo: 'Rock'},
Scissors: {weakTo: 'Rock', strongTo: 'Paper'}
}
if (weapons[myChoice].strongTo === enemyChoice) {
// I won
return;
}
if (weapons[myChoice].weakTo === enemyChoice) {
// I Lost
return;
}
// tie
1
This also allows you to include custom messages within the data structure for use in your alerts. Eg,Rock: {weakTo: 'Paper', strongTo: 'Scissors', strongMsg: 'Rock smashes scissors', weakMsg: 'Paper wraps rock'}
. Then within the if (beforereturn
) you can doalert(weapons[myChoice].strongMsg)
oralert(weapons[myChoice].weakMsg)
.
– Son of a Beach
Dec 12 at 5:27
Would caching the array-lookup result,weapons[myChoice]
, to avoid having to look it up twice tend to be faster in JavaScript? Also, you could shorten this and make a tad more efficient by checking for the tie condition first. That'd allow you to omit the data forweakTo
orstrongTo
, plus the property resolution.
– Nat
Dec 12 at 10:58
add a comment |
up vote
25
down vote
accepted
You can define an object that define if your move is weak or strong against another. Example:
const myChoice = 'Rock'
const enemyChoice = 'Scissors'
const weapons = {
Rock: {weakTo: 'Paper', strongTo: 'Scissors'},
Paper: {weakTo: 'Scissors', strongTo: 'Rock'},
Scissors: {weakTo: 'Rock', strongTo: 'Paper'}
}
if (weapons[myChoice].strongTo === enemyChoice) {
// I won
return;
}
if (weapons[myChoice].weakTo === enemyChoice) {
// I Lost
return;
}
// tie
1
This also allows you to include custom messages within the data structure for use in your alerts. Eg,Rock: {weakTo: 'Paper', strongTo: 'Scissors', strongMsg: 'Rock smashes scissors', weakMsg: 'Paper wraps rock'}
. Then within the if (beforereturn
) you can doalert(weapons[myChoice].strongMsg)
oralert(weapons[myChoice].weakMsg)
.
– Son of a Beach
Dec 12 at 5:27
Would caching the array-lookup result,weapons[myChoice]
, to avoid having to look it up twice tend to be faster in JavaScript? Also, you could shorten this and make a tad more efficient by checking for the tie condition first. That'd allow you to omit the data forweakTo
orstrongTo
, plus the property resolution.
– Nat
Dec 12 at 10:58
add a comment |
up vote
25
down vote
accepted
up vote
25
down vote
accepted
You can define an object that define if your move is weak or strong against another. Example:
const myChoice = 'Rock'
const enemyChoice = 'Scissors'
const weapons = {
Rock: {weakTo: 'Paper', strongTo: 'Scissors'},
Paper: {weakTo: 'Scissors', strongTo: 'Rock'},
Scissors: {weakTo: 'Rock', strongTo: 'Paper'}
}
if (weapons[myChoice].strongTo === enemyChoice) {
// I won
return;
}
if (weapons[myChoice].weakTo === enemyChoice) {
// I Lost
return;
}
// tie
You can define an object that define if your move is weak or strong against another. Example:
const myChoice = 'Rock'
const enemyChoice = 'Scissors'
const weapons = {
Rock: {weakTo: 'Paper', strongTo: 'Scissors'},
Paper: {weakTo: 'Scissors', strongTo: 'Rock'},
Scissors: {weakTo: 'Rock', strongTo: 'Paper'}
}
if (weapons[myChoice].strongTo === enemyChoice) {
// I won
return;
}
if (weapons[myChoice].weakTo === enemyChoice) {
// I Lost
return;
}
// tie
answered Dec 11 at 19:34
Federkun
22.1k74566
22.1k74566
1
This also allows you to include custom messages within the data structure for use in your alerts. Eg,Rock: {weakTo: 'Paper', strongTo: 'Scissors', strongMsg: 'Rock smashes scissors', weakMsg: 'Paper wraps rock'}
. Then within the if (beforereturn
) you can doalert(weapons[myChoice].strongMsg)
oralert(weapons[myChoice].weakMsg)
.
– Son of a Beach
Dec 12 at 5:27
Would caching the array-lookup result,weapons[myChoice]
, to avoid having to look it up twice tend to be faster in JavaScript? Also, you could shorten this and make a tad more efficient by checking for the tie condition first. That'd allow you to omit the data forweakTo
orstrongTo
, plus the property resolution.
– Nat
Dec 12 at 10:58
add a comment |
1
This also allows you to include custom messages within the data structure for use in your alerts. Eg,Rock: {weakTo: 'Paper', strongTo: 'Scissors', strongMsg: 'Rock smashes scissors', weakMsg: 'Paper wraps rock'}
. Then within the if (beforereturn
) you can doalert(weapons[myChoice].strongMsg)
oralert(weapons[myChoice].weakMsg)
.
– Son of a Beach
Dec 12 at 5:27
Would caching the array-lookup result,weapons[myChoice]
, to avoid having to look it up twice tend to be faster in JavaScript? Also, you could shorten this and make a tad more efficient by checking for the tie condition first. That'd allow you to omit the data forweakTo
orstrongTo
, plus the property resolution.
– Nat
Dec 12 at 10:58
1
1
This also allows you to include custom messages within the data structure for use in your alerts. Eg,
Rock: {weakTo: 'Paper', strongTo: 'Scissors', strongMsg: 'Rock smashes scissors', weakMsg: 'Paper wraps rock'}
. Then within the if (before return
) you can do alert(weapons[myChoice].strongMsg)
or alert(weapons[myChoice].weakMsg)
.– Son of a Beach
Dec 12 at 5:27
This also allows you to include custom messages within the data structure for use in your alerts. Eg,
Rock: {weakTo: 'Paper', strongTo: 'Scissors', strongMsg: 'Rock smashes scissors', weakMsg: 'Paper wraps rock'}
. Then within the if (before return
) you can do alert(weapons[myChoice].strongMsg)
or alert(weapons[myChoice].weakMsg)
.– Son of a Beach
Dec 12 at 5:27
Would caching the array-lookup result,
weapons[myChoice]
, to avoid having to look it up twice tend to be faster in JavaScript? Also, you could shorten this and make a tad more efficient by checking for the tie condition first. That'd allow you to omit the data for weakTo
or strongTo
, plus the property resolution.– Nat
Dec 12 at 10:58
Would caching the array-lookup result,
weapons[myChoice]
, to avoid having to look it up twice tend to be faster in JavaScript? Also, you could shorten this and make a tad more efficient by checking for the tie condition first. That'd allow you to omit the data for weakTo
or strongTo
, plus the property resolution.– Nat
Dec 12 at 10:58
add a comment |
up vote
3
down vote
You can also use an array to check the winner. Order the array so that the winner is always on the right side. Then compare if the machine's choise is the one next to user's choise, like so:
var weapons = ['paper', 'scissors', 'rock'],
user = 'scissors',
machine = 'paper',
uIdx = weapons.indexOf(user),
mIdx = weapons.indexOf(machine),
winner;
if (uIdx !== mIdx) {
winner = (mIdx === (uIdx + 1) % 3) ? 'machine' : 'user';
} else {
winner = 'tie';
}
console.log(winner);
A fiddle to play with.
The modulo operator makes the magic at the end of the array. If user has chosen "rock", the next to it would be undefined, but the modulo operator of 3 % 3
returns 0, hence "paper" is compared to "rock".
add a comment |
up vote
3
down vote
You can also use an array to check the winner. Order the array so that the winner is always on the right side. Then compare if the machine's choise is the one next to user's choise, like so:
var weapons = ['paper', 'scissors', 'rock'],
user = 'scissors',
machine = 'paper',
uIdx = weapons.indexOf(user),
mIdx = weapons.indexOf(machine),
winner;
if (uIdx !== mIdx) {
winner = (mIdx === (uIdx + 1) % 3) ? 'machine' : 'user';
} else {
winner = 'tie';
}
console.log(winner);
A fiddle to play with.
The modulo operator makes the magic at the end of the array. If user has chosen "rock", the next to it would be undefined, but the modulo operator of 3 % 3
returns 0, hence "paper" is compared to "rock".
add a comment |
up vote
3
down vote
up vote
3
down vote
You can also use an array to check the winner. Order the array so that the winner is always on the right side. Then compare if the machine's choise is the one next to user's choise, like so:
var weapons = ['paper', 'scissors', 'rock'],
user = 'scissors',
machine = 'paper',
uIdx = weapons.indexOf(user),
mIdx = weapons.indexOf(machine),
winner;
if (uIdx !== mIdx) {
winner = (mIdx === (uIdx + 1) % 3) ? 'machine' : 'user';
} else {
winner = 'tie';
}
console.log(winner);
A fiddle to play with.
The modulo operator makes the magic at the end of the array. If user has chosen "rock", the next to it would be undefined, but the modulo operator of 3 % 3
returns 0, hence "paper" is compared to "rock".
You can also use an array to check the winner. Order the array so that the winner is always on the right side. Then compare if the machine's choise is the one next to user's choise, like so:
var weapons = ['paper', 'scissors', 'rock'],
user = 'scissors',
machine = 'paper',
uIdx = weapons.indexOf(user),
mIdx = weapons.indexOf(machine),
winner;
if (uIdx !== mIdx) {
winner = (mIdx === (uIdx + 1) % 3) ? 'machine' : 'user';
} else {
winner = 'tie';
}
console.log(winner);
A fiddle to play with.
The modulo operator makes the magic at the end of the array. If user has chosen "rock", the next to it would be undefined, but the modulo operator of 3 % 3
returns 0, hence "paper" is compared to "rock".
var weapons = ['paper', 'scissors', 'rock'],
user = 'scissors',
machine = 'paper',
uIdx = weapons.indexOf(user),
mIdx = weapons.indexOf(machine),
winner;
if (uIdx !== mIdx) {
winner = (mIdx === (uIdx + 1) % 3) ? 'machine' : 'user';
} else {
winner = 'tie';
}
console.log(winner);
var weapons = ['paper', 'scissors', 'rock'],
user = 'scissors',
machine = 'paper',
uIdx = weapons.indexOf(user),
mIdx = weapons.indexOf(machine),
winner;
if (uIdx !== mIdx) {
winner = (mIdx === (uIdx + 1) % 3) ? 'machine' : 'user';
} else {
winner = 'tie';
}
console.log(winner);
answered Dec 11 at 20:46
Teemu
18.2k63471
18.2k63471
add a comment |
add a comment |
up vote
0
down vote
Switch statements goes like that.
Try to look at the e.g i gave you and try to understand the flow of the code.
Best way to learn is with your hands!
Random switch eg:
switch(expression) {
case x:
code block
break; // after every statement e.g: (console.log) you need to use
"break"
case y:
code block
break;
default:
code block
}
Your code:
switch (weapon) {
case chosenOne:
return console.log(alert("It's a tie! Try again to win!"));
break;
case "Rock":
case "Paper":
alert("You lost! Paper beats the rock.");
break;
case "Paper":
case "Scissors":
console.log(alert("You lost! The scissors cut the paper."))
break;
case "Scissors":
case "Rock":
console.log(alert("You lost! The rock beats the scissors."))
break;
case "Scissors":
case "Paper" :
alert("You won! Scissors cut the paper.");
break;
case "Paper":
case "Rock":
console.log(alert("You won! Paper beats the rock."))
break;
case "Rock":
case "Scissors":
alert("You won! The rock beats the scissors.");
default:
return "somthing went wrong"
break;
add a comment |
up vote
0
down vote
Switch statements goes like that.
Try to look at the e.g i gave you and try to understand the flow of the code.
Best way to learn is with your hands!
Random switch eg:
switch(expression) {
case x:
code block
break; // after every statement e.g: (console.log) you need to use
"break"
case y:
code block
break;
default:
code block
}
Your code:
switch (weapon) {
case chosenOne:
return console.log(alert("It's a tie! Try again to win!"));
break;
case "Rock":
case "Paper":
alert("You lost! Paper beats the rock.");
break;
case "Paper":
case "Scissors":
console.log(alert("You lost! The scissors cut the paper."))
break;
case "Scissors":
case "Rock":
console.log(alert("You lost! The rock beats the scissors."))
break;
case "Scissors":
case "Paper" :
alert("You won! Scissors cut the paper.");
break;
case "Paper":
case "Rock":
console.log(alert("You won! Paper beats the rock."))
break;
case "Rock":
case "Scissors":
alert("You won! The rock beats the scissors.");
default:
return "somthing went wrong"
break;
add a comment |
up vote
0
down vote
up vote
0
down vote
Switch statements goes like that.
Try to look at the e.g i gave you and try to understand the flow of the code.
Best way to learn is with your hands!
Random switch eg:
switch(expression) {
case x:
code block
break; // after every statement e.g: (console.log) you need to use
"break"
case y:
code block
break;
default:
code block
}
Your code:
switch (weapon) {
case chosenOne:
return console.log(alert("It's a tie! Try again to win!"));
break;
case "Rock":
case "Paper":
alert("You lost! Paper beats the rock.");
break;
case "Paper":
case "Scissors":
console.log(alert("You lost! The scissors cut the paper."))
break;
case "Scissors":
case "Rock":
console.log(alert("You lost! The rock beats the scissors."))
break;
case "Scissors":
case "Paper" :
alert("You won! Scissors cut the paper.");
break;
case "Paper":
case "Rock":
console.log(alert("You won! Paper beats the rock."))
break;
case "Rock":
case "Scissors":
alert("You won! The rock beats the scissors.");
default:
return "somthing went wrong"
break;
Switch statements goes like that.
Try to look at the e.g i gave you and try to understand the flow of the code.
Best way to learn is with your hands!
Random switch eg:
switch(expression) {
case x:
code block
break; // after every statement e.g: (console.log) you need to use
"break"
case y:
code block
break;
default:
code block
}
Your code:
switch (weapon) {
case chosenOne:
return console.log(alert("It's a tie! Try again to win!"));
break;
case "Rock":
case "Paper":
alert("You lost! Paper beats the rock.");
break;
case "Paper":
case "Scissors":
console.log(alert("You lost! The scissors cut the paper."))
break;
case "Scissors":
case "Rock":
console.log(alert("You lost! The rock beats the scissors."))
break;
case "Scissors":
case "Paper" :
alert("You won! Scissors cut the paper.");
break;
case "Paper":
case "Rock":
console.log(alert("You won! Paper beats the rock."))
break;
case "Rock":
case "Scissors":
alert("You won! The rock beats the scissors.");
default:
return "somthing went wrong"
break;
answered Dec 11 at 19:35
Shibex
113
113
add a comment |
add a comment |
up vote
0
down vote
I removed some of your variables and combined some, just to make it shorter. I also got rid of the bulk of the if/else
since it's not really needed here. For more info on how a switch
works, check out https://javascript.info/switch.
I also changed up your choices so that you can add multiple win or loss conditions for each choice, in case you wanted to upgrade to Rock,Paper,Scissors,Lizard,Spock ( https://www.youtube.com/watch?v=cSLeBKT7-s ).
// Set up our various choices, how they rank, and their action (can also be array if desired).
const choices = {
Rock : { win:["Scissors"] , action:"beats" } ,
Paper : { win:["Rock"] , action:"beats" } ,
Scissors : { win:["Paper"] , action:"cuts" } ,
Spock : { win:["Rock","Scissors"] , action:"beats" }
} ;
// Use the keys in choices as our selectable items.
const weapons = Object.keys(choices) ;
// Our basic intro.
const rps = prompt("Welcome to Rock, Paper, Scissors. Would you like to play?" + 'n' + "If you do, enter number 1." + 'n' + "If you don't, enter number 2.");
// Set the computer choice.
const chosenOne = weapons[Math.floor(Math.random()*3)];
// This is an example of your switch.
switch (rps) {
case "1" : // Since we used text input, we have to evaluate for a text "number".
alert("Remember:" + 'n' + " - Rock beats the scissors" + 'n' + " - Paper beats the rock" + 'n' + " - The scissors cut the paper");
// Make your choice.
let weapon = prompt("Make your choice:" + 'n' + weapons, "");
// Is our choice valid?
if ( !weapons.includes(weapon) ) {
alert("Invalid choice. Closing Game."); break;
} else {
alert("You chose: " + weapon + 'n' + "The computer chose: " + chosenOne);
}
// Did I win?
alert( compareRPS(weapon,chosenOne) ) ;
break ; // This will break out of the switch. Otherwise will fall through to next case.
case "2":
alert("Thanks for visiting! See you later.");
break ;
default :
alert("Invalid option. Closing game.");
// No break needed here since this is the end of the switch.
}
// I broke the check-you-vs-cpu functionality out into its own function.
function compareRPS(youC,cpuC) {
if ( youC === cpuC ) {
return "It's a tie! Try again to win." ;
}
if (choices[youC].win.includes(cpuC)) {
return "You won! " + youC + " " + choices[youC].action + " " + cpuC + "." ;
} else {
return "You lost! " + cpuC + " " + choices[cpuC].action + " " + youC + "." ;
}
}
NOTE: I also switch between const
and let
. See https://codeburst.io/part-2-var-vs-const-vs-let-69ea73fe76c1 for differences. I mostly use const
to indicate a variable I won't change and let
to be one that I can (within its proper scope). There's also var
, but I didn't need it here.
add a comment |
up vote
0
down vote
I removed some of your variables and combined some, just to make it shorter. I also got rid of the bulk of the if/else
since it's not really needed here. For more info on how a switch
works, check out https://javascript.info/switch.
I also changed up your choices so that you can add multiple win or loss conditions for each choice, in case you wanted to upgrade to Rock,Paper,Scissors,Lizard,Spock ( https://www.youtube.com/watch?v=cSLeBKT7-s ).
// Set up our various choices, how they rank, and their action (can also be array if desired).
const choices = {
Rock : { win:["Scissors"] , action:"beats" } ,
Paper : { win:["Rock"] , action:"beats" } ,
Scissors : { win:["Paper"] , action:"cuts" } ,
Spock : { win:["Rock","Scissors"] , action:"beats" }
} ;
// Use the keys in choices as our selectable items.
const weapons = Object.keys(choices) ;
// Our basic intro.
const rps = prompt("Welcome to Rock, Paper, Scissors. Would you like to play?" + 'n' + "If you do, enter number 1." + 'n' + "If you don't, enter number 2.");
// Set the computer choice.
const chosenOne = weapons[Math.floor(Math.random()*3)];
// This is an example of your switch.
switch (rps) {
case "1" : // Since we used text input, we have to evaluate for a text "number".
alert("Remember:" + 'n' + " - Rock beats the scissors" + 'n' + " - Paper beats the rock" + 'n' + " - The scissors cut the paper");
// Make your choice.
let weapon = prompt("Make your choice:" + 'n' + weapons, "");
// Is our choice valid?
if ( !weapons.includes(weapon) ) {
alert("Invalid choice. Closing Game."); break;
} else {
alert("You chose: " + weapon + 'n' + "The computer chose: " + chosenOne);
}
// Did I win?
alert( compareRPS(weapon,chosenOne) ) ;
break ; // This will break out of the switch. Otherwise will fall through to next case.
case "2":
alert("Thanks for visiting! See you later.");
break ;
default :
alert("Invalid option. Closing game.");
// No break needed here since this is the end of the switch.
}
// I broke the check-you-vs-cpu functionality out into its own function.
function compareRPS(youC,cpuC) {
if ( youC === cpuC ) {
return "It's a tie! Try again to win." ;
}
if (choices[youC].win.includes(cpuC)) {
return "You won! " + youC + " " + choices[youC].action + " " + cpuC + "." ;
} else {
return "You lost! " + cpuC + " " + choices[cpuC].action + " " + youC + "." ;
}
}
NOTE: I also switch between const
and let
. See https://codeburst.io/part-2-var-vs-const-vs-let-69ea73fe76c1 for differences. I mostly use const
to indicate a variable I won't change and let
to be one that I can (within its proper scope). There's also var
, but I didn't need it here.
add a comment |
up vote
0
down vote
up vote
0
down vote
I removed some of your variables and combined some, just to make it shorter. I also got rid of the bulk of the if/else
since it's not really needed here. For more info on how a switch
works, check out https://javascript.info/switch.
I also changed up your choices so that you can add multiple win or loss conditions for each choice, in case you wanted to upgrade to Rock,Paper,Scissors,Lizard,Spock ( https://www.youtube.com/watch?v=cSLeBKT7-s ).
// Set up our various choices, how they rank, and their action (can also be array if desired).
const choices = {
Rock : { win:["Scissors"] , action:"beats" } ,
Paper : { win:["Rock"] , action:"beats" } ,
Scissors : { win:["Paper"] , action:"cuts" } ,
Spock : { win:["Rock","Scissors"] , action:"beats" }
} ;
// Use the keys in choices as our selectable items.
const weapons = Object.keys(choices) ;
// Our basic intro.
const rps = prompt("Welcome to Rock, Paper, Scissors. Would you like to play?" + 'n' + "If you do, enter number 1." + 'n' + "If you don't, enter number 2.");
// Set the computer choice.
const chosenOne = weapons[Math.floor(Math.random()*3)];
// This is an example of your switch.
switch (rps) {
case "1" : // Since we used text input, we have to evaluate for a text "number".
alert("Remember:" + 'n' + " - Rock beats the scissors" + 'n' + " - Paper beats the rock" + 'n' + " - The scissors cut the paper");
// Make your choice.
let weapon = prompt("Make your choice:" + 'n' + weapons, "");
// Is our choice valid?
if ( !weapons.includes(weapon) ) {
alert("Invalid choice. Closing Game."); break;
} else {
alert("You chose: " + weapon + 'n' + "The computer chose: " + chosenOne);
}
// Did I win?
alert( compareRPS(weapon,chosenOne) ) ;
break ; // This will break out of the switch. Otherwise will fall through to next case.
case "2":
alert("Thanks for visiting! See you later.");
break ;
default :
alert("Invalid option. Closing game.");
// No break needed here since this is the end of the switch.
}
// I broke the check-you-vs-cpu functionality out into its own function.
function compareRPS(youC,cpuC) {
if ( youC === cpuC ) {
return "It's a tie! Try again to win." ;
}
if (choices[youC].win.includes(cpuC)) {
return "You won! " + youC + " " + choices[youC].action + " " + cpuC + "." ;
} else {
return "You lost! " + cpuC + " " + choices[cpuC].action + " " + youC + "." ;
}
}
NOTE: I also switch between const
and let
. See https://codeburst.io/part-2-var-vs-const-vs-let-69ea73fe76c1 for differences. I mostly use const
to indicate a variable I won't change and let
to be one that I can (within its proper scope). There's also var
, but I didn't need it here.
I removed some of your variables and combined some, just to make it shorter. I also got rid of the bulk of the if/else
since it's not really needed here. For more info on how a switch
works, check out https://javascript.info/switch.
I also changed up your choices so that you can add multiple win or loss conditions for each choice, in case you wanted to upgrade to Rock,Paper,Scissors,Lizard,Spock ( https://www.youtube.com/watch?v=cSLeBKT7-s ).
// Set up our various choices, how they rank, and their action (can also be array if desired).
const choices = {
Rock : { win:["Scissors"] , action:"beats" } ,
Paper : { win:["Rock"] , action:"beats" } ,
Scissors : { win:["Paper"] , action:"cuts" } ,
Spock : { win:["Rock","Scissors"] , action:"beats" }
} ;
// Use the keys in choices as our selectable items.
const weapons = Object.keys(choices) ;
// Our basic intro.
const rps = prompt("Welcome to Rock, Paper, Scissors. Would you like to play?" + 'n' + "If you do, enter number 1." + 'n' + "If you don't, enter number 2.");
// Set the computer choice.
const chosenOne = weapons[Math.floor(Math.random()*3)];
// This is an example of your switch.
switch (rps) {
case "1" : // Since we used text input, we have to evaluate for a text "number".
alert("Remember:" + 'n' + " - Rock beats the scissors" + 'n' + " - Paper beats the rock" + 'n' + " - The scissors cut the paper");
// Make your choice.
let weapon = prompt("Make your choice:" + 'n' + weapons, "");
// Is our choice valid?
if ( !weapons.includes(weapon) ) {
alert("Invalid choice. Closing Game."); break;
} else {
alert("You chose: " + weapon + 'n' + "The computer chose: " + chosenOne);
}
// Did I win?
alert( compareRPS(weapon,chosenOne) ) ;
break ; // This will break out of the switch. Otherwise will fall through to next case.
case "2":
alert("Thanks for visiting! See you later.");
break ;
default :
alert("Invalid option. Closing game.");
// No break needed here since this is the end of the switch.
}
// I broke the check-you-vs-cpu functionality out into its own function.
function compareRPS(youC,cpuC) {
if ( youC === cpuC ) {
return "It's a tie! Try again to win." ;
}
if (choices[youC].win.includes(cpuC)) {
return "You won! " + youC + " " + choices[youC].action + " " + cpuC + "." ;
} else {
return "You lost! " + cpuC + " " + choices[cpuC].action + " " + youC + "." ;
}
}
NOTE: I also switch between const
and let
. See https://codeburst.io/part-2-var-vs-const-vs-let-69ea73fe76c1 for differences. I mostly use const
to indicate a variable I won't change and let
to be one that I can (within its proper scope). There's also var
, but I didn't need it here.
edited Dec 11 at 21:53
answered Dec 11 at 21:45
Shawn
3,3431224
3,3431224
add a comment |
add a comment |
up vote
-1
down vote
Since more strightforward answers were already provided, I wrote you an alternative using more advance features of javascript. These features are an overkill for the problem at hand, but are useful as a learning exercise.
// Create an array 'battle' as a result from mapping over the given options
const battle = ["Rock", "Paper", "Scissors"].map(
/* The resulting array is conformed of tuples (arrays of 2 values).
The first value is the weapon of choice and the second value is a function.
That function will receive as an argument another weapon and will return the outcome of battling the first option with the second.
Positive number is win, 0 is tie and negative number is loose. */
(weapon, index, array) => [weapon, enemy => {
const res = index - array.findIndex(x => x === enemy)
return !!(res%2)? res : res * -1
}]
/* The reduce transform the array of tuples into an object,
with each choice as a property key and each function as the property value */
).reduce((accumulator, current) => {accumulator[current[0]] = current[1]; return accumulator}, {})
/* Output is just a function that receives your weapon.
It returns a function that receives your enemy's weapon.
Which in turn uses the previous object with functions to get the result.
Finally it uses the result to print one sentence or other, using template strings. */
const output = mine => enemy => {
const result = battle[mine](enemy)
return result > 0 ? `You won! ${mine} beats ${enemy}`
: result < 0 ? `You lost! ${enemy} beats ${mine}`
: "It's a tie! Try again to win"
}
console.log(output("Rock")("Paper"))
3
"not the clearest code, but it's instructional" is an oxymoron, in my opinion.
– Logan Pickup
Dec 12 at 4:01
Not really. It's instructional if you take the time to understand it. Not every lesson needs to be a step by step tutorial. If it is an "ongoing school project", trying new things is more valuable than just solving the problem one way.
– jorbuedo
Dec 12 at 5:52
1
Since OP has declared that they are a new user, some explanation of what this code is doing would be much more instructional. I added an upvote, because I didn't think the downvotes were fair for a correct answer. But, even though it's correct, it's not going to be understandable (or even followable) by a new user.
– Shawn
Dec 13 at 2:13
Fair enough. I edited my answer.
– jorbuedo
Dec 13 at 12:39
add a comment |
up vote
-1
down vote
Since more strightforward answers were already provided, I wrote you an alternative using more advance features of javascript. These features are an overkill for the problem at hand, but are useful as a learning exercise.
// Create an array 'battle' as a result from mapping over the given options
const battle = ["Rock", "Paper", "Scissors"].map(
/* The resulting array is conformed of tuples (arrays of 2 values).
The first value is the weapon of choice and the second value is a function.
That function will receive as an argument another weapon and will return the outcome of battling the first option with the second.
Positive number is win, 0 is tie and negative number is loose. */
(weapon, index, array) => [weapon, enemy => {
const res = index - array.findIndex(x => x === enemy)
return !!(res%2)? res : res * -1
}]
/* The reduce transform the array of tuples into an object,
with each choice as a property key and each function as the property value */
).reduce((accumulator, current) => {accumulator[current[0]] = current[1]; return accumulator}, {})
/* Output is just a function that receives your weapon.
It returns a function that receives your enemy's weapon.
Which in turn uses the previous object with functions to get the result.
Finally it uses the result to print one sentence or other, using template strings. */
const output = mine => enemy => {
const result = battle[mine](enemy)
return result > 0 ? `You won! ${mine} beats ${enemy}`
: result < 0 ? `You lost! ${enemy} beats ${mine}`
: "It's a tie! Try again to win"
}
console.log(output("Rock")("Paper"))
3
"not the clearest code, but it's instructional" is an oxymoron, in my opinion.
– Logan Pickup
Dec 12 at 4:01
Not really. It's instructional if you take the time to understand it. Not every lesson needs to be a step by step tutorial. If it is an "ongoing school project", trying new things is more valuable than just solving the problem one way.
– jorbuedo
Dec 12 at 5:52
1
Since OP has declared that they are a new user, some explanation of what this code is doing would be much more instructional. I added an upvote, because I didn't think the downvotes were fair for a correct answer. But, even though it's correct, it's not going to be understandable (or even followable) by a new user.
– Shawn
Dec 13 at 2:13
Fair enough. I edited my answer.
– jorbuedo
Dec 13 at 12:39
add a comment |
up vote
-1
down vote
up vote
-1
down vote
Since more strightforward answers were already provided, I wrote you an alternative using more advance features of javascript. These features are an overkill for the problem at hand, but are useful as a learning exercise.
// Create an array 'battle' as a result from mapping over the given options
const battle = ["Rock", "Paper", "Scissors"].map(
/* The resulting array is conformed of tuples (arrays of 2 values).
The first value is the weapon of choice and the second value is a function.
That function will receive as an argument another weapon and will return the outcome of battling the first option with the second.
Positive number is win, 0 is tie and negative number is loose. */
(weapon, index, array) => [weapon, enemy => {
const res = index - array.findIndex(x => x === enemy)
return !!(res%2)? res : res * -1
}]
/* The reduce transform the array of tuples into an object,
with each choice as a property key and each function as the property value */
).reduce((accumulator, current) => {accumulator[current[0]] = current[1]; return accumulator}, {})
/* Output is just a function that receives your weapon.
It returns a function that receives your enemy's weapon.
Which in turn uses the previous object with functions to get the result.
Finally it uses the result to print one sentence or other, using template strings. */
const output = mine => enemy => {
const result = battle[mine](enemy)
return result > 0 ? `You won! ${mine} beats ${enemy}`
: result < 0 ? `You lost! ${enemy} beats ${mine}`
: "It's a tie! Try again to win"
}
console.log(output("Rock")("Paper"))
Since more strightforward answers were already provided, I wrote you an alternative using more advance features of javascript. These features are an overkill for the problem at hand, but are useful as a learning exercise.
// Create an array 'battle' as a result from mapping over the given options
const battle = ["Rock", "Paper", "Scissors"].map(
/* The resulting array is conformed of tuples (arrays of 2 values).
The first value is the weapon of choice and the second value is a function.
That function will receive as an argument another weapon and will return the outcome of battling the first option with the second.
Positive number is win, 0 is tie and negative number is loose. */
(weapon, index, array) => [weapon, enemy => {
const res = index - array.findIndex(x => x === enemy)
return !!(res%2)? res : res * -1
}]
/* The reduce transform the array of tuples into an object,
with each choice as a property key and each function as the property value */
).reduce((accumulator, current) => {accumulator[current[0]] = current[1]; return accumulator}, {})
/* Output is just a function that receives your weapon.
It returns a function that receives your enemy's weapon.
Which in turn uses the previous object with functions to get the result.
Finally it uses the result to print one sentence or other, using template strings. */
const output = mine => enemy => {
const result = battle[mine](enemy)
return result > 0 ? `You won! ${mine} beats ${enemy}`
: result < 0 ? `You lost! ${enemy} beats ${mine}`
: "It's a tie! Try again to win"
}
console.log(output("Rock")("Paper"))
edited Dec 13 at 12:39
answered Dec 11 at 21:37
jorbuedo
55012
55012
3
"not the clearest code, but it's instructional" is an oxymoron, in my opinion.
– Logan Pickup
Dec 12 at 4:01
Not really. It's instructional if you take the time to understand it. Not every lesson needs to be a step by step tutorial. If it is an "ongoing school project", trying new things is more valuable than just solving the problem one way.
– jorbuedo
Dec 12 at 5:52
1
Since OP has declared that they are a new user, some explanation of what this code is doing would be much more instructional. I added an upvote, because I didn't think the downvotes were fair for a correct answer. But, even though it's correct, it's not going to be understandable (or even followable) by a new user.
– Shawn
Dec 13 at 2:13
Fair enough. I edited my answer.
– jorbuedo
Dec 13 at 12:39
add a comment |
3
"not the clearest code, but it's instructional" is an oxymoron, in my opinion.
– Logan Pickup
Dec 12 at 4:01
Not really. It's instructional if you take the time to understand it. Not every lesson needs to be a step by step tutorial. If it is an "ongoing school project", trying new things is more valuable than just solving the problem one way.
– jorbuedo
Dec 12 at 5:52
1
Since OP has declared that they are a new user, some explanation of what this code is doing would be much more instructional. I added an upvote, because I didn't think the downvotes were fair for a correct answer. But, even though it's correct, it's not going to be understandable (or even followable) by a new user.
– Shawn
Dec 13 at 2:13
Fair enough. I edited my answer.
– jorbuedo
Dec 13 at 12:39
3
3
"not the clearest code, but it's instructional" is an oxymoron, in my opinion.
– Logan Pickup
Dec 12 at 4:01
"not the clearest code, but it's instructional" is an oxymoron, in my opinion.
– Logan Pickup
Dec 12 at 4:01
Not really. It's instructional if you take the time to understand it. Not every lesson needs to be a step by step tutorial. If it is an "ongoing school project", trying new things is more valuable than just solving the problem one way.
– jorbuedo
Dec 12 at 5:52
Not really. It's instructional if you take the time to understand it. Not every lesson needs to be a step by step tutorial. If it is an "ongoing school project", trying new things is more valuable than just solving the problem one way.
– jorbuedo
Dec 12 at 5:52
1
1
Since OP has declared that they are a new user, some explanation of what this code is doing would be much more instructional. I added an upvote, because I didn't think the downvotes were fair for a correct answer. But, even though it's correct, it's not going to be understandable (or even followable) by a new user.
– Shawn
Dec 13 at 2:13
Since OP has declared that they are a new user, some explanation of what this code is doing would be much more instructional. I added an upvote, because I didn't think the downvotes were fair for a correct answer. But, even though it's correct, it's not going to be understandable (or even followable) by a new user.
– Shawn
Dec 13 at 2:13
Fair enough. I edited my answer.
– jorbuedo
Dec 13 at 12:39
Fair enough. I edited my answer.
– jorbuedo
Dec 13 at 12:39
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53730900%2fmore-efficient-choice-comparison-for-rock-paper-scissors%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I don't think that string comparisons are the most optimal way to do this either. You could replace the strings with enums.
– Kapten-N
Dec 13 at 8:30