JSFiddle - React, Tailwind, and code Playground

by cmacrander

HTML

<!DOCTYPE html>
<html>
<head>
    <title>Minefield</title>
</head>

<body>
    <table id="minefield">
    <tr>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
    </tr>
    <tr>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td class="hidden"></td>
        <td...

CSS

#minefield {
    border-collapse: collapse;
    font-size: 1.0em;
    font-family: Verdana, sans-serif;
}

#minefield td {
    width: 19px;
    height: 20px;
    border: 1px solid black;
    text-align: center;
}

#minefield td.hidden {
    background-color: grey;
}

#minefield td.revealed {
    background-color: white;
}

JavaScript

// ** GLOBALS ** //

var fieldWidth = 30;
var fieldHeight = 16;
var totalSquares = fieldHeight * fieldWidth;
var totalMines = 99;
var minefield;

// ** MAIN ** //

dojo.addOnLoad(function() {
    minefield = generateMinefield();

    // create all the square widgets
    var index = 0;
    dojo.query("td", "minefield").forEach(function(node) {
        Square.list.push(new Square(node, index));
        index++;
    });

    // allow them to look at their surroundings
    Square.list.forEach(function(square) {
        square.init();
    });

    // find a place to start sweeping.
    var started = false;
    while(!started) {
        var s = Square.list[randomIndex()];
        if(s.d === 0 && !s.isMine()) {
            s.reveal();
            started = true;
        }
    }        

    while(sweep());
});

// ** CLASS MapSet ** //
// Purpose: to hold and analyze information about possible
// arrangements of mines around a square. Can combine with
// other map sets to determine if any certainties can be
// established about where mines must be or must not be.

function MapSet(square) {
    if(!(square instanceof Square)) console.error("Bad input for MapSet", square);
    
    var indices = [];    // list of indices of hidden unmarked neighbors
    this.maps = [];        // will contain all maps
    
    // get indices of hidden neighbors
    square.neighbors.forEach(function(n) {
        if(n.isHidden && !n.isMarked) indices.push(n.index);
    });
    
    // generate possible arrangements of mines (simple lists of 0s and 1s)
    var samples = Util.createBinomialSamples(square.hu, square.r);
    
    // match up the arrangements with the indices and store them as maps
    samples.forEach(function(sample) {
        var map = [];
        for(var x = 0; x < indices.length; x++) {
            map[indices[x]] = sample[x];
        }
        this.maps.push(map);
    }, this);
}

// combines mapSets, testing all combinations and keeping
// only those that completely agree,...