When We first started playing with writing a Sudoku game, I took the long way to create Sudoku templates and to make a sudoku puzzle in html Using a recursive backtracking algorithm, I would slowly fill up the grid with random numbers – checking the validity of the puzzle at each step. If I hit a roadblock where the puzzle cannot be completed, the algorithm would backtrack until it could move forward, and then move forward again. how to make a sudoku game in javascript,

There is a more elegant solution however: create a solved sudoku and then shuffle it.

Generate and Solved Sudoku

1.Step : Creating the solved Sudoku is easy: just shift the row above to the left by 3 unless its vertical index is equally divisible by 3 (starting with index 0) in which case shift the row above by 4.

1 2 3 4 5 6 7 8 9
4 5 6 7 8 9 1 2 3
7 8 9 1 2 3 4 5 6
2 3 4 5 6 7 8 9 1
5 6 7 8 9 1 2 3 4
8 9 1 2 3 4 5 6 7
3 4 5 6 7 8 9 1 2
6 7 8 9 1 2 3 4 5
9 1 2 3 4 5 6 7 8


2.Step : Shuffle the rows and columns. Of course, to do so and ensure the Sudoku rules maintain integrity, you can only shuffle rows and columns of the same group: groups being 1-3, 4-6, and 7-9. Demonstrated below, the columns 1 and 3 are shuffled

<img fetchpriority=

Sudoku Puzzle Game Source Code

index.html

<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>DeepCrazyWorld - SUDOKU Puzzle Project</title>
  <link rel="stylesheet" href="./style.css">

</head>
<body>
<!-- partial:index.partial.html -->
<a href="#" id="sidebar-toggle">
   <span class="bar"></span>
   <span class="bar"></span>
   <span class="bar"></span>
</a>

<h1 id="sudoku_title">SUDOKU PROJECT</h1>

<div id="sudoku_menu">
  <ul>
    <li><a class="restart" href="#">New Game</a></li>
    <li></li>
  </ul>
</div>

<div id="sudoku_container"></div>
<!-- partial -->
  <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script><script  src="./script.js"></script>

</body>
</html>

Make a puzzle in html

style.css

h1 { 
    background:black;
    color:white;
    margin:0px 0px 2px 0px;
    font-size:20px;
    padding:2px 1px 5px 1px;
    text-align:center;    
}

body {
    font-family:verdana,helvetica,arial,sans-serif;
    border:0px; margin:0px; padding:0px;
        
    background:url(
        data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAIUlEQVQYV2N89urtfwYiACNIoZSYMCMhtaMK8YYQ0cEDAG5yJ8eLRhTfAAAAAElFTkSuQmCC
    ) repeat;
}

/* board */
.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; /* Safari/Chrome, other WebKit */
	    -moz-box-sizing: border-box;    /* Firefox, other Gecko */
	    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;
    font-size:14px;
  
    -webkit-box-sizing: border-box;
	    -moz-box-sizing: border-box;
	    box-sizing: border-box;
}

.gameover_container .gameover {
    color:white;
    font-weight:bold;
	    text-align:center; 
    
    display:block;
    position:absolute;       
    width:90%;    
    padding:10px;
    
    box-shadow: 0px 0px 5px 5px #bdc3c7;
}


.restart {
  background:#7F8C8D;
  color:#ecf0f1;
}

/* console */
.board_console_container, .gameover_container {
    background-color: rgba(127, 140, 141, 0.7);
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    
     -webkit-user-select: none;  
     -moz-user-select: none;    
     -ms-user-select: none;      
     user-select: none;
}

.board_console {
    display:block;
    position:absolute;        
    width:50%;        
    color:white;
    background-color: rgba(127, 140, 141, 0.7);
    box-shadow: 0px 0px 5px 5px #bdc3c7;
}

.board_console .num {
    width:33.33%;    
    color:#2c3e50;    
    padding: 1px;
    display: inline-block;    
    font-weight:bold;
    font-size:24px;
    text-align: center;    
    cursor:pointer;
    
    -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
	    -moz-box-sizing: border-box;    /* Firefox, other Gecko */
	    box-sizing: border-box;
    
    box-shadow: 0px 0px 0px 1px #bdc3c7;
}


.board_console .num:hover {
    color:white;
    background:#f1c40f;
}

