JSFiddle - React, Tailwind, and code Playground

by clapynick

HTML

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

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, intitial-scale=1">
    <title>Matching Game</title>
    <meta name="description" content="">
    <link rel="stylesheet prefetch" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css">
    <link rel="stylesheet prefetch" href="https://fonts.googleapis.com/css?family=Coda">
    <link rel="stylesheet" href="css/app.css">
</head>

<body>

    <div class="container">
        <header>
            <h1>Matching Game</h1>
        </header>

        <section class="score-panel">
            <span id="timer">Timer: 00 s</span>

            <span class="moves">Move(s): 0</span>

            <ul class="stars">
                <li><i class="fa fa-star"></i></li>
                <li><i class="fa fa-star"></i></li>
                <li><i class="fa fa-star"></i></li>
            </ul>

            <div class="restart">
                <i class="fa fa-repeat"></i>
            </div>
        </section>

        <ul class="deck">
            <li class="card">
                <i class="fa fa-diamond"></i>
            </li>
            <li class="card">
                <i class="fa fa-paper-plane-o"></i>
            </li>
            <li class="card">
                <i class="fa fa-anchor"></i>
            </li>
            <li class="card">
                <i class="fa fa-bolt"></i>
            </li>
            <li class="card">
                <i class="fa fa-cube"></i>
            </li>
            <li class="card">
                <i class="fa fa-anchor"></i>
            </li>
            <li class="card">
                <i class="fa fa-leaf"></i>
            </li>
            <li class="card">
                <i class="fa fa-bicycle"></i>
            </li>
            <li class="card">
                <i class="fa fa-diamond"></i>
            </li>
            <li class="card">
                <i class="fa fa-bomb"></i>
       ...

CSS

html {
    box-sizing: border-box;
}

*,
*::before,
*::after {
    box-sizing: inherit;
}

html,
body {
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
}

body {
    background: #ffffff url('../img/geometry2.png'); /* Background pattern from Subtle Patterns */
    font-family: 'Coda', cursive;
}

.container {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
}

h1 {
    font-family: 'Open Sans', sans-serif;
    font-weight: 300;
}

/*
 * Styles for the deck of cards
 */

.deck {
    width: 660px;
    min-height: 680px;
    background: linear-gradient(160deg, #02ccba 0%, #aa7ecd 100%);
    padding: 32px;
    border-radius: 10px;
    box-shadow: 12px 15px 20px 0 rgba(46, 61, 73, 0.5);
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    margin: 0 0 3em;
}

.deck .card {
    height: 125px;
    width: 125px;
    background: #2e3d49;
    font-size: 0;
    color: #ffffff;
    border-radius: 8px;
    cursor: pointer;
    display: flex;
    justify-content: center;
    align-items: center;
    box-shadow: 5px 2px 20px 0 rgba(46, 61, 73, 0.5);
}

.deck .card.open {
    transform: rotateY(0);
    background: #02b3e4;
    cursor: default;
}

.deck .card.show {
    font-size: 33px;
}

.deck .card.match {
    cursor: default;
    background: #02ccba;
    font-size: 33px;
}



/*
 * Styles for the Score Panel
 */

.score-panel {
    font-weight: bold;
    text-align: center;
    width: 630px;
    margin-bottom: 10px;
}

.score-panel .stars {
    margin: 0 20px;
    padding: 0;
    display: inline-block;
    margin: 0 0 0 30px;
    color: #02b3e4;
}

.score-panel .stars li {
    list-style: none;
    display: inline-block;
}

.score-panel .restart {
    float: right;
    cursor: pointer;
    margin-right: 80px;
}

#timer{
   float: left;
   margin-right: -300px;
   margin-left: 20px;
}

.moves{
    margin-right: 60px;
    margin-left: 80px;
}

JavaScript

let card = document.getElementsByClassName('card'),
    cards = [...card],
    checkName = [], // store the name of the shape (based on class name) to compare if card matches or not
    matchCard = [], // store parent of clicked card in this array to change its class for flipping card that matches
    totalMatchedCards = [],
    t0, // start time of timer when player select a card
    counter = 0, // move(s) counter
    winGame = false, // to be used later!!!
    deck = document.getElementsByClassName('deck')[0];

//shuffle the deck and add it
shuffle(cards);

for (let i = 0; i < cards.length; i++) {
    card = cards[i];
    card.addEventListener('click', _ => game(i));

}

// RESTART
document.getElementsByClassName('fa-repeat')[0].addEventListener('click', function () {
    // shuffle the deck and add it
    shuffle(cards);
    t0 = Date.now(), counter = 0;
    setInterval(timer);
});


function game(i) {

    /* skip any matched cards so they aren't clickable nor stored anywhere
    note to myself: return true is same as continue */
    if (cards[i].classList[1] === "match" || cards[i].classList[1] === "open" || cards[i].classList[1] === "show") {
        return true;
    }

    // open/close cards
    if (matchCard.length <= 1) { // don't open more than two cards!
        revealCard(cards[i]); // new func
    }

    // add cards to array
    openCards(cards[i]); //new func

    // empty the arrays & close inncorrect matching.
    if (matchCard.length === 2) {
        checkMatching();
        automaticallyCloseCards();
        counter++;
    }

    if (counter === 0) {
        t0 = Date.now();
        setInterval(timer);
    }
    if (totalMatchedCards.length === 16) {
        winGame = true;
        console.log("PLAYER HAS WON THE GAME!!") // to be changed to result pop up.
    }

    // STARS Rating
    if (counter === 15) {
        document.getElementsByClassName('fa-star')[2].style.color = "#d3d3d3";
    }
    if (counter === 20) {
       ...