# Sudoku Solver - 2018 Number Checking Class Example

## In this example below you will see how to do a Sudoku Solver - 2018 Number Checking Class Example with some HTML / CSS and Javascript

This awesome code was written by thomaskhugo, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
• HTML
• CSS
• JavaScript
``````    <div class="full-page">
<h1>Sudoku Solver</h1>
<div class="squareContainer">
<div id="boardContainer">
</div>
</div>
<!--   <div id="edit-lock-toggle">
<div id="toggle-background"></div>
<div id="edit" class="toggle">edit</div>
<div id="lock" class="toggle">lock</div>
</div>
<div id="solve_button" class="button">solve</div>
<div id="clear_button" class="button">clear</div> -->
</div>
``````
``````
* {
box-sizing: border-box;
}

body {
background-color: #ddd;
}

h1 {
text-align: center;
}

.full-page {
height: 100vh;
width: 100%;
}

.grid_3x3 {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
grid-gap: 4px;
overflow: hidden;
}

.section {
background-color: #999;
grid-gap: 1px;
}

.space {
background-color: #ccc;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
max-width: 100%;
}

.space:focus {
outline: none;
background-color: #bbb;
}

.space:hover {
background-color: #bbb;
}

.squareContainer {
margin: auto;
max-width: 500px;
background-color: #eee;
}

#boardContainer {
width: 100%;
background-color: #eee;
position: relative;
}

#board {
margin: auto;
background-color: #999;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}

#solve_button {
background-color: #ccc;
color: #333;
}

#solve_button:hover {
background-color: #bbb;
}

#clear_button {
background-color: #c55;
color: #eee;
}

#clear_button:hover {
background-color: #d33;
}

.button {
max-width: 500px;
margin: 10px auto;
text-align: center;
font-size: 1.5em;
border: 4px solid #aaa;
}

#edit-lock-toggle {
cursor: pointer;
max-width: 500px;
display: flex;
margin: 10px auto;
color: #333;
font-size: 1.5em;
border: 4px solid #aaa;
overflow: hidden;
position: relative;
}

#toggle-background {
position: absolute;
left: 50%;
top: 0;
background-color: #383;
width: 50%;
height: 100%;
z-index: -1;
transition: 0.3s;
}

#edit-lock-toggle .toggle {
flex: 1 1 auto;
text-align: center;
}

.space[contentEditable=true]:empty {
}

``````
``````
var boardContainer = document.getElementById("boardContainer");

/////////// Global board variable that holds our live board data

var board;

////////// Object with methods that creates and displays the board HTML

var boardMaker = {
createNewBoardObject: function(){
var board = {
section: {},
column: {},
row: {},
space: {},
};

var section = 1;

for (var section_row = 1; section_row < 4; section_row++){
// The row offset will increase the row value for spaces by 3 section each row
var row_offset = (section_row - 1) * 3;
for (var section_column = 1; section_column < 4; section_column++){
// The column offset will increase the column value for spaces by 3 each row
var column_offset = (section_column - 1) * 3;

for (var space_row = 1; space_row < 4; space_row++){
for (var space_column = 1; space_column < 4; space_column++){

var _column = space_column + column_offset;
var _row = space_row + row_offset;
var _id = "s" + section.toString() + _row.toString() + _column.toString();

// define a space
var space = {
section: section,
column: _column,
row: _row,
id: _id,
number: null,
availableNumbers: [1,2,3,4,5,6,7,8,9],
blacklist: [],
};

// add the space to the board.space object
board.space[_id] = space;

// check if the section, row, and column exists in the board and add them if necessary
if (!board.section[space.section]){
board.section[space.section] = [];
}
if (!board.column[space.column]){
board.column[space.column] = [];
}
if (!board.row[space.row]){
board.row[space.row] = [];
}

// add the space ID to the matching section, row, and column
board.section[space.section].push(space.id);
board.column[space.column].push(space.id);
board.row[space.row].push(space.id);

}
}
section += 1;
}
}

return board;
},

makeSectionDiv: function(){
var sectionDiv = document.createElement("div");
return sectionDiv;
},
makeSpaceDiv: function(spaceID){
var spaceDiv = document.createElement("div");
spaceDiv.id = spaceID;
return spaceDiv;
},
displayBoard: function(boardContainerElement, boardData){
var boardMaker = this;
var board = document.createElement("div");
board.id = "board";

for (var i = 1; i < 10; i++){

var sectionDIV = boardMaker.makeSectionDiv();

boardData.section[i].forEach(function(spaceID){
sectionDIV.appendChild(boardMaker.makeSpaceDiv(spaceID));
});

board.appendChild(sectionDIV);
}

boardContainerElement.innerHTML = "";
boardContainerElement.appendChild(board);
},
clearBoard: function(boardContainerElement){
board = this.createNewBoardObject();
this.displayBoard(boardContainerElement, board);
},
}