.board_console .num.remove {
    width:66.66%;    
}

.board_console .num.note {
    background:#95a5a6;
    color:#ecf0f1;
}

.board_console .num.note:hover {
    background:#95a5a6;
    color:#f1c40f;
}

.board_console .num.selected {
    background:#f1c40f;
    box-shadow: 0px 0px 3px 3px #bdc3c7;
}

.board_console .num.note.selected {
    background:#f1c40f;  
    box-shadow: 0px 0px 3px 3px #bdc3c7;
}

.board_console .num.note.selected:hover {
  color:white;
}

.board_console .num.no:hover {
    color:white;
    cursor:not-allowed;
}

.board_console .num.remove:hover {
    color:white;
    background:#c0392b;
}

.statistics {
    text-align:center;    
}

#sudoku_menu {
    background-color: black;
    position: absolute;
    z-index:2;
    width: 100%;
    height: 100%;
    left: -100%;
    box-sizing: border-box;
    -moz-box-sizing: border-box;
}

#sudoku_menu ul {
   margin: 0;
   padding: 100px 0px 0px 0px;
   list-style: none;
}

#sudoku_menu ul li{
  margin: 0px 50px;
}

#sudoku_menu ul li a {
  text-align:center;
  padding: 15px 20px;
  font-size: 28px;
  font-weight: bold;
  color: white;
  text-decoration: none;
  display: block;
  border-bottom: 1px solid #2c3e50;
}

#sudoku_menu.open-sidebar {
  left:0px;
}

#sidebar-toggle {
    z-index:3;
    background: #bdc3c7;
    border-radius: 3px;
    display: block;
    position: relative;
    padding: 22px 18px;
    float: left;
}

#sidebar-toggle .bar{
    display: block;
    width: 28px;
    margin-bottom: 4px;
    height: 4px;
    background-color: #f0f0f0;
    border-radius: 1px;   
}

#sidebar-toggle .bar:last-child{
     margin-bottom: 0;   
}

/*Responsive Stuff*/

@media all and (orientation:portrait) and (min-width: 640px){
    h1 { font-size:50px; }
    .statistics { font-size:30px; }    
    .sudoku_board .cell span { font-size:60px; }    
    .board_console .num { font-size:60px; }
}

@media all and (orientation:landscape) and (min-height: 640px){
    h1 { font-size:50px; }
    .statistics { font-size:30px; }
    .sudoku_board .cell span { font-size:50px; }
    .board_console .num { font-size:50px; }
}

@media all and (orientation:portrait) and (max-width: 1000px){
    .sudoku_board .cell span { font-size:30px; }   
}

@media all and (orientation:portrait) and (max-width: 640px){
	.sudoku_board .cell span { font-size:24px; }
  .sudoku_board .cell .note { font-size:10px; }
}

@media all and (orientation:portrait) and (max-width: 470px){
	.sudoku_board .cell span { font-size:16px; }
.sudoku_board .cell .note { font-size:8px; }
}

@media all and (orientation:portrait) and (max-width: 320px){
	.sudoku_board .cell span { font-size:12px; }
.sudoku_board .cell .note { font-size:8px; }
}

@media all and (orientation:portrait) and  (max-width: 240px){
	.sudoku_board .cell span { font-size:10px; }   
}

create a sudoku game in html css and js

script.js


/**
Sudoku game by deepcrazyworld
*/
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 = [];
  
    //shuffle matrix indexes
    for (i = 0; i < this.nn; i++) {
        matrix_fields[i] = i+1;
    }  
    
    //shuffle sudoku 'collors'
    matrix_fields = this.shuffle(matrix_fields);
    for (i = 0; i < n*n; i++) {
        for (j = 0; j < n*n; j++) {
            var value = Math.floor( (i*n + i/n + j) % (n*n) + 1 );            
            this.boardSolution[index] = value;
            index++;
        }
    }
    
    //shuffle sudokus indexes of bands on horizontal and vertical
    var blank_indexes = [];    
    for (i = 0; i < this.n; i++) {
        blank_indexes[i] = i+1;        
    }
  
    
    //shuffle sudokus bands horizontal
    var bands_horizontal_indexes = this.shuffle(blank_indexes);
    var board_solution_tmp = [];
    index = 0;
    for (i = 0; i < bands_horizontal_indexes.length; i++) {
        j_start = (bands_horizontal_indexes[i] -1) * this.n * this.nn;
        j_stop  = bands_horizontal_indexes[i] * this.n * this.nn;
        
        for( j = j_start; j < j_stop; j++ ) {
          board_solution_tmp[index] = this.boardSolution[j];
          index++;
        }
    }
    this.boardSolution = board_solution_tmp;
    
    
    //shuffle sudokus bands vertical
    var bands_vertical_indexes   = this.shuffle(blank_indexes);
    board_solution_tmp = [];
    index = 0;    
    for (k = 0; k < this.nn; k++) {      
      for (i = 0; i < this.n; i++) {      
        j_start = (bands_vertical_indexes[i]-1) * this.n;
        j_stop  = bands_vertical_indexes[i] * this.n;
      
        for( j = j_start; j < j_stop; j++ ) {
          board_solution_tmp[index] = this.boardSolution[j + (k*this.nn)];
          index++;
        }
      }
    }
    this.boardSolution = board_solution_tmp;
    
    //shuffle sudokus lines on each bands horizontal
    //TO DO
  
    //shuffle sudokus columns on each bands vertical
    //TO DO
    
    //board init
    var board_indexes =[],
        board_init = [];
  
    //shuffle board indexes and cut empty cells    
    for (i=0; i < this.boardSolution.length; i++) {
        board_indexes[i] = i;
        board_init[i] = 0;
    }
    
    board_indexes = this.shuffle(board_indexes);
    board_indexes = board_indexes.slice(0, this.fixCellsNr);
    
    //build the init board    
    for (i=0; i< board_indexes.length; i++) {
        board_init[ board_indexes[i] ] = this.boardSolution[ board_indexes[i] ];
        if (parseInt(board_init[ board_indexes[i] ]) > 0) {
          this.cellsComplete++;
        }
    }
    
    return (this.displaySolutionOnly) ? this.boardSolution : board_init;    
};

/**
Draw sudoku board in the specified container
*/
Sudoku.prototype.drawBoard = function(){
    var index = 0,
        position       = { x: 0, y: 0 },
        group_position = { x: 0, y: 0 };
    
    var sudoku_board = $('<div></div>').addClass('sudoku_board');
    var sudoku_statistics = $('<div></div>')
                                .addClass('statistics')
    .html('<b>Cells:</b> <span class="cells_complete">'+ this.cellsComplete +'/'+this.cellsNr +'</span> <b>Time:</b> <span class="time">' + this.secondsElapsed + '</span>');
    
    $('#'+ this.id).empty();
    
    //draw board 
    for (i=0; i < this.nn; i++) {
        for (j=0; j < this.nn; j++) {
            position       = { x: i+1, y: j+1 };
            group_position = { x: Math.floor((position.x -1)/this.n), y: Math.floor((position.y-1)/this.n) };
            
            var value = (this.board[index] > 0 ? this.board[index] : ''),
                value_solution = (this.boardSolution[index] > 0 ? this.boardSolution[index] : ''),
                cell = $('<div></div>')
                            .addClass('cell')
                            .attr('x', position.x)
                            .attr('y', position.y)
                            .attr('gr', group_position.x +''+ group_position.y)
                            .html('<span>'+ value +'</span>' );
          
            if (this.displaySolution) {
               $('<span class="solution">('+ value_solution +')</span>').appendTo(cell);
            }
          
            if ( value > 0) {
                cell.addClass('fix');
            }
            
            if ( position.x % this.n === 0 && position.x != this.nn ) {
                cell.addClass('border_h');
            }
            
            if ( position.y % this.n === 0 && position.y != this.nn ) {
                cell.addClass('border_v');
            }
            
            cell.appendTo(sudoku_board);
            index++;
        }
    }
    
    sudoku_board.appendTo('#'+ this.id);
    
    //draw console
    var sudoku_console_cotainer = $('<div></div>').addClass('board_console_container');
    var sudoku_console = $('<div></div>').addClass('board_console');
    
    for (i=1; i <= this.nn; i++) {
        $('<div></div>').addClass('num').text(i).appendTo(sudoku_console);
    }
    $('<div></div>').addClass('num remove').text('X').appendTo(sudoku_console);
    $('<div></div>').addClass('num note').text('?').appendTo(sudoku_console);
    
    //draw gameover
    var sudoku_gameover = $('<div class="gameover_container"><div class="gameover">Congratulation! <button class="restart">Play Again</button></div></div>');
    
    //add all to sudoku container
    sudoku_console_cotainer.appendTo('#'+ this.id).hide();
    sudoku_console.appendTo(sudoku_console_cotainer);    
    sudoku_statistics.appendTo('#'+ this.id);
    sudoku_gameover.appendTo('#'+ this.id).hide();  
  
    //adjust size
    this.resizeWindow();
};

