Gioco semplice che nasconde però qualche insidia per il programmatore meno esperto. Vediamo come fare.
Versione 1 – Non interattivo
Facciamo una prima versione del gioco in modalità “non interattiva”. Ovvero, facciamo un semplice bottone per cominciare a giocare e il software js deve simulare l’estrazione automatica dei simboli di entrambi i giocatori, verificando che vince turno dopo turno e stampando il vincitore alla fine di tre turni. L’esercizio è un’ottima scusa per vedere l’uso dell’evento click, l’uso della funzione standard random, dell’uso delle funzioni js con tanto di passaggio di parametri.
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<title>Sasso Carta Forbice</title>
<script>
function random()
{
let n = Math.floor(Math.random() * 2);
return n;
}
function stampaSimbolo(valore)
{
if (valore == 0)
return "sasso";
if (valore == 1)
return "carta";
if (valore == 2)
return "forbice";
return "ERRORE";
}
function confronta(a, b)
{
//imposto
//0 -> sasso
//1 -> carta
//2 -> forbici
//ritorno A -> ha vinto giocatore A
//ritorno B -> ha vinto giocatore B
//ritorno P -> pareggio
if (a == 0 && b == 0)
{
return "P";
}
if (a == 1 && b == 1)
{
return "P";
}
if (a == 2 && b == 2)
{
return "P";
}
if (a == 0 && b == 1)
{
return "B";
}
if (a == 1 && b == 0)
{
return "A";
}
if (a == 0 && b == 2)
{
return "A";
}
if (a == 2 && b == 0)
{
return "B";
}
if (a == 1 && b == 2)
{
return "B";
}
if (a == 2 && b == 1)
{
return "A";
}
}
function gioca()
{
const turniPartita = 3;
let turno = 0;
let punteggioA = 0;
let punteggioB = 0;
let estrazioneA;
let estrazioneB;
while(turno < turniPartita)
{
//faccio lanciare due simboli ai giocatori
estrazioneA = random();
estrazioneB = random();
//estrazioneA = setInterval(random, 1000);
//estrazioneB = setInterval(random, 1000);
document.getElementById("risultatoA").innerHTML += stampaSimbolo(estrazioneA)+"<br>";
document.getElementById("risultatoB").innerHTML += stampaSimbolo(estrazioneB)+"<br>";
//confronto le estrazioni per determinare chi vince il turno
let round = confronta(estrazioneA,estrazioneB);
if (round == 'A')
punteggioA = punteggioA + 1;
if (round == 'B')
punteggioB = punteggioB + 1;
turno = turno + 1;
}
if (punteggioA>punteggioB)
{
document.getElementById("risultatoA")
.innerHTML += "HAI VINTO";
document.getElementById("risultatoB")
.innerHTML += "HAI PERSO";
}
else
{
document.getElementById("risultatoA")
.innerHTML += "HAI PERSO <br>";
document.getElementById("risultatoB")
.innerHTML += "HAI VINTO <br>";
}
}
</script>
</head>
<body>
<div class="container">
<h1>Benvenuto nel gioco sasso carta forbici!</h1>
<p>Il programma simula l'estrazione di due simboli per il giocatore A e B
tra sasso carta e forbice e dopo 3 turni dice chi ha vinto</p>
<div class="row">
<div class="col text-center">
<span class="fw-bold">Giocatore A</span>
<div id="risultatoA"></div>
</div>
<div class="col-3 text-center"><button class="btn btn-primary" onclick="gioca();">Gioca!</button></div>
<div class="col text-center">
<span class="fw-bold">Giocatore B</span>
<div id="risultatoB"></div>
</div>
</div>
</div>
<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
</body>
</html>
Versione 2 – Giocatore singolo interattivo

