JSFiddle - React, Tailwind, and code Playground

by Gwyn Milcote

HTML

<h2>Card memory game</h2>

<div id='mem-container'></div>

<p>
    <button id='mem-reveal-btn'>Reveal</button> |
    Cards: <select id='mem-select-number'> 
        <option>8</option>
        <option>12</option>
        <option>16</option>
        <option>24</option>
        <option>36</option>
    </select>
    <button id='mem-reset-btn'>Reset</button>
</p>


<h2>Ships</h2>

<div id='ships-container'></div>

<p><button id='ships-reveal-btn'>Reveal</button> | <button id='ships-reset-btn'>Reset</button></p>


<h2>Mahjong</h2>

<div id='maj-container'></div>

<p><button id='maj-hint-btn'>Show Hint</button> | <button id='maj-reset-btn'>Reset</button></p>

CSS

div, img, p, canvas, btn {
    box-sizing: border-box;
}

/* CARD MEMORY GAME */

#mem-container {
    display: flex;
    flex-flow: row wrap;
}

#mem-container .mem-card-empty {
    width: 100px;
    height: 100px;
    margin: 5px;
}

#mem-container .mem-card {
    width: 100px;
    height: 100px;
    border: 1px solid silver;
    background-color: #eee;
    margin: 5px;
}

#mem-container .mem-card:hover {
    cursor: pointer;
}


/* SHIPS */

table {
    border-collapse: collapse;
}
table th {
    width: 26px;
    height: 26px;
    background-color: #eee;
    border: 1px solid grey;
    padding: 3px;
}
table td {
    background-color: #fff;
    border: 1px solid silver;
    padding: 3px;
}


/* MAHJONG */

#maj-container {
    
}

JavaScript

const db = {

    // Pairs of cards for memory game.
    cards: [
        {id: 1, name: "Valravn"},
        {id: 2, name: "Meganeura"},
        {id: 3, name: "Opinicus"},
        {id: 4, name: "Marlik"},
        {id: 5, name: "Aquila"},
        {id: 6, name: "Frizzle"},
        {id: 7, name: "Achaemenid"},
        {id: 8, name: "Minoan"},
        {id: 9, name: "Osprey"},
        {id: 10, name: "Owl"},
        {id: 11, name: "Peregrine"},
        {id: 12, name: "Bald"},
        {id: 13, name: "Heraldic"},
        {id: 14, name: "Hippogriff"},
        {id: 15, name: "Axex"},
        {id: 16, name: "Hieracosphinx"},
        {id: 17, name: "Hieracosphinx"},
        {id: 18, name: "Hieracosphinx"}
    ],
    
    
};

function shuffle(array){
    for (let i = array.length - 1; i > 0; i--){
        let j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
    }
}

function randomNumber(min, max){
  return Math.floor(Math.random() * (max - min + 1) + min);
}

function randomArray(array){
    return array[Math.floor(Math.random()*array.length)];
}


class MemoryGame {

    constructor(){
        this.pairs = [
            "owl", "aquila", "fantail", "valravn", 
            "hippogriff", "minoan", "axex", "frizzle",
            "achae", "osprey", "bald", "marlik",
            "peregrine", "meganeura", "hier", "byz",
            "butterfly", "heraldic", "opi", "pea"
        ];
        this.reset(12);
    }
    
    reset(num){
        this.totalCards = num;
        this.wrongGuesses = 0;
        this.timeElapsed = 0;
        this.cards = [];
        this.cardsVisible = [];
        
        for(let i = 0; i < num; i++){
            let pair = this.pairs[Math.floor(i / 2)];
            
            let card = {
                id: (i + 1),
                pair: (Math.floor(i / 2) + 1),
                removed: false
            };
            this.cards.push(card);
        }
        
        shuffle(this.cards);
        
       ...