Memory Game using HTML, CSS and JavaScript (Source Code) - Coding Torque

Memory Game using HTML, CSS and JavaScript

"Welcome to Coding Torque, fellow coders! In today's blog post, we will be embarking on a journey to create a classic memory game using HTML, CSS, and JavaScript. Not only will this project be a fun and engaging coding exercise, but it will also provide a chance for you to test your memory skills as you play the game. So grab your favorite beverage and let's get started building this fun and interactive game!

Join us on Telegram Join Now

Before we start, here are some more JavaScript Games you might like to create:

1. Snake Game using JavaScript

2. 2D Bouncing Ball Game using JavaScript

3. Rock Paper Scissor Game using JavaScript

4. Tic Tac Toe Game using JavaScript

5. QR Code Generator using JavaScript


I would recommend you don't just copy and paste the code, just look at the code and type by understanding it.


Demo



HTML Code

Starter Template

<!doctype html>
<html lang="en">

<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSS -->
    <link rel="stylesheet" href="style.css">

    <title>Memory Game using JavaScript - @code.scientist x @codingtorque</title>
</head>

<body>
    <!-- Further code here -->

    <script src="script.js"></script>
</body>

</html>


Paste the below code in your <body> tag

<main class="content">
    <header class="header">
        <h1 class="title">Memory Game</h1>
        <div class="movement">
            <h6 class="subtitle">Movements</h6>
            <div class="available" id="available"></div>
        </div>
    </header>
    <section class="card-container"></section>
</main>
<div class="modal" id="modal">
    <div class="modal-container">
        <h3 class="modal-title" id="modal-title">You win!</h3>
        <button type="button" class="button" id="play-again">Play Again</button>
    </div>
</div>


Output Till Now

Memory Game using HTML, CSS and JavaScript

CSS Code

Create a file style.css and paste the code below. 

@import url("https://fonts.googleapis.com/css2?family=Cormorant+Infant:ital,wght@1,600&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Raleway:wght@300;400;600&display=swap");

:root {
  --blue: #0282f9;
  --bridal-heath: #fffbf6;
  --dark-gray: #262626;
  --gray: #323232;
  --sidecar: #f4eac0;
  --white: #fff;
  --white-smoke: #f5f5f5;
}

* {
  box-sizing: border-box;
  font-family: "Raleway", serif;
  margin: 0;
  padding: 0;
}

body {
  background-color: var(--gray);
  padding: 1rem;
}

.content {
  margin: 0 auto;
  max-width: 85rem;
  width: 100%;
}

.title {
  color: var(--white);
  font-family: "Cormorant Infant", serif;
  font-size: 3rem;
  font-weight: 600;
  line-height: 1.2;
}

.header {
  align-items: center;
  display: flex;
  justify-content: space-between;
  margin-bottom: 1rem;
}

.movement {
  align-items: center;
  display: flex;
  flex-direction: column;
}

.subtitle {
  color: var(--white);
  font-size: 1rem;
  font-weight: 300;
  line-height: 1.2;
  margin-bottom: 0.25rem;
}

.available {
  border-radius: 0.25rem;
  box-shadow: inset 0.25rem 0.25rem 0.25rem rgba(0, 0, 0, 0.2),
    inset -0.25rem -0.25rem 0.25rem rgba(0, 0, 0, 0.2);
  color: var(--white);
  font-size: 2rem;
  font-weight: 600;
  padding: 0.5rem 1rem;
}

.card-container {
  display: grid;
  grid-gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
}

.card {
  background-color: var(--bridal-heath);
  border: 0.2rem solid var(--dark-gray);
  border-radius: 0.25rem;
  cursor: pointer;
  height: 12rem;
  position: relative;
  transform-style: preserve-3d;
  transition: transform 500ms ease-in-out;
  width: 100%;
}

.card--picked {
  transform: rotateY(180deg);
}

.card--guessed {
  background-color: var(--white-smoke);
  transform: rotateY(180deg) scale(0.9);
}

.card__front,
.card__back {
  align-items: center;
  backface-visibility: hidden;
  display: flex;
  height: 100%;
  justify-content: center;
  left: 0;
  padding: 1rem;
  pointer-events: none;
  position: absolute;
  top: 0;
  transition: transform 330ms ease-in-out;
  width: 100%;
}

.card__front {
  flex-direction: column;
  transform: rotateY(-180deg);
}

.card__back {
  background-color: var(--sidecar);
  transform: rotateY(0);
}

.front__img {
  margin-bottom: 0.5rem;
  width: 7rem;
}

.back__img {
  width: 6rem;
}

.card__name {
  font-size: 0.9rem;
  font-weight: 400;
  text-transform: capitalize;
}

/* Modal */
.modal {
  align-items: center;
  backdrop-filter: blur(0.2rem);
  background-color: rgba(0, 0, 0, 0.3);
  bottom: 0;
  display: flex;
  justify-content: center;
  left: 0;
  opacity: 0;
  position: fixed;
  right: 0;
  top: 0;
  transform: translateY(100%);
  transition: all 270ms ease-in;
}

.modal--open {
  opacity: 1;
  transform: translateY(0);
}

.modal-container {
  align-items: center;
  background-color: var(--white);
  border-radius: 0.5rem;
  display: flex;
  flex-direction: column;
  height: 12rem;
  justify-content: center;
  max-width: 20rem;
  padding: 1rem;
  width: 100%;
}

.modal-title {
  color: var(--dark-gray);
  font-size: 2rem;
  font-weight: 400;
  line-height: 1.2;
  margin-bottom: 1rem;
}

