Rock, Paper, Scissors Game
Il Progetto
Gioco interattivo Rock, Paper, Scissors sviluppato con vanilla JavaScript, DOM manipulation e logica di gioco completa. Un progetto di ripasso che consolida tutti i concetti appresi finora.
Codice Sorgente
- index.html
- styles.css
- script.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Rock, Paper, Scissors game</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Let's play Rock, Paper, Scissors!</h1>
<main>
<details class="rules-container">
<summary>Rules to the game</summary>
<p>You will be playing against the computer.</p>
<p>You can choose between Rock, Paper, and Scissors.</p>
<p>The first one to three points wins.</p>
<p>Here are the rules to getting a point in the game:</p>
<ul>
<li>Rock beats Scissors</li>
<li>Scissors beats Paper</li>
<li>Paper beats Rock</li>
</ul>
<p>
If the player and computer choose the same option (Ex. Paper and
Paper), then no one gets the point.
</p>
</details>
<div class="score-container">
<strong
>Player Score: <span class="score" id="player-score">0</span></strong
>
<strong
>Computer Score:
<span class="score" id="computer-score">0</span></strong
>
</div>
<section class="options-container">
<h2>Choose an option:</h2>
<div class="btn-container">
<button id="rock-btn" class="btn">Rock</button>
<button id="paper-btn" class="btn">Paper</button>
<button id="scissors-btn" class="btn">Scissors</button>
</div>
</section>
<div class="results-container">
<p id="results-msg"></p>
<p id="winner-msg"></p>
<button class="btn" id="reset-game-btn">Play again?</button>
</div>
</main>
<script src="./script.js"></script>
</body>
</html>
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--very-dark-blue: #0a0a23;
--white: #ffffff;
--yellow: #f1be32;
--golden-yellow: #feac32;
}
body {
background-color: var(--very-dark-blue);
text-align: center;
color: var(--white);
}
h1 {
margin: 15px 0 20px;
}
.btn {
cursor: pointer;
width: 100px;
margin: 10px;
color: var(--very-dark-blue);
background-color: var(--golden-yellow);
background-image: linear-gradient(#fecc4c, #ffac33);
border-color: var(--golden-yellow);
border-width: 3px;
}
.btn:hover {
background-image: linear-gradient(#ffcc4c, #f89808);
}
.rules-container {
padding: 10px 0;
margin: auto;
border-radius: 15px;
border: 5px solid var(--yellow);
background-color: var(--white);
color: var(--very-dark-blue);
}
.rules-container ul {
list-style-type: none;
}
.rules-container p {
margin: 10px 0;
}
@media (min-width: 760px) {
.rules-container {
width: 60%;
}
}
.score-container {
display: flex;
justify-content: space-around;
margin: 30px 0;
font-size: 1.2rem;
}
.score {
font-weight: 500;
}
.results-container {
font-size: 1.3rem;
margin: 15px 0;
}
#winner-msg {
margin-top: 25px;
}
#reset-game-btn {
display: none;
margin: 20px auto;
}
function getRandomComputerResult() {
const options = ["Rock", "Paper", "Scissors"];
const randomIndex = Math.floor(Math.random() * options.length);
return options[randomIndex];
}
function hasPlayerWonTheRound(player, computer) {
return (
(player === "Rock" && computer === "Scissors") ||
(player === "Scissors" && computer === "Paper") ||
(player === "Paper" && computer === "Rock")
);
}
let playerScore = 0;
let computerScore = 0;
function getRoundResults(userOption) {
const computerResult = getRandomComputerResult();
if (hasPlayerWonTheRound(userOption, computerResult)) {
playerScore++;
return `Player wins! ${userOption} beats ${computerResult}`;
} else if (computerResult === userOption) {
return `It's a tie! Both chose ${userOption}`;
} else {
computerScore++;
return `Computer wins! ${computerResult} beats ${userOption}`;
}
}
const playerScoreSpanElement = document.getElementById("player-score");
const computerScoreSpanElement = document.getElementById("computer-score");
const roundResultsMsg = document.getElementById("results-msg");
const winnerMsgElement = document.getElementById("winner-msg");
const optionsContainer = document.querySelector(".options-container");
const resetGameBtn = document.getElementById("reset-game-btn");
function showResults(userOption) {
roundResultsMsg.innerText = getRoundResults(userOption);
computerScoreSpanElement.innerText = computerScore;
playerScoreSpanElement.innerText = playerScore;
if (playerScore === 3 || computerScore === 3) {
winnerMsgElement.innerText = `${
playerScore === 3 ? "Player" : "Computer"
} has won the game!`;
resetGameBtn.style.display = "block";
optionsContainer.style.display = "none";
}
};
function resetGame() {
playerScore = 0;
computerScore = 0;
playerScoreSpanElement.innerText = "0";
computerScoreSpanElement.innerText = "0";
resetGameBtn.style.display = "none";
optionsContainer.style.display = "block";
winnerMsgElement.innerText = "";
roundResultsMsg.innerText = "";
};
resetGameBtn.addEventListener("click", resetGame);
const rockBtn = document.getElementById("rock-btn");
const paperBtn = document.getElementById("paper-btn");
const scissorsBtn = document.getElementById("scissors-btn");
rockBtn.addEventListener("click", function () {
showResults("Rock");
});
paperBtn.addEventListener("click", function () {
showResults("Paper");
});
scissorsBtn.addEventListener("click", function () {
showResults("Scissors");
});
L’intensità cognitiva del ripasso
Questo progetto è stato piuttosto impegnativo dal punto di vista cognitivo. Anche se era composto da soli 6 step, ognuno di essi mi ha richiesto un ripasso totale della maggior parte dei concetti imparati.
Il vademecum ha calzato a pennello ed è stato super interessante modificarlo man mano che procedevo.
Si potrebbe dire che questo progetto abbia funzionato come un vero e proprio “validatore” del vademecum: mi sono basato su di esso e l’ho migliorato proprio in funzione dei concetti che necessitavano maggiore chiarezza, completezza e anche l’aggiunta di sintassi più concise ed efficienti.
La sfida del “solo JavaScript”
A volte, come in questo caso, non si parte scrivendo HTML e CSS, ma solo JavaScript. Ammetto che questa cosa mi pesa sempre un po’, come le altre volte, perché mi piace portare i progetti avanti dalla A alla Z.
Cosa Ho Imparato
Logica di gioco avanzata:
Math.random()eMath.floor()per la generazione casuale- Funzioni logiche con ritorno booleano per determinare il vincitore
- State management con variabili globali (
playerScore,computerScore)
DOM Manipulation complessa:
document.getElementById()per elementi specificidocument.querySelector()per selettori CSSinnerTextper aggiornamenti dinamici dei contenutistyle.displayper mostrare/nascondere elementi in modo condizionale
Padronanza degli eventi:
addEventListener()con callback functions- Event listener multipli per pulsanti diversi
- Gestione degli eventi per reset e restart del gioco
Flusso di gioco condizionale:
- Operatori ternari per messaggi dinamici
- Logica if/else complessa per determinare i risultati
- Controllo dello stato del gioco per la fine della partita
Architettura delle funzioni:
getRandomComputerResult()– scelta casuale del computerhasPlayerWonTheRound()– logica di vittoriagetRoundResults()– gestione completa del roundshowResults()– aggiornamento della UIresetGame()– ripristino dello stato iniziale
Pattern JavaScript osservati:
- Return statement con logica complessa
- Template literals per messaggi dinamici
- Logica booleana per le meccaniche di gioco
Riflessione
Questo progetto ha davvero validato il mio vademecum. È stato incredibile vedere come ogni concetto si incastrasse perfettamente e come il vademecum mi guidasse passo dopo passo.
Prossimo progetto: Imparare i Basic String and Array Methods costruendo un Music Player