More efficient choice comparison for Rock Paper Scissors












14















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.










share|improve this question























  • 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 '18 at 8:30
















14















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.










share|improve this question























  • 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 '18 at 8:30














14












14








14


1






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.










share|improve this question














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






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Dec 11 '18 at 19:14









TBGTBG

783




783













  • 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 '18 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 '18 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 '18 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 '18 at 8:30












5 Answers
5






active

oldest

votes


















26














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





share|improve this answer



















  • 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 '18 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 '18 at 10:58





















3














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






share|improve this answer































    1














    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.






    share|improve this answer

































      0














      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;





      share|improve this answer































        -1














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





        share|improve this answer





















        • 3





          "not the clearest code, but it's instructional" is an oxymoron, in my opinion.

          – Logan Pickup
          Dec 12 '18 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 '18 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 '18 at 2:13











        • Fair enough. I edited my answer.

          – jorbuedo
          Dec 13 '18 at 12:39











        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',
        autoActivateHeartbeat: false,
        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
        });


        }
        });














        draft saved

        draft discarded


















        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









        26














        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





        share|improve this answer



















        • 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 '18 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 '18 at 10:58


















        26














        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





        share|improve this answer



















        • 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 '18 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 '18 at 10:58
















        26












        26








        26







        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





        share|improve this answer













        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






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Dec 11 '18 at 19:34









        FederkunFederkun

        22.5k74766




        22.5k74766








        • 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 '18 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 '18 at 10:58
















        • 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 at 10:58















        3














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






        share|improve this answer




























          3














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






          share|improve this answer


























            3












            3








            3







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






            share|improve this answer













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






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Dec 11 '18 at 20:46









            TeemuTeemu

            18.3k63571




            18.3k63571























                1














                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.






                share|improve this answer






























                  1














                  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.






                  share|improve this answer




























                    1












                    1








                    1







                    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.






                    share|improve this answer















                    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.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Dec 11 '18 at 21:53

























                    answered Dec 11 '18 at 21:45









                    ShawnShawn

                    3,53511324




                    3,53511324























                        0














                        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;





                        share|improve this answer




























                          0














                          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;





                          share|improve this answer


























                            0












                            0








                            0







                            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;





                            share|improve this answer













                            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;






                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Dec 11 '18 at 19:35









                            ShibexShibex

                            216




                            216























                                -1














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





                                share|improve this answer





















                                • 3





                                  "not the clearest code, but it's instructional" is an oxymoron, in my opinion.

                                  – Logan Pickup
                                  Dec 12 '18 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 '18 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 '18 at 2:13











                                • Fair enough. I edited my answer.

                                  – jorbuedo
                                  Dec 13 '18 at 12:39
















                                -1














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





                                share|improve this answer





















                                • 3





                                  "not the clearest code, but it's instructional" is an oxymoron, in my opinion.

                                  – Logan Pickup
                                  Dec 12 '18 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 '18 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 '18 at 2:13











                                • Fair enough. I edited my answer.

                                  – jorbuedo
                                  Dec 13 '18 at 12:39














                                -1












                                -1








                                -1







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





                                share|improve this answer















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






                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited Dec 13 '18 at 12:39

























                                answered Dec 11 '18 at 21:37









                                jorbuedojorbuedo

                                651115




                                651115








                                • 3





                                  "not the clearest code, but it's instructional" is an oxymoron, in my opinion.

                                  – Logan Pickup
                                  Dec 12 '18 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 '18 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 '18 at 2:13











                                • Fair enough. I edited my answer.

                                  – jorbuedo
                                  Dec 13 '18 at 12:39














                                • 3





                                  "not the clearest code, but it's instructional" is an oxymoron, in my opinion.

                                  – Logan Pickup
                                  Dec 12 '18 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 '18 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 '18 at 2:13











                                • Fair enough. I edited my answer.

                                  – jorbuedo
                                  Dec 13 '18 at 12:39








                                3




                                3





                                "not the clearest code, but it's instructional" is an oxymoron, in my opinion.

                                – Logan Pickup
                                Dec 12 '18 at 4:01





                                "not the clearest code, but it's instructional" is an oxymoron, in my opinion.

                                – Logan Pickup
                                Dec 12 '18 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 '18 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 '18 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 '18 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 '18 at 2:13













                                Fair enough. I edited my answer.

                                – jorbuedo
                                Dec 13 '18 at 12:39





                                Fair enough. I edited my answer.

                                – jorbuedo
                                Dec 13 '18 at 12:39


















                                draft saved

                                draft discarded




















































                                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.




                                draft saved


                                draft discarded














                                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





















































                                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







                                Popular posts from this blog

                                How do I know what Microsoft account the skydrive app is syncing to?

                                When does type information flow backwards in C++?

                                Grease: Live!