-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #168 from Yarlin16/main
Added Memory Game of Tiles
- Loading branch information
Showing
15 changed files
with
311 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Memory Game</title> | ||
<!-- Google Fonts --> | ||
<link | ||
href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap" | ||
rel="stylesheet" | ||
/> | ||
<!-- Stylesheet --> | ||
<link rel="stylesheet" href="style.css" /> | ||
</head> | ||
<body> | ||
<div class="wrapper"> | ||
<div class="stats-container"> | ||
<div id="moves-count"></div> | ||
<div id="time"></div> | ||
</div> | ||
<div class="game-container"></div> | ||
<button id="stop" class="hide">Stop Game</button> | ||
</div> | ||
<div class="controls-container"> | ||
<p id="result"></p> | ||
<button id="start">Start Game</button> | ||
</div> | ||
<!-- Script --> | ||
<script src="logic.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
const moves = document.getElementById('moves-count'); | ||
const timeValue = document.getElementById('time'); | ||
const startButton = document.getElementById('start'); | ||
const stopButton = document.getElementById('stop'); | ||
const gameContainer = document.querySelector('.game-container'); | ||
const result = document.getElementById('result'); | ||
const controls = document.querySelector('.controls-container'); | ||
let cards; | ||
let interval; | ||
let firstCard = false; | ||
let secondCard = false; | ||
//Items array | ||
const items = [ | ||
{name: 'bee', image: 'images/bee.png'}, | ||
{name: 'crocodile', image: 'images/crocodile.png'}, | ||
{name: 'macaw', image: 'images/macaw.png'}, | ||
{name: 'gorilla', image: 'images/gorilla.png'}, | ||
{name: 'tiger', image: 'images/tiger.png'}, | ||
{name: 'monkey', image: 'images/monkey.png'}, | ||
{name: 'chameleon', image: 'images/chameleon.png'}, | ||
{name: 'piranha', image: 'images/piranha.png'}, | ||
{name: 'anaconda', image: 'images/anaconda.png'}, | ||
{name: 'sloth', image: 'images/sloth.png'}, | ||
{name: 'cockatoo', image: 'images/cockatoo.png'}, | ||
{name: 'toucan', image: 'images/toucan.png'}, | ||
]; | ||
//Initial Time | ||
let seconds = 0, | ||
minutes = 0; | ||
//Initial moves and win count | ||
let movesCount = 0, | ||
winCount = 0; | ||
//For timer | ||
const timeGenerator = () => { | ||
seconds += 1; | ||
//minutes logic | ||
if (seconds >= 60) { | ||
minutes += 1; | ||
seconds = 0; | ||
} | ||
//format time before displaying | ||
let secondsValue = seconds < 10 ? `0${seconds}` : seconds; | ||
let minutesValue = minutes < 10 ? `0${minutes}` : minutes; | ||
timeValue.innerHTML = `<span>Time:</span>${minutesValue}:${secondsValue}`; | ||
}; | ||
//For calculating moves | ||
const movesCounter = () => { | ||
movesCount += 1; | ||
moves.innerHTML = `<span>Moves:</span>${movesCount}`; | ||
}; | ||
//Pick random objects from the items array | ||
const generateRandom = (size = 4) => { | ||
//temporary array | ||
let tempArray = [...items]; | ||
//initializes cardValues array | ||
let cardValues = []; | ||
//size should be double (4*4 matrix)/2 since pairs of objects would exist | ||
size = (size * size) / 2; | ||
//Random object selection | ||
for (let i = 0; i < size; i++) { | ||
const randomIndex = Math.floor(Math.random() * tempArray.length); | ||
cardValues.push(tempArray[randomIndex]); | ||
//once selected remove the object from temp array | ||
tempArray.splice(randomIndex, 1); | ||
} | ||
return cardValues; | ||
}; | ||
const matrixGenerator = (cardValues, size = 4) => { | ||
gameContainer.innerHTML = ''; | ||
cardValues = [...cardValues, ...cardValues]; | ||
//simple shuffle | ||
cardValues.sort(() => Math.random() - 0.5); | ||
for (let i = 0; i < size * size; i++) { | ||
/* | ||
Create Cards | ||
before => front side (contains question mark) | ||
after => back side (contains actual image); | ||
data-card-values is a custom attribute which stores the names of the cards to match later | ||
*/ | ||
gameContainer.innerHTML += ` | ||
<div class="card-container" data-card-value="${cardValues[i].name}"> | ||
<div class="card-before">?</div> | ||
<div class="card-after"> | ||
<img src="${cardValues[i].image}" class="image"/></div> | ||
</div> | ||
`; | ||
} | ||
//Grid | ||
gameContainer.style.gridTemplateColumns = `repeat(${size},auto)`; | ||
//Cards | ||
cards = document.querySelectorAll('.card-container'); | ||
cards.forEach(card => { | ||
card.addEventListener('click', () => { | ||
//If selected card is not matched yet then only run (i.e already matched card when clicked would be ignored) | ||
if (!card.classList.contains('matched')) { | ||
//flip the cliked card | ||
card.classList.add('flipped'); | ||
//if it is the firstcard (!firstCard since firstCard is initially false) | ||
if (!firstCard) { | ||
//so current card will become firstCard | ||
firstCard = card; | ||
//current cards value becomes firstCardValue | ||
firstCardValue = card.getAttribute('data-card-value'); | ||
} else { | ||
//increment moves since user selected second card | ||
movesCounter(); | ||
//secondCard and value | ||
secondCard = card; | ||
let secondCardValue = card.getAttribute('data-card-value'); | ||
if (firstCardValue == secondCardValue) { | ||
//if both cards match add matched class so these cards would beignored next time | ||
firstCard.classList.add('matched'); | ||
secondCard.classList.add('matched'); | ||
//set firstCard to false since next card would be first now | ||
firstCard = false; | ||
//winCount increment as user found a correct match | ||
winCount += 1; | ||
//check if winCount ==half of cardValues | ||
if (winCount == Math.floor(cardValues.length / 2)) { | ||
result.innerHTML = `<h2>You Won</h2> | ||
<h4>Moves: ${movesCount}</h4>`; | ||
stopGame(); | ||
} | ||
} else { | ||
//if the cards dont match | ||
//flip the cards back to normal | ||
let [tempFirst, tempSecond] = [firstCard, secondCard]; | ||
firstCard = false; | ||
secondCard = false; | ||
let delay = setTimeout(() => { | ||
tempFirst.classList.remove('flipped'); | ||
tempSecond.classList.remove('flipped'); | ||
}, 900); | ||
} | ||
} | ||
} | ||
}); | ||
}); | ||
}; | ||
//Start game | ||
startButton.addEventListener('click', () => { | ||
movesCount = 0; | ||
seconds = 0; | ||
minutes = 0; | ||
//controls amd buttons visibility | ||
controls.classList.add('hide'); | ||
stopButton.classList.remove('hide'); | ||
startButton.classList.add('hide'); | ||
//Start timer | ||
interval = setInterval(timeGenerator, 1000); | ||
//initial moves | ||
moves.innerHTML = `<span>Moves:</span> ${movesCount}`; | ||
initializer(); | ||
}); | ||
//Stop game | ||
stopButton.addEventListener( | ||
'click', | ||
(stopGame = () => { | ||
controls.classList.remove('hide'); | ||
stopButton.classList.add('hide'); | ||
startButton.classList.remove('hide'); | ||
clearInterval(interval); | ||
}), | ||
); | ||
//Initialize values and func calls | ||
const initializer = () => { | ||
result.innerText = ''; | ||
winCount = 0; | ||
let cardValues = generateRandom(); | ||
console.log(cardValues); | ||
matrixGenerator(cardValues); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
* { | ||
padding: 0; | ||
margin: 0; | ||
box-sizing: border-box; | ||
font-family: 'Poppins', sans-serif; | ||
} | ||
body { | ||
background-color: #26f7fd; | ||
} | ||
.wrapper { | ||
box-sizing: content-box; | ||
width: 26.87em; | ||
padding: 2.5em 3em; | ||
background-color: #ffffff; | ||
position: absolute; | ||
transform: translate(-50%, -50%); | ||
left: 50%; | ||
top: 50%; | ||
border-radius: 0.6em; | ||
box-shadow: 0 0.9em 2.8em rgba(86, 66, 0, 0.2); | ||
} | ||
.game-container { | ||
position: relative; | ||
width: 100%; | ||
display: grid; | ||
gap: 0.6em; | ||
} | ||
.stats-container { | ||
text-align: right; | ||
margin-bottom: 1.2em; | ||
} | ||
.stats-container span { | ||
font-weight: 600; | ||
} | ||
.card-container { | ||
position: relative; | ||
width: 6.25em; | ||
height: 6.25em; | ||
cursor: pointer; | ||
} | ||
.card-before, | ||
.card-after { | ||
position: absolute; | ||
border-radius: 5px; | ||
width: 100%; | ||
height: 100%; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
border: 4px solid #000000; | ||
transition: transform 0.7s ease-out; | ||
backface-visibility: hidden; | ||
} | ||
.card-before { | ||
background-color: #26f7fd; | ||
font-size: 2.8em; | ||
font-weight: 600; | ||
} | ||
.card-after { | ||
background-color: #ffffff; | ||
transform: rotateY(180deg); | ||
} | ||
.card-container.flipped .card-before { | ||
transform: rotateY(180deg); | ||
} | ||
.card-container.flipped .card-after { | ||
transform: rotateY(0deg); | ||
} | ||
.controls-container { | ||
position: absolute; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
flex-direction: column; | ||
width: 100%; | ||
height: 100%; | ||
background-color: #26f7fd; | ||
top: 0; | ||
} | ||
button { | ||
border: none; | ||
border-radius: 0.3em; | ||
padding: 1em 1.5em; | ||
cursor: pointer; | ||
} | ||
#stop { | ||
font-size: 1.1em; | ||
display: block; | ||
margin: 1.1em auto 0 auto; | ||
background-color: #000000; | ||
color: #ffffff; | ||
} | ||
.controls-container button { | ||
font-size: 1.3em; | ||
box-shadow: 0 0.6em 2em rgba(86, 66, 0, 0.2); | ||
} | ||
.hide { | ||
display: none; | ||
} | ||
#result { | ||
text-align: center; | ||
} | ||
#result h2 { | ||
font-size: 2.5em; | ||
} | ||
#result h4 { | ||
font-size: 1.8em; | ||
margin: 0.6em 0 1em 0; | ||
} |