JSFiddle - React, Tailwind, and code Playground

by Gwyn Milcote

HTML

Width: <input id='select_width' type='number' min='8' max='30' value='10'> 
Height: <input id='select_height' type='number' min='8' max='30' value='10'> Mines: <input id='select_mines' type='number' min='6' max='50' value='10'> 

<button id='reset_button'>Start</button>
<button id='reveal_button'>Reveal</button>

<table id='game_board'></table>

<p id='test_info'></p>

CSS

div {
    box-sizing: border-box;
}

input {
    width: 40px;
}

/* The main table. */
#game_board {
    border: 1px solid black;
    margin: 20px auto;
    border-collapse: collapse;
}

/* All the cells in the table. */
#game_board td {
    border: 1px solid grey;
    transition: 0.2s;
    font-size: 20px;
    text-align: center;
}

/* Different cell sizes for larger boards. */
.cell_small {
    width: 20px;
    height: 20px;
}
.cell_medium {
    width: 25px;
    height: 25px;
}
.cell_large {
    width: 30px;
    height: 30px;
}

/* Nice highlight effect when hovering. */
#game_board td:hover {
    cursor: pointer;
    background-color: white;
    transition: 0.2s;
}

/* Styles for different statuses. */
.cell_default {
    background-color: silver;
}
.cell_empty {
    background-color: #eee;
}
.cell_mine {
    background-color: crimson;
}
.cell_flag {
    background-color: pink;
}
.cell_number {
    background-color: white;
}

JavaScript

let width = 10,
    height = 10,
    mines = 10,
    mineLocations = [],
    cells = [];

function drawGrid(){
    let html = "";
    cells = [];
    for(let y = 0; y < height; y++){
        html += "<tr>";
        let row = [];
        
        for(let x = 0; x < width; x++){
            let style = "large";
            if(width > 15 || height > 15){ style = "medium"; }
            if(width > 22 || height > 22){ style = "small"; }
            
            html += "<td id='cell_"  +x  + "_" + y + "' class='cell cell_default cell_" + style + "' data-x='" + x + "' data-y='" + y + "'></td>";
            row.push(0);
        }
        
        html += "</tr>";
        cells.push(row);
    }
    document.getElementById("game_board").innerHTML = html;
}

/*
* Mine co-ords are stored in own array. For grabbing convenience.
* But cells also contain mines: number 2.
*/
function scatterMines(){
    let i = 0;
    mineLocations = [];
    while(i <= mines){
        let y = randomNumber(0, height - 1);
        let x = randomNumber(0, width - 1);
        
        if(!mineLocations.includes(x + "_" + y)){
            mineLocations.push(x + "_" + y);
            cells[y][x] = 2;
            i++;
        }
    }
}

function revealMines(){
    for(let mine of mineLocations){
        let v = "cell_" + mine;
        console.log(v);
        let cell = document.getElementById(v);
        cell.classList.remove("cell_default");
        cell.classList.add("cell_mine");
    }
}

function clickCell(x,y){
    let cell = document.getElementById("cell_" + x + "_" + y);
    if(cells[y][x] != 1){
        // Check if a mine is here.
        //if(mineLocations.includes(x + "_" + y)){
        if(cells[y][x] == 2){
            gameOver();
        }else{
            cells[y][x] = 1;
            cell.classList.remove("cell_default");
            cell.classList.add("cell_empty");
        }
    }
}

function randomNumber(n1, n2){
    if(n1 == n2){ return n1; }
    var min = n1; var max = n2;
    if(n1...