.button {
  background-color: var(--blue);
  border: 0.15rem solid var(--blue);
  color: var(--white);
  cursor: pointer;
  font-size: 1.1rem;
  font-weight: 600;
  padding: 0.5rem 1rem;
  transition: all 270ms ease-in;
}

.button:hover,
.button:active {
  background-color: var(--white);
  color: var(--blue);
}  

Output Till Now

Memory Game using HTML, CSS and JavaScript

JavaScript Code

Create a file script.js and paste the code below.

const CARDS = [
    {
        id: 1,
        name: 'javascript',
        img: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/74196/js-logo.png'
    },
    {
        id: 2,
        name: 'css3',
        img: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/74196/css3-logo.png'
    },
    {
        id: 3,
        name: 'html5',
        img: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/74196/html5-logo.png'
    },
    {
        id: 4,
        name: 'safari',
        img:
            'https://res.cloudinary.com/henryzarza/image/upload/v1601735663/General%20assets/safari_mw13q8.png'
    },
    {
        id: 5,
        name: 'rails',
        img: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/74196/rails-logo.png'
    },
    {
        id: 6,
        name: 'node',
        img: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/74196/nodejs-logo.png'
    },
    {
        id: 7,
        name: 'react',
        img:
            'https://res.cloudinary.com/henryzarza/image/upload/v1601735662/General%20assets/react_m1pmwj.png'
    },
    {
        id: 8,
        name: 'angular',
        img:
            'https://res.cloudinary.com/henryzarza/image/upload/v1601735662/General%20assets/angular_qqblks.png'
    },
    {
        id: 9,
        name: 'vuejs',
        img:
            'https://res.cloudinary.com/henryzarza/image/upload/v1601735662/General%20assets/vue_ctikzd.png'
    },
    {
        id: 10,
        name: 'svelte',
        img:
            'https://res.cloudinary.com/henryzarza/image/upload/v1601735662/General%20assets/svelte_keupr5.png'
    },
    {
        id: 11,
        name: 'chrome',
        img:
            'https://res.cloudinary.com/henryzarza/image/upload/v1601735663/General%20assets/chrome_lr919s.png'
    },
    {
        id: 12,
        name: 'mozilla',
        img:
            'https://res.cloudinary.com/henryzarza/image/upload/v1601735663/General%20assets/mozilla_us5y7o.png'
    }
];
const cardContainer = document.querySelector('.card-container');
const available = document.querySelector('#available');
const modalTitle = document.querySelector('#modal-title');
const modal = document.querySelector('#modal');
let currentCards = [...CARDS, ...CARDS];
let isPaused = false;
let counter = CARDS.length + 10;
let isLose = false;

// Fisher--Yates Algorithm -- https://bost.ocks.org/mike/shuffle/
function shuffle(array) {
    let counter = array.length,
        temp,
        index;
    while (counter > 0) {
        index = Math.floor(Math.random() * counter);
        counter--;
        temp = array[counter];
        array[counter] = array[index];
        array[index] = temp;
    }
    return array;
}

function win() {
    isPaused = true;
    modalTitle.innerHTML = 'You win! 🙌🥳';
    modal.classList.add('modal--open');
}

function lose() {
    isLose = true;
    modalTitle.innerHTML = 'You lose 😢😩';
    modal.classList.add('modal--open');
}

function handleClick(e) {
    const { target } = e;
    if (
        !isPaused &&
        !isLose &&
        !target.classList.contains('card--guessed') &&
        !target.classList.contains('card--picked')
    ) {
        isPaused = true;
        const picked = cardContainer.querySelector('.card--picked');
        if (picked) {
            if (picked.dataset.id === target.dataset.id) {
                target.classList.remove('card--picked');
                picked.classList.remove('card--picked');
                target.classList.add('card--guessed');
                picked.classList.add('card--guessed');
                isPaused = false;
            } else {
                target.classList.add('card--picked');
                setTimeout(() => {
                    target.classList.remove('card--picked');
                    picked.classList.remove('card--picked');
                    isPaused = false;
                }, 1500);
            }
            console.log('counter', counter);
            counter -= 1;
            available.innerHTML = counter;
            if (counter === 0) {
                lose();
            }
        } else {
            target.classList.add('card--picked');
            isPaused = false;
        }

        // Validate is already win
        const isWin = cardContainer.querySelectorAll('card--guessed').length === currentCards.length;
        if (isWin) {
            win();
        }
    }
}

function drawCards() {
    cardContainer.innerHTML = '';
    available.innerHTML = counter;

    shuffle(currentCards).forEach((el) => {
        const card = document.createElement('div');
        card.className = 'card';
        card.setAttribute('data-id', el.id);
        card.innerHTML = `
          <div class="card__front">
            <img
              class="front__img"
              src="${el.img}"
              alt="${el.name}"
            />
            <h6 class="card__name">${el.name}</h6>
          </div>
          <div class="card__back">
            <img
              class="back__img"
              src="https://res.cloudinary.com/henryzarza/image/upload/v1601745355/General%20assets/thought_pr1pzv.png"
              alt="Thought"
            />
          </div>
        `;
        card.addEventListener('click', handleClick);
        cardContainer.appendChild(card);
    });
}

document.querySelector('#play-again').addEventListener('click', function () {
    modal.classList.remove('modal--open');
    isPaused = false;
    isLose = false;
    counter = CARDS.length + 10;
    drawCards();
});

drawCards();

Join us on Telegram Join Now

Written by: Coding Torque | Piyush Patil

Code Credits: @HenryZarza

If you have any doubts or any project ideas feel free to Contact Us 

Hope you find this post helpful💖
 
 Follow us on Instagram for more projects like this👨‍💻 

Post a Comment

Previous Post Next Post