Last active
April 20, 2020 08:22
-
-
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/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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