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.
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 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 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)
}