Pair Game / Párosító játék

Mi a cél?

Olyan játék, ahol megkeressük a párokat. Ha rákattintunk egy kártyára akkor elindul a játék számlálója. Ha megtaláljuk az azonos kártyákat, akkor azok úgy maradnak, ha nem akkor visszafordulnak. Ha minden kártyát azonosítottunk, akkor megáll a számláló és 5 másodperc múlva visszafordulnak a lapok és újra indulhat a játék.

DEMO (a képre kattintva indul)

Pair Game / Párosító játék

A HTML template

A HTML vázban megjelenítjük a kártyák képeit, a value attributumokban tároljuk majd az egyedi kép referenciákat. A játék kezdetén rendezetten jelennek meg, mindegyik kép duplán, de a CSS img visibility: hidden property miatt, nem a kép, hanem a héttérkép látszik. A kép csak akkor fog látszódni, ha majd rákattintunk.

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Pair Game</title> <link rel="stylesheet" href="style.css"> </head> <body> <div class="container"> <h1>JAVASCRIPT PAIRS GAME</h1> <h2>CLICK ANY CARD TO BEGIN</h2> <div class="clock">00:00</div> <div class="game"> <div class="card" value="1"><img src="./images/1.jpg" value="1" alt="Secret"></div> <div class="card" value="2"><img src="./images/2.jpg" value="2" alt="Secret"></div> <div class="card" value="3"><img src="./images/3.jpg" value="3" alt="Secret"></div> <div class="card" value="4"><img src="./images/4.jpg" value="4" alt="Secret"></div> <div class="card" value="5"><img src="./images/5.jpg" value="5" alt="Secret"></div> <div class="card" value="1"><img src="./images/1.jpg" value="1" alt="Secret"></div> <div class="card" value="2"><img src="./images/2.jpg" value="2" alt="Secret"></div> <div class="card" value="3"><img src="./images/3.jpg" value="3" alt="Secret"></div> <div class="card" value="4"><img src="./images/4.jpg" value="4" alt="Secret"></div> <div class="card" value="5"><img src="./images/5.jpg" value="5" alt="Secret"></div> </div> </div> <script src="main.js"></script> </body> </html>

A CSS stílus

A statikus megjelenítést segítő elemek mellett vannak azon osztályok (visible, open, close, disabled) melyek a JS által történő dinamikus kártyamozgatást segítik.

* { margin: 0; padding: 0; } *, *::before, *::after { box-sizing: inherit; } html { box-sizing: border-box; } body { min-height: 100vh; font-family: sans-serif; background-color: turquoise; } .container { width: 65vw; display: flex; flex-direction: column; justify-content: center; align-items: center; margin: 0 auto; color: #fff; } h1 { font-weight: 100; font-size: 3rem; margin: 1rem; } h2, .clock { font-weight: 100; font-size: 1.5rem; margin: .5rem; } .clock { font-size: 3rem; } .game { display: flex; flex-wrap: wrap; justify-content: space-evenly; width: 100%; } .card { width: 18%; margin-bottom: 1.5%; cursor: pointer; background: url(./images/bg.jpg); background-size: cover; border-radius: 0.5rem; } img { width: 100%; height: 100%; transition: all 2s; visibility: hidden; border-radius: 0.5rem; } .visible { visibility: visible; } .open { transform: rotateY(180deg); } .close { transform: rotateY(180deg); } .disabled { pointer-events: none; cursor: none; }

A JS logika

A kártyákat egy NodeList-be importáljuk a DOM-ból, a cardsArray a kártyák NodeElement tömbje lesz, hogy azon tömbműveleteket tudjunk majd végezni, a hangingCards tömbben pedig az éppen kiválasztott képeket fogjuk majd ideiglenesen tárolni.

let cards = document.querySelectorAll('.card'); let cardsArray = [...cards]; let game = document.querySelector('.game'); let clock = document.querySelector('.clock'); let isStarted = false; let hangingCards; let result = 0; let timer;

A képek véletlenszerű összekeverését az alábbi függvénnyel végezzük.

function shuffleImages(array) { for (let i = array.length - 1; i > 0; i--) { let j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } }

A program kezdetén beállítjuk a kezdőértékeket és töröljük a képek beállításait, ha ez már nem az első játék volt.

function start() { hangingCards = []; shuffleImages(cardsArray); game.textContent = '' cardsArray.forEach(card => { game.appendChild(card); card.firstChild.classList.remove('visible', 'open'); card.classList.remove('disabled'); }) } start();

A kártyákra felírjuk az eseményfigyelőket.

cards.forEach(card => card.addEventListener('click', handleClicked)); function handleClicked(event) { isFirstClick() showImage(event); checkPairs(); if (result === 5) { restart() } }

Itt több függvényt is végrehajtottunk, elsőként annak a vizsgálatát, hogy ez az első klikk volt-e, mert akkor elindíjuk az órát. Mivel az órát 00:00:00 formátumban akarjuk megjeleníteni, ezért egy kicsit alakítgatnunk kell a számolás utáni megjelenítésen.

function isFirstClick() { if (!isStarted) { isStarted = true; startClock(); } } function startClock() { timer = setInterval(countTimer, 1000); let totalSeconds = 0; function countTimer() { ++totalSeconds; let minute = Math.floor(totalSeconds / 60); let seconds = totalSeconds - (minute * 60); if (minute < 10) minute = `0${minute}`; if (seconds < 10) seconds = `0${seconds}`; clock.textContent = `${minute}:${seconds}`; } }

Ez után megjelenítjük a képet, amire kattintottunk, láthatóvá tesszük a DOM-ban és belerakjuk a hangingCards tömbbe.

function showImage(event) { event.target.firstChild.classList.add('visible', 'open'); hangingCards.push(event.target); }

Ezt követően megvizsgáljuk, hogy van-e egyezés.

function checkPairs() { if (hangingCards.length === 2 && hangingCards[0].getAttribute('value') !== hangingCards[1].getAttribute('value')) { disabled(4000); setTimeout(() => { hangingCards[0].firstChild.classList.remove('open'); hangingCards[1].firstChild.classList.remove('open'); hangingCards[0].firstChild.classList.remove('visible'); hangingCards[1].firstChild.classList.remove('visible'); }, 2000) } else if (hangingCards.length === 2) { disabled(2000); hangingCards[0].classList.add('disabled'); hangingCards[1].classList.add('disabled'); result++; } }

A disabled(number) függvény azt valósítja meg, hogy number ideig az adott kártya ne legyen kattintható.

function disabled(number) { cards.forEach(card => card.classList.add('disabled')); setTimeout(() => { cards.forEach(card => card.classList.remove('disabled')); hangingCards = []; }, number); }

Ha az összes kép párosodott, akkor meghívjuk a restart() függvényt, mely leállítja az órát, kezdeti értékre állítja a változókat és öt másodperc múlva nullázza is az órát és lehetővé teszi, hogy új játékot kezdjünk.

function restart() { clearInterval(timer); isStarted = false; result = 0; hangingCards = []; setTimeout(() => { clock.textContent = '00:00' start(); }, 5000) }

A teljes kód itt található.