Skip to content

Instantly share code, notes, and snippets.

@vasilionjea
Last active November 24, 2022 18:27
Show Gist options
  • Save vasilionjea/c23dd1a9dfc4a9396642ae960bfd285d to your computer and use it in GitHub Desktop.
Save vasilionjea/c23dd1a9dfc4a9396642ae960bfd285d to your computer and use it in GitHub Desktop.
Mentoring juniors through rock, paper, scissors
/**
* -----------------------------------------------------------------
* 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