Last active
November 24, 2022 18:27
-
-
Save vasilionjea/c23dd1a9dfc4a9396642ae960bfd285d to your computer and use it in GitHub Desktop.
Mentoring juniors through rock, paper, scissors
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
/** | |
* ----------------------------------------------------------------- | |
* It works version | |
* ----------------------------------------------------------------- | |
*/ | |
const computerChoiceDisplay = document.getElementById('computer-choice') | |
const playerChoiceDisplay = document.getElementById('player-choice') | |
const resultDisplay = document.getElementById('result') | |
const possibleChoices = document.querySelectorAll('button') | |
let playerChoice | |
let computerChoice | |
possibleChoices.forEach(possibleChoice => possibleChoice.addEventListener('click', (e) =>{ | |
playerChoice = e.target.id | |
playerChoiceDisplay.innerHTML = playerChoice | |
generateComputerChoice() | |
getResult() | |
})) | |
function generateComputerChoice(){ | |
const randomNumber = Math.floor(Math.random() * 3) | |
if (randomNumber === 0) { | |
computerChoice = 'Lapis' | |
} | |
if (randomNumber === 1) { | |
computerChoice = 'Papyrus' | |
} | |
if (randomNumber === 2) { | |
computerChoice = 'Scalpellus' | |
} | |
computerChoiceDisplay.innerHTML = computerChoice | |
} | |
function getResult() { | |
if (computerChoice === playerChoice) { | |
result = "it's a draw!"; | |
} | |
if (computerChoice === 'Lapis' && playerChoice === 'Papyrus') { | |
result = "you win!" | |
} | |
if (computerChoice === 'Lapis' && playerChoice === 'Scalpellus') { | |
result = "you lose!" | |
} | |
if (computerChoice === 'Papyrus' && playerChoice === 'Lapis') { | |
result = "you lose!" | |
} | |
if (computerChoice === 'Papyrus' && playerChoice === 'Scalpellus') { | |
result = "you win!" | |
} | |
if (computerChoice === 'Scalpellus' && playerChoice === 'Lapis') { | |
result = "you win!" | |
} | |
if (computerChoice === 'Scalpellus' && playerChoice === 'Papyrus') { | |
result = "you lose!" | |
} | |
resultDisplay.innerHTML = result | |
} | |
/** | |
* ----------------------------------------------------------------- | |
* It works but better | |
* ----------------------------------------------------------------- | |
*/ | |
// Elements | |
const computerChoiceDisplay = document.getElementById('computer-choice'); | |
const playerChoiceDisplay = document.getElementById('player-choice'); | |
const playerMoves = document.querySelectorAll('#player-moves button'); | |
const resultDisplay = document.getElementById('result'); | |
// Data | |
const ROCK = 'Lapis'; | |
const PAPER = 'Papyrus'; | |
const SCISSORS = 'Scalpellus'; | |
const CHOICES = [ROCK, PAPER, SCISSORS]; | |
const WIN_TEXT = 'You win!'; | |
const LOSE_TEXT = 'You lose!'; | |
function playGame(e) { | |
const computerChoice = CHOICES[Math.floor(Math.random() * 3)]; | |
const playerChoice = CHOICES[parseInt(e.target.dataset.id)]; | |
computerChoiceDisplay.textContent = computerChoice; | |
playerChoiceDisplay.textContent = playerChoice; | |
resultDisplay.textContent = getResult(computerChoice, playerChoice); | |
} | |
function getResult(computer, player) { | |
let result; | |
if (computer === player) { | |
result = "It's a draw!"; | |
} | |
// Rock | |
if (computer === ROCK && player === PAPER) { | |
result = WIN_TEXT; | |
} else if (computer === ROCK && player === SCISSORS) { | |
result = LOSE_TEXT; | |
} | |
// Paper | |
if (computer === PAPER && player === SCISSORS) { | |
result = WIN_TEXT; | |
} else if (computer === PAPER && player === ROCK) { | |
result = LOSE_TEXT; | |
} | |
// Scissors | |
if (computer === SCISSORS && player === ROCK) { | |
result = WIN_TEXT; | |
} else if (computer === SCISSORS && player === PAPER) { | |
result = LOSE_TEXT; | |
} | |
return result; | |
} | |
playerMoves.forEach(move => { | |
move.addEventListener('click', playGame); | |
}); | |
/** | |
* ----------------------------------------------------------------- | |
* OOP version with separation of concerns | |
* ----------------------------------------------------------------- | |
*/ | |
const $ = (selector) => document.querySelector(selector); | |
const Choice = {Rock: 0, Paper: 1, Scissors: 2}; | |
const ChoiceName = { | |
[Choice.Rock]: 'Lapis', | |
[Choice.Paper]: 'Papyrus', | |
[Choice.Scissors]: 'Scalpellus', | |
}; | |
const Result = {Draw: 0, Won: 1, Lost: 2}; | |
const ResultText = { | |
[Result.Draw]: "It's a draw!", | |
[Result.Won]: "You win!", | |
[Result.Lost]: "You lose!", | |
} | |
class Game { | |
state = { | |
computerChoice: null, | |
playerChoice: null, | |
result: null | |
}; | |
setState(newState) { | |
Object.assign(this.state, newState); | |
} | |
getState() { | |
return { ...this.state }; | |
} | |
getResult(computer, player) { | |
let result; | |
if (computer === player) return Result.Draw; | |
switch(computer) { | |
case Choice.Rock: | |
if (player === Choice.Paper) { | |
result = Result.Won; | |
} else if (player === Choice.Scissors) { | |
result = Result.Lost; | |
} | |
break; | |
case Choice.Paper: | |
if (player === Choice.Scissors) { | |
result = Result.Won; | |
} else if (player === Choice.Rock) { | |
result = Result.Lost; | |
} | |
break; | |
case Choice.Scissors: | |
if (player === Choice.Rock) { | |
result = Result.Won; | |
} else if (player === Choice.Paper) { | |
result = Result.Lost; | |
} | |
break; | |
} | |
return result; | |
} | |
play(playerChoice) { | |
const computerChoice = Math.floor(Math.random() * 3); | |
const result = this.getResult(computerChoice, playerChoice); | |
this.setState({ | |
computerChoice, | |
playerChoice, | |
result, | |
}); | |
return this.getState(); | |
} | |
} | |
class GameDisplay { | |
constructor(game) { | |
this.game = game; | |
this.computerChoice = $('#computer-choice'); | |
this.playerChoice = $('#player-choice'); | |
this.result = $('#result'); | |
} | |
start() { | |
const moves = [ | |
{ button: $('#lapis'), choice: Choice.Rock }, | |
{ button: $('#papyrus'), choice: Choice.Paper }, | |
{ button: $('#scalpellus'), choice: Choice.Scissors } | |
]; | |
moves.forEach(move => { | |
move.button.addEventListener('click', () => this.makeMove(move)); | |
}); | |
} | |
makeMove(move) { | |
const { | |
computerChoice, | |
playerChoice, | |
result | |
} = this.game.play(move.choice); | |
this.computerChoice.textContent = ChoiceName[computerChoice]; | |
this.playerChoice.textContent = ChoiceName[playerChoice]; | |
this.result.textContent = ResultText[result]; | |
} | |
} | |
// Off we go! | |
const gameDisplay = new GameDisplay(new Game); | |
gameDisplay.start(); | |
/** | |
* ----------------------------------------------------------------- | |
* OOP version but simplified | |
* ----------------------------------------------------------------- | |
*/ | |
const $ = (selector) => document.querySelector(selector); | |
const Choice = {Rock: 0, Paper: 1, Scissors: 2}; | |
const ChoiceName = { | |
[Choice.Rock]: 'Lapis', | |
[Choice.Paper]: 'Papyrus', | |
[Choice.Scissors]: 'Scalpellus', | |
}; | |
const Result = {Draw: 0, Won: 1, Lost: 2}; | |
const ResultText = { | |
[Result.Draw]: "It's a draw!", | |
[Result.Won]: "You win!", | |
[Result.Lost]: "You lose!", | |
} | |
const WinningChoice = { | |
[Choice.Rock]: Choice.Scissors, | |
[Choice.Paper]: Choice.Rock, | |
[Choice.Scissors]: Choice.Paper, | |
}; | |
class Game { | |
state = { | |
computerChoice: null, | |
playerChoice: null, | |
result: null | |
}; | |
setState(newState) { | |
Object.assign(this.state, newState); | |
} | |
getState() { | |
return { ...this.state }; | |
} | |
getResult(computerChoice, playerChoice) { | |
if (computerChoice === playerChoice) { | |
return Result.Draw; | |
} else if (WinningChoice[computerChoice] === playerChoice) { | |
return Result.Lost; | |
} else { | |
return Result.Won; | |
} | |
} | |
play(playerChoice) { | |
const computerChoice = Math.floor(Math.random() * 3); | |
const result = this.getResult(computerChoice, playerChoice); | |
this.setState({ | |
computerChoice, | |
playerChoice, | |
result, | |
}); | |
return this.getState(); | |
} | |
} | |
class GameDisplay { | |
constructor(game) { | |
this.game = game; | |
this.computerChoice = $('#computer-choice'); | |
this.playerChoice = $('#player-choice'); | |
this.result = $('#result'); | |
} | |
start() { | |
const moves = [ | |
{ button: $('#lapis'), choice: Choice.Rock }, | |
{ button: $('#papyrus'), choice: Choice.Paper }, | |
{ button: $('#scalpellus'), choice: Choice.Scissors } | |
]; | |
moves.forEach(move => { | |
move.button.addEventListener('click', () => this.makeMove(move)); | |
}); | |
} | |
makeMove(move) { | |
const { | |
computerChoice, | |
playerChoice, | |
result | |
} = this.game.play(move.choice); | |
this.computerChoice.textContent = ChoiceName[computerChoice]; | |
this.playerChoice.textContent = ChoiceName[playerChoice]; | |
this.result.textContent = ResultText[result]; | |
} | |
} | |
// Off we go! | |
const gameDisplay = new GameDisplay(new Game); | |
gameDisplay.start(); | |
/** | |
* ----------------------------------------------------------------- | |
* What else? | |
* ----------------------------------------------------------------- | |
* - Unit Tests | |
* - Error/noop states (what happens if an argument is undefined?) | |
* - DOM performance (e.g. event delegate & detach, querying/updating) | |
* - State immutability | |
* - Typescript (e.g. enums, private class members, etc) | |
* - OOP vs Functional | |
* - Event Driven vs Dependency Injection | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment