JSFiddle - React, Tailwind, and code Playground

vatoSupport Sudoku Game

by Jennifer Perrin

HTML

<link rel="stylesheet" href="https://jennperrin.com/support/css/bootstrap.css">
<link rel="stylesheet" href="https://jennperrin.com/support/css/custom.css">
<link rel="stylesheet" href="https://jennperrin.com/support/css/styles.css">
<script src="https://jennperrin.com/support/js/bootstrap.js"></script>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css">
<nav class="navbar navbar-inverse navbar-static-top">
    <div class="container-fluid">
        <div class="container no-padding">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only">Toggle Navigation</span>
 <span class="icon-bar"></span>
 <span class="icon-bar"></span>
 <span class="icon-bar"></span>

                </button>
            </div>
            <div id="navbar" class="navbar-collapse collapse">
                <ul class="nav navbar-nav"></ul>
            </div>
        </div>
    </div>
</nav>
<div class="container-fluid headerBar">
    <div class="container no-padding">
        <p class="site-title"><a href="https://jennperrin.com/support" rel="home"><img src="https://jennperrin.com/support/images/logo-header.png" alt="authosSupport" /></a>
        </p>
        <p class="site-description">Forkable Fiddle</p>
        <p class="newSupportBtn"> <a data-toggle="modal" href="#sudoku" class="btn btn-info btn-lg btnIcon"><i class="fa fa-th"></i> Sudoku</a>

        </p>
    </div>
</div>
<div class="container"></div>
<div class="modal fade" id="sudoku" tabindex="-1" role="dialog" aria-hidden="true">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true"><i class="fa fa-times"></i></span>
               ...

CSS

@import url(http://fonts.googleapis.com/css?family=Muli:200, 300, 400, 700);
 .sudoku_board {
    margin:6px auto;
    overflow: hidden;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    box-shadow: 0px 0px 5px 5px #bdc3c7;
}
.sudoku_board .cell {
    width:11.11%;
    display: inline-block;
    float:left;
    cursor:pointer;
    text-align: center;
    overflow: hidden;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    box-shadow: 0px 0px 0px 1px #bdc3c7;
    background:white;
}
.sudoku_board .cell.border_h {
    box-shadow: 0px 0px 0px 1px #bdc3c7, inset 0px -2px 0 0 #34495e;
}
.sudoku_board .cell.border_v {
    box-shadow: 0px 0px 0px 1px #bdc3c7, inset -2px 0 0 #34495e;
}
.sudoku_board .cell.border_h.border_v {
    box-shadow: 0px 0px 0px 1px #bdc3c7, inset -2px 0 0 black, inset 0px -2px 0 black;
}
.sudoku_board .cell span {
    color:#2c3e50;
    font-size:14px;
    text-align:middle;
}
.sudoku_board .cell.selected, .sudoku_board .cell.selected.fix {
    background:#FFE;
}
.sudoku_board .cell.selected.current {
    position:relative;
    background: #3498db;
    font-weight:bold;
    box-shadow: 0px 0px 3px 3px #bdc3c7;
}
.sudoku_board .cell.selected.current span {
    color:white;
}
.sudoku_board .cell.selected.group {
    color:blue;
}
.sudoku_board .cell span.samevalue, .sudoku_board .cell.fix span.samevalue {
    font-weight:bold;
    color:#3498db;
}
.sudoku_board .cell.notvalid, .sudoku_board .cell.selected.notvalid {
    font-weight:bold;
    color:white;
    ;
    background:#e74c3c;
}
.sudoku_board .cell.fix {
    background:#ecf0f1;
    cursor:not-allowed;
}
.sudoku_board .cell.fix span {
    color:#7f8c8d;
}
.sudoku_board .cell .solution {
    font-size:10px;
    color:#d35400;
}
.sudoku_board .cell .note {
    color:#bdc3c7;
    width:50%;
    height:50%;
    display: inline-block;
    float:left;
    text-align:center;
   ...

JavaScript

function Sudoku(params) {
    var t = this;

    this.INIT = 0;
    this.RUNNING = 1;
    this.END = 2;

    this.id = params.id || 'sudoku_container';
    this.displaySolution = params.displaySolution || 0;
    this.displaySolutionOnly = params.displaySolutionOnly || 0;
    this.displayTitle = params.displayTitle || 0;
    this.highlight = params.highlight || 0;
    this.fixCellsNr = params.fixCellsNr || 32;
    this.n = 3;
    this.nn = this.n * this.n;
    this.cellsNr = this.nn * this.nn;

    if (this.fixCellsNr < 10) this.fixCellsNr = 10;
    if (this.fixCellsNr > 70) this.fixCellsNr = 70;

    this.init();

    //counter    
    setInterval(function () {
        t.timer();
    }, 1000);

    return this;
}

Sudoku.prototype.init = function () {
    this.status = this.INIT;
    this.cellsComplete = 0;
    this.board = [];
    this.boardSolution = [];
    this.cell = null;
    this.markNotes = 0;
    this.secondsElapsed = 0;

    if (this.displayTitle == 0) {
        $('#sudoku_title').hide();
    }

    this.board = this.boardGenerator(this.n, this.fixCellsNr);

    return this;
};

Sudoku.prototype.timer = function () {
    if (this.status === this.RUNNING) {
        this.secondsElapsed++;
        $('.time').text('' + this.secondsElapsed);
    }
};

/**
Shuffle array
*/
Sudoku.prototype.shuffle = function (array) {
    var currentIndex = array.length,
        temporaryValue = 0,
        randomIndex = 0;

    while (0 !== currentIndex) {
        randomIndex = Math.floor(Math.random() * currentIndex);
        currentIndex -= 1;
        temporaryValue = array[currentIndex];
        array[currentIndex] = array[randomIndex];
        array[randomIndex] = temporaryValue;
    }

    return array;
};

/**
Generate the sudoku board
*/
Sudoku.prototype.boardGenerator = function (n, fixCellsNr) {
    var matrix_fields = [],
        index = 0,
        i = 0,
        j = 0,
        j_start = 0,
        j_stop = 0;

    //generate solution
    this.boardSolution = [];

 ...