Skip to content

Instantly share code, notes, and snippets.

@azrikahar
Last active April 20, 2020 08:22
Show Gist options
  • Save azrikahar/5a77a68fb03d678192c6f5a638e21621 to your computer and use it in GitHub Desktop.
Save azrikahar/5a77a68fb03d678192c6f5a638e21621 to your computer and use it in GitHub Desktop.
Sample code for Rock, Paper & Scissors game in response to Reddit thread: https://www.reddit.com/r/learnjavascript/comments/g4jiq8/at_long_last_i_have_finished_my_rock_paper/
// Modified the ordering of these moves so we can do an easier comparison later.
// selectMove sounds more of a verb like a function doing something, so renaming
// to "moves" to signify it is a collection/array of move.
const moves = ["Rock", "Scissors", "Paper"];
let playerScore = 0;
let computerScore = 0;
// Using getComputerSelection() instead of computerPlay()
// lets us know that we will indeed GET something from it,
// ie. the function will return something.
function getComputerSelection() {
const randomIndex = Math.floor(Math.random() * moves.length);
const computerSelection = moves[randomIndex];
return computerSelection;
}
// Utility function to capitalize 1st letter
// credit to: https://flaviocopes.com/how-to-uppercase-first-letter-javascript/
function capitalize(s) {
if (typeof s !== "string") return "";
return s.charAt(0).toUpperCase() + s.slice(1);
}
// The % in JavaScript is Remainder rather than the usual Modulo operator used elsewhere,
// So we use this utility function to perform it.
// credit to: https://stackoverflow.com/a/17323608
function mod(n, m) {
return ((n % m) + m) % m;
}
// Your oneRound() function actually gets user input only
// whereas the computerSelection is generated in this function,
// so we can just remove the second argument you had for this function.
// Perhaps function name can be renamed, but it's not the main point in this scenario.
function oneRound(playerInput) {
// Changed playerSelection param to playerInput, so later on we have consistent variables to compare: playerSelection vs computerSelection
// rather than "lowerCase vs computerSelection" where the lowerCase isn't readily obvious what it is.
const playerInputLowerCase = playerInput.toLowerCase();
const playerSelection = capitalize(playerInputLowerCase);
const computerSelection = getComputerSelection();
// We get the index of playerSelection & computerSelection for "greater than" comparison to see who's selection is the winning one
const playerSelectionIndex = moves.findIndex((move) => move === playerSelection);
const computerSelectionIndex = moves.findIndex((move) => move === computerSelection);
// Set a variable for roundMsg so we don't have to reuse getElementById many times.
const roundMsg = document.getElementById("roundMsg");
// Return if playerSelection is not found in the array. find() returns -1 if it's not found.
// Returning early also prevent the need of executing needless comparison of selection since this check
// was in your final ELSE IF statement in the whole chain.
if (playerSelectionIndex === -1) {
roundMsg.textContent = "Invalid selection, please try again.";
return;
}
// Return early as well if it's a tie.
// Here we used the Template Literal syntax so we can add variable(s) inside strings
// rather than concatenating them using plus signs.
if (playerSelectionIndex === computerSelectionIndex) {
const move = moves[playerSelectionIndex];
roundMsg.textContent = `It is a Tie! ${move} are equal.`;
return;
}
// We use playerSelectionIndex minus computerSelectionIndex because of how we arranged the moves array.
// Imagine the 3 moves as a looping circle or triangle, refer to this image: https://www.pngitem.com/pimgs/m/266-2667226_rock-paper-scissors-rules-hd-png-download.png
// Rock going through the arrow 1 time, means Rock wins vs Scissors. If Rock goes through 2 arrows, means it's vs Paper, and it losses.
// Similarly, Paper going 2 times, means it losses to Scissors. But if Paper goes 1 time, means it wins vs Rock.
// Since the index of Rock Scissors Paper (in moves array) are 0, 1 and 2 respectively, the result modulo 3
// will tell us there are 1 or 2 arrows in between.
// Example A: player choose Rock (0), computer choose Scissors (1). 1 - 0 equals 1, then 1 mod 3 is 1 (our move 1 arrow to theirs), player wins.
// Example B: player choose Scissors (1), computer chooses Rock (0). 0 - 1 equals -1. then -1 mod 3 is 2 (our move 2 arrows to theirs), computer wins.
const comparisonResult = mod(computerSelectionIndex - playerSelectionIndex, 3);
// We increment score first before adding it in the roundMsg so it's clearer compared to inserting it in the same line as before.
if (comparisonResult === 1) {
playerScore += 1;
roundMsg.textContent = `You Win! ${playerSelection} beats ${computerSelection}! Player's score is ${playerScore}`;
} else if (comparisonResult === 2) {
computerScore += 1;
roundMsg.textContent = `You Lose! ${computerSelection} beats ${playerSelection}! Computer's score is ${computerScore}`;
}
}
function game() {
const result = prompt("Rock, Paper, or Scissors? First to five wins!");
// there's nothing wrong in putting a function inside console.log when it returns a value,
// however oneRound() in this case doesn't really return a value and more so perform specific tasks/comparisons,
// therefore it will be misleading in this case.
oneRound(result);
document.getElementById("p1Button").innerHTML = playerScore;
document.getElementById("cpuButton").innerHTML = computerScore;
const resultMsg = document.getElementById("resultMsg");
if (playerScore > computerScore) {
resultMsg.textContent = "You are Winning! " + playerScore + " to " + computerScore;
} else if (playerScore < computerScore) {
resultMsg.textContent = "The computer is Winning! " + computerScore + " to " + playerScore;
} else if (playerScore === computerScore) {
resultMsg.textContent = "You are currently tied for the lead " + playerScore + " to " + computerScore;
}
if (playerScore === 5) {
resultMsg.textContent = "YOU WON! Please refresh to play again.";
} else if (computerScore === 5) {
resultMsg.textContent = "YOU LOSE! Please refresh to play again.";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment