I started studying web development a few months ago and to practice my skills I decided to do the game of rock, paper, scissors.
Here are some questions for review:
- Is the use of HTML semantics correct and how could I improve it?
- How could I improve the CSS and JavaScript code in terms of readability, optimization and best practices?
- Are the class, functions and variable names correct (I am not a native English speaker and I am learning, so there may be things misspelled)?
- Is the style of the code correct?
Code:
let counter_rounds = 0;
let player_wins = 0;
let computer_wins = 0;
let draws = 0;
const ROUNDS_PER_GAME = 3;
const choices = ["ROCK", "PAPER", "SCISSORS"];
const score_human = document.querySelector(".score-human");
const score_computer = document.querySelector(".score-computer");
const result_round = document.querySelector(".result-round");
const result_human = document.querySelector(".result-human");
const final_result = document.querySelector(".final-result");
const result_computer = document.querySelector(".result-computer");
const image_container_player = document.querySelector(".player-choose .image-container");
const image_container_computer = document.querySelector(".computer-choose .image-container");
const buttons = document.querySelector(".buttons-container");
const new_game_button = document.querySelector(".new-game-button");
buttons.addEventListener("click", play);
new_game_button.addEventListener("click", reset_game);
function play(event) {
counter_rounds++;
let player, computer;
if (
event.target.classList.contains("btn") ||
event.target.closest(".button-container") &&
counter_rounds < 3
) {
const button_value = event.target
.closest(".button-container")
.getAttribute("data-value");
player = choices.indexOf(button_value);
computer = Math.floor(Math.random() * 3);
check_winner_round(player, computer);
}
if (counter_rounds === ROUNDS_PER_GAME) {
disable_buttons();
check_winner_game();
new_game_button.style.display = "block";
}
}
function check_winner_round(player, computer) {
if (player === computer) {
result_round.textContent = "It's a draw.";
result_human.textContent = `You chose ${choices[player]}.`;
result_computer.textContent = `Computer choose ${choices[computer]}.`;
draws++;
} else if ((player-computer+3) % 3 === 1) {
score_human.textContent = Number(score_human.textContent) + 1;
result_round.textContent = "You won.";
result_human.textContent = `You chose ${choices[player]}.`;
result_computer.textContent = `Computer chose ${choices[computer]}.`;
player_wins++;
} else {
score_computer.textContent = Number(score_computer.textContent) + 1;
result_round.textContent = "You lost.";
result_human.textContent = `You chose ${choices[player]}.`;
result_computer.textContent = `Computer chose ${choices[computer]}.`;
computer_wins++;
}
update_image_containers(player, computer);
}
function check_winner_game() {
if (player_wins === computer_wins)
final_result.textContent = "It's a draw.";
else if (player_wins > computer_wins)
final_result.textContent = "You won the set.";
else
final_result.textContent = "Computer wins the set.";
}
function update_image_containers(player, computer) {
const image_player = `img/${choices[player].toLowerCase()}.png`;
const image_computer = `img/${choices[computer].toLowerCase()}.png`;
image_container_player.style.backgroundImage = `url(${image_player})`;
image_container_computer.style.backgroundImage = `url(${image_computer})`;
image_container_player.classList.remove("empty");
image_container_computer.classList.remove("empty");
}
function reset_image_containers() {
image_container_player.classList.add("empty");
image_container_computer.classList.add("empty");
image_container_player.style.backgroundImage = "";
image_container_computer.style.backgroundImage = "";
}
function set_buttons_state(disabled) {
const buttonContainer = document.querySelector(".buttons-container");
buttonContainer.classList.toggle("disabled", disabled);
}
function disable_buttons() {
set_buttons_state(true);
}
function enable_buttons() {
set_buttons_state(false);
}
function reset_game() {
score_human.textContent = 0;
score_computer.textContent = 0;
result_round.textContent = "";
result_human.textContent = "";
result_computer.textContent = "";
final_result.textContent = "";
player_wins = 0;
computer_wins = 0;
draws = 0;
counter_rounds = 0;
reset_image_containers();
enable_buttons();
new_game_button.style.display = "none";
}
*,
*::before,
*::after {
box-sizing: border-box;
padding: 0;
margin: 0;
}
body {
background-color: #000;
max-height: 100vh;
}
header {
margin-top: 20px;
margin-bottom: 20px;
}
h1 {
color: #f3ffff;
text-align: center;
}
.scoreboard {
display: grid;
grid-template-columns: repeat(2, 1fr);
justify-items: center;
align-items: center;
background-color: #014689;
height: 150px;
width: 400px;
margin: 0 auto;
border: 4px solid #f3ffff;
border-radius: 20px;
}
.player-score,
.computer-score {
display: flex;
flex-direction: column;
justify-content: space-around;
height: inherit;
width: 100px;
}
.player,
.computer {
color: #f3ffff;
font-weight: bold;
font-size: 25px;
text-decoration: underline #f3ffff;
display: flex;
justify-content: center;
align-items: center;
}
.score-computer,
.score-human {
background-color: #000;
border: 4px solid #f3ffff;
border-radius: 10px;
color: #ea4225;
font-family: 'Seven Segment', sans-serif;
font-weight: bold;
font-size: 55px;
display: flex;
justify-content: space-around;
align-items: center;
}
.game-board-container {
display: flex;
justify-content: center;
align-items: center;
height: 385px;
max-width: 100vw;
padding-left: 10%;
padding-right: 10%;
}
.game-board {
display: flex;
justify-content: center;
align-items: center;
}
.player-choose p,
.computer-choose p {
color: #ffd700;
font-weight: bold;
font-size: 25px;
text-decoration: underline #ffd700;
}
.circle {
background-color: #87ceeb;
border: 3px solid #3b83bd;
border-radius: 50%;
height: 250px;
width: 250px;
margin-top: 20px;
}
.image-container {
background-repeat: no-repeat;
background-size: 80% 80%;
background-position: center;
height: 100%;
width: 100%;
}
.vs-image {
background-repeat: no-repeat;
background-size: 100% 100%;
background-position: center;
height: 200px;
width: 200px;
}
.game-play p {
font-family: 'Proxima Nova', sans-serif;
font-weight: bold;
text-align: center;
}
.win-condition {
color: #f5f5dc;
font-size: 18px;
}
.round-results {
color: #f3ffff;
font-size: 20px;
margin-top: 20px;
margin-bottom: 50px;
}
.choose-option {
font-family: 'Proxima Nova', sans-serif;
font-weight: bold;
font-size: 25px;
color: red;
}
.buttons-container {
display: flex;
justify-content: center;
max-width: 100vw;
margin-top: 10px;
}
.button-container {
background-color: #014689;
width: 150px;
height: 70px;
padding: 20px;
margin-left: 20px;
border-radius: 5px;
cursor: pointer;
}
.btn {
background: none;
border: 0;
color: #f3ffff;
cursor: pointer;
font: inherit;
font-weight: bold;
line-height: normal;
overflow: visible;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: space-evenly;
padding: 0 10px;
}
.btn img {
width: 50px;
height: 50px;
background-color: transparent;
}
.image-container.empty {
background: none;
}
.new-game-button {
background-color: #014689;
border-radius: 5px;
width: 130px;
cursor: pointer;
display: none;
margin: 0 auto;
margin-top: 10px;
}
.disabled {
opacity: 0.5;
pointer-events: none;
cursor: not-allowed;
}
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Rock, Paper, Scissors</title>
<link rel="stylesheet" href="css/styles.css" />
<link
href="https://fonts.cdnfonts.com/css/seven-segment"
rel="stylesheet"
/>
<link
href="https://fonts.cdnfonts.com/css/proxima-nova-2"
rel="stylesheet"
/>
</head>
<body>
<header><h1>Rock, Paper, Scissors</h1></header>
<main>
<section class="scoreboard">
<div class="player-score">
<p class="player">PLAYER</p>
<p class="score-human">0</p>
</div>
<div class="computer-score">
<p class="computer">COMPUTER</p>
<p class="score-computer">0</p>
</div>
</section>
<section class="game-board-container">
<div class="game-board">
<div class="player-choose">
<p class="player">PLAYER</p>
<div class="circle">
<div class="image-container empty"></div>
</div>
</div>
<img src="img/vs.png" class="vs-image" />
<div class="computer-choose">
<p class="computer">COMPUTER</p>
<div class="circle">
<div class="image-container empty"></div>
</div>
</div>
</div>
</section>
<section class="game-play">
<p class="win-condition">The best score out of 3 is the winner.</p>
<div class="round-results">
<p class="result-human"></p>
<p class="result-computer"></p>
<p class="result-round"></p>
<p class="final-result"></p>
<button class="btn new-game-button">New Game</button>
</div>
<p class="choose-option">Choose an option:</p>
<div class="buttons-container">
<div class="button-container" data-value="ROCK">
<button class="btn game-button">
<img src="img/rock_emoji.png" alt="rock_button">
Rock
</button>
</div>
<div class="button-container" data-value="PAPER">
<button class="btn game-button">
<img src="img/paper_emoji.png" alt="paper_button" data-value="PAPER">
Paper
</button>
</div>
<div class="button-container" data-value="SCISSORS">
<button class="btn game-button">
<img src="img/scissors_emoji.png" alt="scissors_button" data-value="SCISSORS">
Scissors
</button>
</div>
</div>
</section>
</main>
<script src="js/script.js"></script>
</body>
</html>