/////////// Sudoku object with methods that control how our board works and solving the puzzle

var sudoku = {
markSpace: function(boardObj, spaceID, num){
if (/[1-9]/.test(num) && sudoku.numberIsAvailable(boardObj, spaceID, num)) {
boardObj.space[spaceID].number = Number(num);
sudoku.updateAvailableNumbersForAllSpaces(boardObj);
}
if (num === "Backspace") {
boardObj.space[spaceID].number = null;
sudoku.updateAvailableNumbersForAllSpaces(boardObj);
}
},

numberIsAvailable: function(boardObj, spaceID, num){

var availableNumbersArr = boardObj.space[spaceID].availableNumbers;

num = Number(num);

///////// Imperative

for (var i = 0; i < availableNumbersArr.length; i++){
if (availableNumbersArr[i] == num){
return true
}
}

return false

///////// Delcarative

var numIsAvailable = availableNumbersArr.includes(num);

if (numIsAvailable){
return true;
} else {
return false;
}

///////////

return boardObj.space[spaceID].availableNumbers.includes(num);
},

numberIsAvailableInSpaceArray: function(boardObj, spaceArray, num){
return spaceArray.every(function(spaceID){
return boardObj.space[spaceID].number != num;
});
},
updateAvailableNumbersForSpace: function(boardObj, spaceID){

var sectionNum = boardObj.space[spaceID].section;
var rowNum = boardObj.space[spaceID].row;
var columnNum = boardObj.space[spaceID].column;

var sectionArr = boardObj.section[sectionNum];
var rowArr = boardObj.row[rowNum];
var columnArr = boardObj.column[columnNum];

var allNumbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];

var newAvailableNumbers = allNumbers.filter(function(num){
var availableInSection = sudoku.numberIsAvailableInSpaceArray(boardObj, sectionArr, num);
var availableInRow = sudoku.numberIsAvailableInSpaceArray(boardObj, rowArr, num);
var availableInColumn = sudoku.numberIsAvailableInSpaceArray(boardObj, columnArr, num);

return (availableInSection && availableInRow && availableInColumn);
});

boardObj.space[spaceID].availableNumbers = newAvailableNumbers;

},
updateAvailableNumbersForAllSpaces: function(boardObj){

var spaces = boardObj.space;

for (var space in spaces){
sudoku.updateAvailableNumbersForSpace(boardObj, space);
}

},
}

board = boardMaker.createNewBoardObject();
boardMaker.displayBoard(boardContainer, board);

// Buttons // UI // Display

function updateUI(boardObj){
var spaces = Array.from(document.getElementsByClassName("space"));
spaces.forEach(function(space){
space.innerHTML = boardObj.space[space.id].number;
});
}

function unlockBoard(elementArray){
elementArray.forEach(function(element){
element.setAttribute("contenteditable", true);
element.style.backgroundColor = "#ddd";
});
};

unlockBoard(Array.from(document.getElementsByClassName("space")));

// Event Listeners