├── assets ├── images │ ├── img-1.png │ ├── img-2.png │ ├── img-3.png │ ├── img-4.png │ ├── img-5.png │ ├── img-6.png │ └── que_icon.svg ├── js │ └── app.js └── css │ └── style.css ├── LICENSE ├── README.md └── index.html /assets/images/img-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeaashu/Memory-Card-Game/HEAD/assets/images/img-1.png -------------------------------------------------------------------------------- /assets/images/img-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeaashu/Memory-Card-Game/HEAD/assets/images/img-2.png -------------------------------------------------------------------------------- /assets/images/img-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeaashu/Memory-Card-Game/HEAD/assets/images/img-3.png -------------------------------------------------------------------------------- /assets/images/img-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeaashu/Memory-Card-Game/HEAD/assets/images/img-4.png -------------------------------------------------------------------------------- /assets/images/img-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeaashu/Memory-Card-Game/HEAD/assets/images/img-5.png -------------------------------------------------------------------------------- /assets/images/img-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeaashu/Memory-Card-Game/HEAD/assets/images/img-6.png -------------------------------------------------------------------------------- /assets/images/que_icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Ashutosh Kumar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | ![GitHub repo size](https://img.shields.io/github/repo-size/codeaashu/Memory-Card-Game) 4 | [![Twitter Follow](https://img.shields.io/twitter/follow/warrior_aashuu?style=social)](https://twitter.com/warrior_aashuu) 5 | 6 | 7 |
8 |
9 | 10 | 11 | 12 |

Memory Card Game v.2.0

13 | Built a Memory Matching Card game using JavaScript Now This version has a Timer in which you have to complete the game.Built a Memory Card game using HTML5, CSS3 and JavaScript. Used CSS Animation and also used Array sort method to sort the images. 14 | 15 | ➥ Play Now 16 | 17 |
18 | 19 |
20 | 21 | ### Prerequisites 22 | 23 | Before you begin, ensure you have met the following requirements: 24 | 25 | - [Git](https://git-scm.com/downloads "Download Git") must be installed on your operating system. 26 | 27 | ### Run Locally 28 | 29 | To run **Memory Card Game v.2.0**, run this command on your git bash: 30 | 31 | Linux and macOS: 32 | 33 | ```bash 34 | sudo git clone https://github.com/codeaashu/Memory-Card-Game.git 35 | ``` 36 | 37 | Windows: 38 | 39 | ```bash 40 | git clone https://github.com/codeaashu/Memory-Card-Game.git 41 | ``` 42 | 43 | ### License 44 | 45 | MIT 46 | -------------------------------------------------------------------------------- /assets/js/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // Selecting Elements 4 | const cards = document.querySelectorAll(".card"); 5 | const timeTag = document.querySelector(".time b"); 6 | const flipsTag = document.querySelector(".flips b"); 7 | const restartBtn = document.querySelector(".details button"); 8 | 9 | // Required Variables 10 | let maxTime = 25; 11 | let timeLeft = maxTime; 12 | let flips = 0; 13 | let matchedCard = 0; 14 | let disableDeck = false; 15 | let isPlaying = false; 16 | let card1, card2, timer; 17 | 18 | // Function initial Timer 19 | function initialTimer() { 20 | if (timeLeft <= 0) { 21 | return clearInterval(timer); 22 | } 23 | timeLeft--; 24 | timeTag.innerText = timeLeft; 25 | } 26 | 27 | // Function FlipCard 28 | function flipCard({ target: clickedCard }) { 29 | if (!isPlaying) { 30 | isPlaying = true; 31 | timer = setInterval(initialTimer, 1000); 32 | } 33 | if (clickedCard !== card1 && !disableDeck && timeLeft > 0) { 34 | flips++; 35 | flipsTag.innerText = flips; 36 | clickedCard.classList.add("flip"); 37 | if (!card1) { 38 | return (card1 = clickedCard); 39 | } 40 | card2 = clickedCard; 41 | disableDeck = true; 42 | let card1Img = card1.querySelector(".back-view img").src, 43 | card2Img = card2.querySelector(".back-view img").src; 44 | matchCard(card1Img, card2Img); 45 | } 46 | } 47 | 48 | // Function MatchCard 49 | function matchCard(img1, img2) { 50 | if (img1 === img2) { 51 | matchedCard++; 52 | if (matchedCard == 6 && timeLeft > 0) { 53 | return clearInterval(timer); 54 | } 55 | card1.removeEventListener("click", flipCard); 56 | card2.removeEventListener("click", flipCard); 57 | card1 = card2 = ""; 58 | return (disableDeck = false); 59 | } 60 | 61 | setTimeout(() => { 62 | card1.classList.add("shake"); 63 | card2.classList.add("shake"); 64 | }, 400); 65 | 66 | setTimeout(() => { 67 | card1.classList.remove("shake", "flip"); 68 | card2.classList.remove("shake", "flip"); 69 | card1 = card2 = ""; 70 | disableDeck = false; 71 | }, 1200); 72 | } 73 | 74 | // Function ShuffleCard 75 | function shuffleCard() { 76 | timeLeft = maxTime; 77 | flips = matchedCard = 0; 78 | card1 = card1 = ""; 79 | clearInterval(timer); 80 | timeTag.innerText = timeLeft; 81 | flipsTag.innerText = flips; 82 | disableDeck = isPlaying = false; 83 | 84 | let arr = [1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6]; 85 | arr.sort(() => (Math.random() > 0.5 ? 1 : -1)); 86 | 87 | cards.forEach((card, i) => { 88 | card.classList.remove("flip"); 89 | let imgTag = card.querySelector(".back-view img"); 90 | 91 | setTimeout(() => { 92 | imgTag.src = `/assets/images/img-${arr[i]}.png`; 93 | }, 500); 94 | card.addEventListener("click", flipCard); 95 | }); 96 | } 97 | shuffleCard(); 98 | 99 | // Add events 100 | restartBtn.addEventListener("click", shuffleCard); 101 | 102 | cards.forEach((card) => { 103 | card.addEventListener("click", flipCard); 104 | }); 105 | -------------------------------------------------------------------------------- /assets/css/style.css: -------------------------------------------------------------------------------- 1 | /* --- Google Fonts: Poppins --- */ 2 | @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap"); 3 | 4 | /* --- Variable CSS --- */ 5 | :root { 6 | --bgColor: #6563ff; 7 | --bgWrapper: #f8f8f8; 8 | } 9 | 10 | /* --- Reset --- */ 11 | * { 12 | margin: 0; 13 | padding: 0; 14 | box-sizing: border-box; 15 | font-family: "Poppins", sans-serif; 16 | } 17 | p { 18 | font-size: 20px; 19 | } 20 | body { 21 | display: flex; 22 | align-items: center; 23 | justify-content: center; 24 | min-height: 100vh; 25 | background-color: var(--bgColor); 26 | } 27 | ::selection { 28 | color: #fff; 29 | background-color: var(--bgColor); 30 | } 31 | .wrapper { 32 | background-color: var(--bgWrapper); 33 | padding: 25px; 34 | border-radius: 10px; 35 | box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); 36 | } 37 | .cards, 38 | .card, 39 | .view, 40 | .details, 41 | p { 42 | display: flex; 43 | align-items: center; 44 | justify-content: center; 45 | } 46 | .cards { 47 | height: 350px; 48 | width: 350px; 49 | flex-wrap: wrap; 50 | justify-content: space-between; 51 | } 52 | .cards .card { 53 | cursor: pointer; 54 | position: relative; 55 | perspective: 1000px; 56 | transform-style: preserve-3d; 57 | height: calc(100% / 4 - 10px); 58 | width: calc(100% / 4 - 10px); 59 | } 60 | .cards .card .view { 61 | width: 100%; 62 | height: 100%; 63 | user-select: none; 64 | pointer-events: none; 65 | position: absolute; 66 | background: #fff; 67 | border-radius: 7px; 68 | backface-visibility: hidden; 69 | transition: transform 0.25s linear; 70 | box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1); 71 | } 72 | .card .front-view img { 73 | max-width: 17px; 74 | } 75 | .card .back-view img { 76 | max-width: 40px; 77 | } 78 | 79 | .card .back-view { 80 | transform: rotateY(-180deg); 81 | } 82 | 83 | .card.flip .front-view { 84 | transform: rotateY(180deg); 85 | } 86 | .card.flip .back-view { 87 | transform: rotateY(0); 88 | } 89 | 90 | /* --- Animation --- */ 91 | .card.shake { 92 | animation: shake 0.35s ease-in-out; 93 | } 94 | @keyframes shake { 95 | 0%, 96 | 100% { 97 | transform: translateX(0); 98 | } 99 | 20% { 100 | transform: translateX(-13px); 101 | } 102 | 40% { 103 | transform: translateX(13px); 104 | } 105 | 60% { 106 | transform: translateX(-8px); 107 | } 108 | 80% { 109 | transform: translateX(8px); 110 | } 111 | } 112 | 113 | /* --- Details --- */ 114 | .details { 115 | width: 100%; 116 | margin-top: 15px; 117 | padding: 0 20px; 118 | border-radius: 7px; 119 | background: #fff; 120 | height: calc(100% / 4 - 10px); 121 | justify-content: space-between; 122 | box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1); 123 | } 124 | .details p { 125 | font-size: 18px; 126 | height: 17px; 127 | padding-right: 18px; 128 | border-right: 1px solid #ccc; 129 | } 130 | .details p span { 131 | margin-left: 8px; 132 | } 133 | .details p b { 134 | font-weight: 500; 135 | } 136 | .details button { 137 | cursor: pointer; 138 | font-size: 14px; 139 | color: var(--bgColor); 140 | border-radius: 4px; 141 | padding: 4px 11px; 142 | background-color: #fff; 143 | border: 2px solid var(--bgColor); 144 | transition: all 0.3s ease; 145 | } 146 | .details button:hover { 147 | color: #fff; 148 | background-color: var(--bgColor); 149 | } 150 | 151 | /* --- Media Queries --- */ 152 | @media screen and (max-width: 700px) { 153 | .cards { 154 | height: 350px; 155 | width: 350px; 156 | } 157 | .card .front-view img { 158 | max-width: 16px; 159 | } 160 | .card .back-view img { 161 | max-width: 40px; 162 | } 163 | } 164 | 165 | @media screen and (max-width: 430px) { 166 | .cards { 167 | height: 300px; 168 | width: 300px; 169 | } 170 | .card .back-view img { 171 | max-width: 35px; 172 | } 173 | .details { 174 | margin-top: 10px; 175 | padding: 0 15px; 176 | height: calc(100% / 4 - 20px); 177 | } 178 | .details p { 179 | height: 15px; 180 | font-size: 17px; 181 | padding-right: 13px; 182 | } 183 | .details button { 184 | font-size: 13px; 185 | padding: 5px 10px; 186 | border: none; 187 | background-color: #fff; 188 | border: 2px solid var(--bgColor); 189 | } 190 | } 191 | 192 | @media screen and (max-width: 325px) { 193 | .cards { 194 | height: 250px; 195 | width: 250px; 196 | } 197 | .card .back-view img { 198 | max-width: 30px; 199 | } 200 | .details { 201 | margin-top: 10px; 202 | padding: 0 15px; 203 | height: calc(100% / 4 - 20px); 204 | } 205 | .details p { 206 | height: 13px; 207 | font-size: 15px; 208 | padding-right: 13px; 209 | } 210 | .details button { 211 | font-size: 13px; 212 | padding: 2px 4px; 213 | border: none; 214 | background-color: #fff; 215 | border: 2px solid var(--bgColor); 216 | margin-left: 5px; 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 15 | 16 | Memory Card Game 17 | 18 | 19 | 20 | 21 | 22 |
23 | 131 |
132 | 133 | 134 | 135 | 136 | --------------------------------------------------------------------------------