diff --git a/index.html b/index.html index ccbe66c..6170743 100644 --- a/index.html +++ b/index.html @@ -48,18 +48,47 @@ Memory Game - Aakash Dinkar - - + + +

Memory Game

- -

-
- -
+ + +
+ +
+ +
+
+

Moves: 0

+
+

- + diff --git a/script.js b/script.js index 28a49de..c94afd8 100644 --- a/script.js +++ b/script.js @@ -1,72 +1,140 @@ -const images = ['panda.jpg', 'cat.jpg', 'panda.jpg', 'cat.jpg', 'mickey.jpg', 'mickey.jpg']; - -function start() { - let moves = 0; - var points = document.createElement('p') - points.setAttribute('id', 'points'); - points.innerHTML = 'points'; - document.getElementById("score").append(points) - - let imagesCopy = []; - for(let i = 0; i < images.length; i++) { - imagesCopy.push(images[i]); - } - var row = document.createElement('div') - var n = images.length; - for(let i = 1; i <=n; i++){ - var div = document.createElement('div'); - div.setAttribute('class', 'imageDiv') - - let randomImg = imagesCopy.splice(Math.floor(Math.random() * imagesCopy.length), 1); - console.log(randomImg) - - var img = document.createElement('img') - img.setAttribute('src', randomImg) - img.setAttribute('class', 'hide') - - div.appendChild(img) - row.appendChild(div) - - if( i%3 == 0) { - document.getElementById('boardgame').appendChild(row); - row = document.createElement('div'); - } - - div.addEventListener('click', function(event) { - moves++; - document.getElementById('points').innerHTML = moves; - - - var curr = event.currentTarget.children - var currImg = curr[0]; - - var currShowing = document.getElementsByClassName('show') - - let flag = 0; - if(currShowing.length >= 1) { - for(let j = 0; j < currShowing.length; j++) { - if(currShowing[j].src != currImg.src) - currShowing[j].classList.remove('show') - else { - currShowing[j].classList.add('match') - currImg.classList.add('match') - flag = 1; - } - } - } - if(flag == 0) { - currImg.classList.add('show'); - } - - if( document.getElementsByClassName('match').length == n ) { - let button = document.createElement('button') - button.setAttribute('class', 'warning') - - let node = document.createTextNode("You've won!! Moves = "+moves) - button.appendChild(node); - - document.getElementById('score').appendChild(button) - } - }); - } -} +(function () { + const images = ['panda.jpg', 'cat.jpg', 'panda.jpg', 'cat.jpg', 'mickey.jpg', 'mickey.jpg']; + const imagesPerRow = 3; + + let winMessageShown = false; + const __moves__ = document.getElementById('moves'); + const __restartBtn__ = document.getElementById('restart-btn'); + const __gameBoard__ = document.getElementById('gameBoard'); + const __gameWonMsg__ = document.getElementById('gameWonMsg'); + const __toggleSwitch__ = document.querySelector('.theme-slider input[type="checkbox"]'); + const __slider__ = document.querySelector('.theme-slider .slider'); + const __getMatchElements__ = () => document.getElementsByClassName('match'); + const __getAllImageDiv__ = () => document.querySelectorAll('.imageDiv'); + const __getShowingElements__ = () => document.getElementsByClassName('show'); + + function restartGame() { + __gameBoard__.innerHTML = ''; + __gameWonMsg__.innerText = ''; + winMessageShown = false; + + startGame(); + } + + function startGame() { + let moves = 0; + renderMoves(moves); + + const shuffledImages = shuffleImages(images); + generateBoard(shuffledImages); + + function updateScore() { + moves++; + renderMoves(moves); + } + + __getAllImageDiv__().forEach((div) => { + div.addEventListener('click', function (event) { + handleCardClick(event, moves, updateScore); + }); + }); + } + + function renderMoves(moves = 0) { + __moves__.innerText = `Moves: ${moves}`; + } + + function shuffleImages(imagesArray) { + let copy = [...imagesArray]; + let shuffled = []; + while (copy.length) { + let randomIndex = Math.floor(Math.random() * copy.length); + shuffled.push(copy.splice(randomIndex, 1)[0]); + } + return shuffled; + } + + function generateBoard(images) { + const fragment = document.createDocumentFragment(); + let row = document.createElement('div'); + + images.forEach((image, index) => { + const div = document.createElement('div'); + div.setAttribute('class', 'imageDiv'); + + const img = document.createElement('img'); + img.setAttribute('src', image); + img.setAttribute('class', 'hide'); + + div.appendChild(img); + row.appendChild(div); + + if ((index + 1) % imagesPerRow === 0) { + fragment.appendChild(row); + row = document.createElement('div'); + } + }); + + __gameBoard__.replaceChildren(fragment); + } + + function handleCardClick(event, moves, updateScore) { + if (winMessageShown) return; + + updateScore(); + const clickedImage = event.currentTarget.children[0]; + const showingImages = __getShowingElements__(); + + let matchFound = false; + + if (showingImages.length >= 1) { + [...showingImages].forEach((showingImage) => { + if (showingImage.src !== clickedImage.src) { + showingImage.classList.remove('show'); + } else { + showingImage.classList.add('match'); + clickedImage.classList.add('match'); + matchFound = true; + } + }); + } + + if (!matchFound) { + clickedImage.classList.add('show'); + } + + if (__getMatchElements__().length === images.length) { + displayWinMessage(moves); + } + } + + function displayWinMessage(moves) { + winMessageShown = true; + __gameWonMsg__.innerText = `You've won!! Moves = ${moves}`; + } + + document.addEventListener('DOMContentLoaded', () => { + document.body.style.cssText = `transition: background-color 0.3s, color 0.3s;`; + startGame(); + __restartBtn__.onclick = restartGame; + + /* theme slider logic --- START --- */ + __toggleSwitch__.onchange = toggleTheme; + __toggleSwitch__.checked = document.body.className === 'dark-theme'; + setTimeout(() => { + __slider__.classList.add('slider-transition-class'); + }, 0); + /* theme slider logic --- END --- */ + + function toggleTheme(e) { + const isDarkThemeEnabled = e.target.checked; + + if (isDarkThemeEnabled) { + document.body.className = 'dark-theme'; + } else { + document.body.className = 'light-theme'; + } + saveIsDarkThemeEnabledToLocalStorage(isDarkThemeEnabled); + }; + }); +})(); diff --git a/style.css b/style.css index 616cb17..4e2b207 100644 --- a/style.css +++ b/style.css @@ -1,41 +1,186 @@ * { - box-sizing: border-box; + box-sizing: border-box; } +body { + font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, + Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-size: large; +} +button { + font-family: inherit; +} +body.light-theme { + background-color: #ffffff; + color: #333333; +} +body.dark-theme { + background-color: #121212; + color: #ffffff; +} + img { - height: 100px; - width: 100px; - padding: 5px; - border: 1px solid black; - vertical-align: middle; + height: 70%; + width: 70%; + padding: 5px; + border: 1px solid black; + vertical-align: middle; } .hide { - visibility: hidden; + visibility: hidden; +} +.match, +.show { + visibility: visible !important; +} + +#gameBoard > div { + display: flex; + flex-wrap: nowrap; +} + +.imageDiv { + display: flex; + justify-content: center; + align-items: center; + width: 150px; + height: 150px; + border-right: 2px solid black; + border-bottom: 2px solid black; + cursor: pointer; +} +#gameBoard > div:first-of-type > .imageDiv { + border-top: 2px solid black; +} +.imageDiv:first-of-type { + border-left: 2px solid black; +} +body.dark-theme .imageDiv { + box-shadow: inset 0px 0px 12px -4px rgba(255, 255, 255, 0.5); +} + +/* restart button -- start -- */ +#restart-btn { + margin: 10px 0 0; + border: none; + display: block; + font-size: 16px; + border-radius: 5px; + background-color: #6c63ff; + color: white; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + padding: 10px 20px; + transition: background-color 0.3s, transform 0.2s; +} +#restart-btn:hover { + background-color: #5b1dc9; +} +#restart-btn:active { + transform: translateY(2px); +} +body.dark-theme #restart-btn { + background-color: #bb86fc; +} +/* restart button -- end -- */ + +@media (max-width: 468px) { + #restart-btn { + font-size: 0.9rem; + padding: 0.8rem 1.5rem; + margin-left: auto; + margin-right: auto; + } + + .imageDiv { + width: 120px; + height: 120px; + } + + h1 { + margin-top: 80px; + text-align: center; + } + + #gameBoard > div { + justify-content: center; + } + + #moves, + #gameWonMsg { + text-align: center; + } } -.match, .show { - visibility: visible !important; + +@media (max-width: 375px) { + #restart-btn { + font-size: 0.9rem; + padding: 0.8rem 1.5rem; + } + + .imageDiv { + width: 100px; + height: 100px; + } } -.success, .warning { - background-color: rgb(2, 237, 2); - border: 4px solid rgb(207, 207, 207); - border-radius: 5px; - padding: 10px; - font-size: 20px; - cursor: pointer; + +/* theme slider --- START --- */ +.theme-slider-container { + position: fixed; + top: 18px; + right: 20px; } -.warning { - background-color: red; + +.theme-slider { + display: inline-block; + height: 34px; + position: relative; + width: 60px; +} + +.theme-slider input { + display: none; +} + +.slider { + background-color: #333; + bottom: 0; + cursor: pointer; + left: 0; + position: absolute; + right: 0; + top: 0; } -.success:hover { - background-color: rgb(0, 205, 0); + +.slider::before { + background-color: #fff; + bottom: 4px; + content: ''; + height: 26px; + left: 4px; + position: absolute; + width: 26px; +} + +.slider-transition-class, +.slider-transition-class::before { + transition: 0.4s; +} + +input:checked + .slider { + background-color: #ccc; +} +input:checked + .slider::before { + background-color: #333; +} + +input:checked + .slider::before { + transform: translateX(26px); +} + +.slider.round { + border-radius: 34px; } -.imageDiv{ - position: relative; - display: inline-block; - width:150px; - height: 150px; - line-height: 150px; - text-align: center; - border: 2px solid black; - cursor: pointer; +.slider.round::before { + border-radius: 50%; } +/* theme slider --- END --- */