Se siamo già ad un livello di js più esperto, possiamo ridisegnare il nostro gioco sfruttando altre soluzioni. Ad esempio, possiamo simulare che ci sia un utente umano contro la macchina. L’utente umano, ovviamente, può selezionare il simbolo da lanciare nel turno, ad esempio cliccando una figura apposita. La gestione degli eventi possiamo poi relegarla interamente al codice js con eventHandler. Ecco una soluzione sfruttando in modo massiccio Bootstrap e le sue classi.
Vogliamo aggiungere qualche effetto grafico sfruttando gli eventi javascript per meglio approfondirli. Ad esempio quando si passa sulle figure si opacizzano e quando il mouse esce dalla figura tornano normali. In modo analogo, se si clicca una figura cambia bordo da nero a rosso. Scelta la figura, si procede con il cliccare il bottone sfida che visualizza uno spinner nascosto, attende un tempo casuale di 10 secondi massimo prima di scegliere un simbolo per il giocatore PC e visualizzare il risultato. Dentro la funzione dello spinner il resto dell’esecuzione.
Essendo realizzato con l’ausilio di bootstrap, la gestione dei CSS è fatta con le classi della libreria front-end. Motivo per cui tutti gli eventi gestiscono gli stili con oggetto.classList.add(“qualcosa”) o oggetto.classList.remove(“qualcosa”). Rimandiamo ad altri esercizi l’uso del CSS puro con la modalità oggetto.style.attributo = valore che qui usiamo solo per lo spinner ornamentale.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Morra Cinese in JavaScript</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
</head>
<body>
<div class="container text-center">
<h1>Morra Cinese in JavaScript</h1>
<p>Il gioco è molto semplice: l'utente umano sceglie un simbolo tra quelli previsti e schiaccia il bottone "Sfida!".
Il calcolatore scegli un valore a caso tra quelli disponibili e viene confrontanto il risultato.</p>
<br>
<div class="container text-center">
<h3>Giocatore 1</h3>
<img id="sasso" class="border border-dark mx-5" src="img/sasso-verde.png" alt="sasso">
<img id="carta" class="border border-dark mx-5" src="img/carta-verde.png" alt="carta">
<img id="forbice" class="border border-dark mx-5" src="img/forbice-verde.png" alt="forbice">
<br><br>
<button class="btn btn-primary" id="sfida">Sfida!</button>
<br><br>
<div class="spinner-border" id="spinner" role="status">
<span class="visually-hidden">Sto pensando...</span>
</div>
<div id="avversario"></div>
</div>
</div>
<script src="js/script.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
</body>
</html>
Lo script JS
//
let sasso = document.querySelector("#sasso");
let carta = document.querySelector("#carta");
let forbice = document.querySelector("#forbice");
let sfida = document.querySelector("#sfida");
let spinner = document.querySelector("#spinner");
let avversario = document.querySelector("#avversario");
spinner.style.visibility = "hidden";
/**
* Effetto sfumato entri/esci col mouse
*/
sasso.addEventListener("mouseover", sfumaSasso, true);
carta.addEventListener("mouseover", sfumaCarta, true);
forbice.addEventListener("mouseover", sfumaForbice, true);
function sfumaSasso()
{
//sasso.style.opacity = 0.4;
sasso.classList.add("opacity-25");
}
function sfumaCarta()
{
carta.classList.add("opacity-25");
}
function sfumaForbice()
{
forbice.classList.add("opacity-25");
}
//stessa funzionalità delle righe 7,8,9 con le loro funzioni ma in forma compatta arrow function
sasso.onmouseleave = (event) => { sasso.classList.remove("opacity-25");};
carta.onmouseleave = (event) => { carta.classList.remove("opacity-25");};
forbice.onmouseleave = (event) => { forbice.classList.remove("opacity-25");};
/**
* Annoto la scelta del clìck dela mouse
*/
sasso.addEventListener("click", scegliSasso, true);
carta.addEventListener("click", scegliCarta, true);
forbice.addEventListener("click", scegliForbice, true);
let scelta;
function scegliSasso()
{
scelta = "sasso";
sasso.classList.remove("border-dark");
sasso.classList.add("border-danger");
//cambia immagine scelta?
}
function scegliCarta()
{
scelta = "carta";
carta.classList.remove("border-dark");
carta.classList.add("border-danger");
//cambia immagine scelta?
}
function scegliForbice()
{
scelta = "forbice";
forbice.classList.remove("border-dark");
forbice.classList.add("border-danger");
//cambia immagine scelta?
}
sfida.addEventListener("click",tira, true);
function tira()
{
if (scelta == null)
return;
//faccio girare lo spinner per un tempo casuale tra i 10 secondi
spinner.style.visibility = "visible";
let attesa = Math.floor(Math.random()*10);
setTimeout(function(){
//intanto faccio scegliere al giocatore pc un simbolo
let sceltaPC = "";
let simbolo = Math.floor(Math.random()*2);
//console.log(simbolo);
if (simbolo == 0)
sceltaPC = "sasso";
if (simbolo == 1)
sceltaPC = "carta";
if (simbolo == 2)
sceltaPC = "forbice";
spinner.style.visibility = "hidden";
avversario.innerHTML = "Il PC ha scelto " + sceltaPC + " - il giocatore ha scelto " + scelta + "<br>";
let vincitore = "";
if (sceltaPC == scelta)
vincitore = "PAREGGIO";
if (scelta == "sasso" && sceltaPC == "forbice")
vincitore = "HA VINTO IL GIOCAORE";
if (scelta == "sasso" && sceltaPC == "carta")
vincitore = "HA VINTO IL PC";
if (scelta == "carta" && sceltaPC == "forbice")
vincitore = "HA VINTO IL PC";
if (scelta == "carta" && sceltaPC == "sasso")
vincitore = "HA VINTO IL GIOCATORE";
if (scelta == "forbice" && sceltaPC == "carta")
vincitore = "HA VINTO IL GIOCATORE";
if (scelta == "forbice" && sceltaPC == "sasso")
vincitore = "HA VINTO IL PC";
avversario.innerHTML += vincitore;
}, attesa*1000);
}
Ultima modifica 21 Febbraio 2023