Sudoku.prototype.resizeWindow = function(){
    console.time("resizeWindow");
    
    var screen = { w: $(window).width(), h: $(window).height() };
    
    //adjust the board
    var b_pos = $('#'+ this.id +' .sudoku_board').offset(),
        b_dim = { w: $('#'+ this.id +' .sudoku_board').width(),  h: $('#'+ this.id +' .sudoku_board').height() },
        s_dim = { w: $('#'+ this.id +' .statistics').width(),    h: $('#'+ this.id +' .statistics').height()   };
    
    var screen_wr = screen.w + s_dim.h + b_pos.top + 10;
  
    if (screen_wr > screen.h) {
        $('#'+ this.id +' .sudoku_board').css('width', (screen.h - b_pos.top - s_dim.h - 14) );
        $('#'+ this.id +' .board_console').css('width', (b_dim.h/2) );
    } else {
        $('#'+ this.id +' .sudoku_board').css('width', '98%' );
        $('#'+ this.id +' .board_console').css('width', '50%' );
    }
    
    var cell_width = $('#'+ this.id +' .sudoku_board .cell:first').width(),
        note_with  = Math.floor(cell_width/2) -1;
  
    $('#'+ this.id +' .sudoku_board .cell').height(cell_width);
    $('#'+ this.id +' .sudoku_board .cell span').css('line-height', cell_width+'px');    
    $('#'+ this.id +' .sudoku_board .cell .note').css({'line-height': note_with+'px' ,'width' : note_with, 'height': note_with});
    
    //adjust the console
    var console_cell_width = $('#'+ this.id +' .board_console .num:first').width();
    $('#'+ this.id +' .board_console .num').css('height', console_cell_width);
    $('#'+ this.id +' .board_console .num').css('line-height', console_cell_width+'px');
    
    //adjust console
    b_dim = { w: $('#'+ this.id +' .sudoku_board').width(),  h: $('#'+ this.id +' .sudoku_board').width() };
    b_pos = $('#'+ this.id +' .sudoku_board').offset();
    c_dim = { w: $('#'+ this.id +' .board_console').width(), h: $('#'+ this.id +' .board_console').height() };
    
    var c_pos_new = { left : ( b_dim.w/2 - c_dim.w/2 + b_pos.left ), top  : ( b_dim.h/2 - c_dim.h/2 + b_pos.top ) };    
    $('#'+ this.id +' .board_console').css({'left': c_pos_new.left, 'top': c_pos_new.top});
    
    //adjust the gameover container
    var gameover_pos_new = { left : ( screen.w/20 ), top  : ( screen.w/20 + b_pos.top ) };    
    
    $('#'+ this.id +' .gameover').css({'left': gameover_pos_new.left, 'top': gameover_pos_new.top});    
    
    console.log('screen', screen);    
    console.timeEnd("resizeWindow");
};

/**
Show console
*/
Sudoku.prototype.showConsole = function(cell) {
  $('#'+ this.id +' .board_console_container').show();
  
  var 
    t = this,
    oldNotes = $(this.cell).find('.note');
  
  //init
  $('#'+ t.id +' .board_console .num').removeClass('selected');
    
  //mark buttons
  if(t.markNotes) {
    //select markNote button  
    $('#'+ t.id +' .board_console .num.note').addClass('selected');
  
    //select buttons
    $.each(oldNotes, function() {
      var noteNum = $(this).text();
      $('#'+ t.id +' .board_console .num:contains('+ noteNum +')').addClass('selected');
    });  
  }
  
  return this;
};

/**
Hide console
*/
Sudoku.prototype.hideConsole = function(cell) {
  $('#'+ this.id +' .board_console_container').hide();
  return this;
};

/**
Select cell and prepare it for input from sudoku board console
*/
Sudoku.prototype.cellSelect = function(cell){    
    this.cell = cell;
    
    var value = $(cell).text() | 0,
        position       = { x: $(cell).attr('x'), y: $(cell).attr('y') } ,
        group_position = { x: Math.floor((position.x -1)/3), y: Math.floor((position.y-1)/3) },
        horizontal_cells = $('#'+ this.id +' .sudoku_board .cell[x="'+ position.x +'"]'),
        vertical_cells   = $('#'+ this.id +' .sudoku_board .cell[y="'+ position.y +'"]'),
        group_cells      = $('#'+ this.id +' .sudoku_board .cell[gr="'+ group_position.x +''+ group_position.y +'"]'),
        same_value_cells = $('#'+ this.id +' .sudoku_board .cell span:contains('+value+')');
    
    //remove all other selections
    $('#'+ this.id +' .sudoku_board .cell').removeClass('selected current group');
    $('#'+ this.id +' .sudoku_board .cell span').removeClass('samevalue');
    //select current cell
    $(cell).addClass('selected current');
    
    //highlight select cells
    if (this.highlight > 0) {        
        horizontal_cells.addClass('selected');
        vertical_cells.addClass('selected');
        group_cells.addClass('selected group');
        same_value_cells.not( $(cell).find('span') ).addClass('samevalue');
    }
    
    if ($( this.cell ).hasClass('fix')) {
        $('#'+ this.id +' .board_console .num').addClass('no');
    } else {
        $('#'+ this.id +' .board_console .num').removeClass('no');
        
        this.showConsole();
        this.resizeWindow();
    }    
};

/**
Add value from sudoku console to selected board cell
*/
Sudoku.prototype.addValue = function(value) {
    console.log('prepare for addValue', value);
    
    var    
        position       = { x: $(this.cell).attr('x'), y: $(this.cell).attr('y') },        
        group_position = { x: Math.floor((position.x -1)/3), y: Math.floor((position.y-1)/3) },
        
        horizontal_cells = '#'+ this.id +' .sudoku_board .cell[x="'+ position.x +'"]',
        vertical_cells   = '#'+ this.id +' .sudoku_board .cell[y="'+ position.y +'"]',
        group_cells      = '#'+ this.id +' .sudoku_board .cell[gr="'+ group_position.x +''+ group_position.y +'"]',
          
        horizontal_cells_exists = $(horizontal_cells + ' span:contains('+ value +')'),
        vertical_cells_exists   = $(vertical_cells + ' span:contains('+ value +')'),
        group_cells_exists      = $(group_cells + ' span:contains('+ value +')'),
        
        horizontal_notes = horizontal_cells + ' .note:contains('+ value +')',
        vertical_notes   = vertical_cells + ' .note:contains('+ value +')',
        group_notes      = group_cells + ' .note:contains('+ value +')',
          
        old_value = parseInt($( this.cell ).not('.notvalid').text()) || 0;
      
  
    if ($( this.cell ).hasClass('fix')) {
        return;
    }        
  
    //delete value or write it in cell
    $( this.cell ).find('span').text( (value === 0) ? '' : value );
        
    if ( this.cell !== null && ( horizontal_cells_exists.length || vertical_cells_exists.length || group_cells_exists.length ) ) {
        if (old_value !== value) {
            $( this.cell ).addClass('notvalid');            
        } else {            
            $(this.cell).find('span').text('');            
        }
    } else {
        //add value
        $(this.cell).removeClass('notvalid');        
        console.log('Value added ', value); 
      
        //remove all notes from current cell,  line column and group
        $(horizontal_notes).remove();
        $(vertical_notes).remove();
        $(group_notes).remove();      
    }
    
    //recalculate completed cells
    this.cellsComplete = $('#'+ this.id +' .sudoku_board .cell:not(.notvalid) span:not(:empty)').length;
    console.log('is game over? ', this.cellsComplete, this.cellsNr, (this.cellsComplete === this.cellsNr) );
    //game over
    if (this.cellsComplete === this.cellsNr) {
        this.gameOver();
    }
      
    $('#'+ this.id +' .statistics .cells_complete').text(''+this.cellsComplete+'/'+this.cellsNr);  
    
    return this;
};


/**
Add note from sudoku console to selected board cell
*/
Sudoku.prototype.addNote = function(value) {
  console.log('addNote', value);
 
  var 
    t = this,
    oldNotes = $(t.cell).find('.note'),
    note_width = Math.floor($(t.cell).width() / 2);
  
  //add note to cell
  if (oldNotes.length < 4) {
    $('<div></div>')
        .addClass('note')
        .css({'line-height' : note_width+'px', 'height': note_width -1, 'width': note_width -1})
        .text(value)
        .appendTo( this.cell );    
  }
  
  return this;
};

/**
Remove note from sudoku console to selected board cell
*/
Sudoku.prototype.removeNote = function(value) {
  if (value === 0) {    
      $(this.cell).find('.note').remove();
  } else {    
      $(this.cell).find('.note:contains('+value+')').remove();        
  }
  
  return this;
};

/**
End game routine
*/
Sudoku.prototype.gameOver = function(){
    console.log('GAME OVER!');  
    this.status = this.END;   
  
    $('#'+ this.id +' .gameover_container').show();
};

/**
Run a new sudoku game
*/
Sudoku.prototype.run = function(){
    this.status = this.RUNNING;
  
    var t = this;
    this.drawBoard();
    
    //click on board cell
    $('#'+ this.id +' .sudoku_board .cell').on('click', function(e){
        t.cellSelect(this);
    });
    
    //click on console num
    $('#'+ this.id +' .board_console .num').on('click', function(e){
        var 
            value          = $.isNumeric($(this).text()) ? parseInt($(this).text()) : 0,
            clickMarkNotes = $(this).hasClass('note'),
            clickRemove = $(this).hasClass('remove'),
            numSelected    = $(this).hasClass('selected');
                
        if (clickMarkNotes) {
            console.log('clickMarkNotes');
            t.markNotes = !t.markNotes;
            
            if(t.markNotes) { 
                $(this).addClass('selected'); 
            } else { 
                $(this).removeClass('selected');
                t.removeNote(0).showConsole();
            }
        
        } else {
            if (t.markNotes) {
                if (!numSelected) {
                    if (!value) {
                        t.removeNote(0).hideConsole();
                    } else {
                        t.addValue(0).addNote(value).hideConsole();
                    }
                } else {
                    t.removeNote(value).hideConsole();
                }
            } else {
                t.removeNote(0).addValue(value).hideConsole();
            }
        }        
    });
    
    //click outer console
    $('#'+ this.id +' .board_console_container').on('click', function(e){        
        if ( $(e.target).is('.board_console_container') ) {
            $(this).hide();
        }                
    });
    
    $( window ).resize(function() {
        t.resizeWindow();
    });
};

//main
$(function() {
    console.time("loading time");    
    
    //init        
    $('head').append('<meta name="viewport" content="initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,width=device-width,height=device-height,target-densitydpi=device-dpi,user-scalable=yes" />');
    
    //game  
    var game = new Sudoku({ 
                    id: 'sudoku_container',                    
                    fixCellsNr: 30,
                    highlight : 1,
                    displayTitle : 1,
                    //displaySolution: 1,
                    //displaySolutionOnly: 1,
               });
    
    game.run();
  
    $('#sidebar-toggle').on('click', function(e){
      $('#sudoku_menu').toggleClass("open-sidebar");
    });
  
     //restart game
    $('#'+ game.id +' .restart').on('click', function(){
        game.init().run();
    });
  
    $('#sudoku_menu .restart').on('click', function(){
        game.init().run();
        $('#sudoku_menu').removeClass('open-sidebar');
    });
    
    console.timeEnd("loading time");
});

YouTube Video

And this can be continued for as many iterations as one likes, shuffling random rows and columns from a random group, resulting in a pseudo-random puzzle. I am still waiting for the day when I solve a puzzle and the result is the first puzzle above: not sure I would even notice until it is close to being solved.

Don’t forget to share this post!

READ MORE


Deepika

Hey, I'm Deepika, Experienced in Mobile app Development (Flutter, Android and iOS) and professional blogger. Technically sound Post graduated M.Tech in Computer Science and Engineering. I Love to gain every type of knowledge that's why i have done many courses in different fields like engineering and technology. Skilled in Flutter,( Dart ), Java, HTML, CSS, PHP, Python, SQL, C, C++,Firebase,MySQL,SQLite,JavaScript, Networking, Ethical Hacking.

0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *