1var speedOfSolve = 500;
2
3var sudokuBoard = generateEmptyBoard();
4
5function generateEmptyBoard() {
6 return [
7 [[], [], [], [], [], [], [], [], []],
8 [[], [], [], [], [], [], [], [], []],
9 [[], [], [], [], [], [], [], [], []],
10 [[], [], [], [], [], [], [], [], []],
11 [[], [], [], [], [], [], [], [], []],
12 [[], [], [], [], [], [], [], [], []],
13 [[], [], [], [], [], [], [], [], []],
14 [[], [], [], [], [], [], [], [], []],
15 [[], [], [], [], [], [], [], [], []],
16 ];
17}
18
19function getCoordsOfBoxesInSameSubBox(x, y) {
20 let subBoxX = Math.floor(x / 3);
21 let subBoxY = Math.floor(y / 3);
22 let coords = [];
23 for (let subBoxBoxX = 0; subBoxBoxX < 3; subBoxBoxX++) {
24 for (let subBoxBoxY = 0; subBoxBoxY < 3; subBoxBoxY++) {
25 let globalX = subBoxBoxX + subBoxX * 3;
26 let globalY = subBoxBoxY + subBoxY * 3;
27 if (!(globalX === x && globalY === y)) {
28 coords.push({ x: globalX, y: globalY });
29 }
30 }
31 }
32 return coords;
33}
34
35function getCoordsOfBoxesInSameXandY(x, y) {
36 let coords = [];
37 for (let boxX = 0; boxX < 9; boxX++) {
38 if (!(boxX === x)) {
39 coords.push({ x: boxX, y: y });
40 }
41 }
42 for (let boxY = 0; boxY < 9; boxY++) {
43 if (!(boxY === y)) {
44 coords.push({ x: x, y: boxY });
45 }
46 }
47 return coords;
48}
49
50function getPossibleNumbers(x, y, sudokuBoard) {
51 let possibleNumbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
52 let coordsToCheck = getCoordsOfBoxesInSameSubBox(x, y).concat(
53 getCoordsOfBoxesInSameXandY(x, y)
54 );
55 for (let coordIndex in coordsToCheck) {
56 let coord = coordsToCheck[coordIndex];
57 let boxData = sudokuBoard[coord.x][coord.y];
58 if (boxData.length === 1) {
59 var index = possibleNumbers.indexOf(boxData[0]);
60 if (index !== -1) {
61 possibleNumbers.splice(index, 1);
62 }
63 }
64 }
65 return possibleNumbers;
66}
67
68function iterativelySolveSudokuBoard(sudokuBoard) {
69 let newSudokuBoard = sudokuBoard;
70 for (let x in sudokuBoard) {
71 let sudokuBoardRow = sudokuBoard[x];
72 for (let y in sudokuBoard) {
73 let sudokuBox = sudokuBoardRow[y];
74 if (!(sudokuBox.length === 1)) {
75 newSudokuBoard[x][y] = getPossibleNumbers(x, y, sudokuBoard);
76 }
77 }
78 }
79 return newSudokuBoard;
80}
81
82function initDisplay() {
83 let sudokuBoardElement = document.getElementById("sudoku-board");
84 sudokuBoardElement.innerHTML = "";
85 for (let boxX = 0; boxX < 9; boxX++) {
86 let sudokuBoardRow = document.createElement("div");
87 sudokuBoardRow.className = "sudoku-board-row";
88 for (let boxY = 0; boxY < 9; boxY++) {
89 let sudokuBoardBox = document.createElement("div");
90 sudokuBoardBox.className = "sudoku-board-box";
91 sudokuBoardBox.id = "sudoku-board-box-" + boxX + "-" + boxY;
92 sudokuBoardBox.innerHTML = `<input type="text" class="sudoku-board-box-input" id="${
93 "sudoku-board-box-input-" + boxX + "-" + boxY
94 }">`;
95 sudokuBoardRow.appendChild(sudokuBoardBox);
96 }
97 sudokuBoardElement.appendChild(sudokuBoardRow);
98 }
99}
100
101function updateDisplay(sudokuBoard) {
102 for (let boxX = 0; boxX < 9; boxX++) {
103 for (let boxY = 0; boxY < 9; boxY++) {
104 let currentSudokuBoardBox = document.getElementById(
105 "sudoku-board-box-" + boxX + "-" + boxY
106 );
107 let currentBoxData = sudokuBoard[boxX][boxY];
108 if (currentBoxData.length === 1) {
109 currentSudokuBoardBox.className =
110 "sudoku-board-box sudoku-board-box-solved";
111 currentSudokuBoardBox.innerHTML = currentBoxData[0];
112 } else if (currentBoxData.length === 0) {
113 currentSudokuBoardBox.className =
114 "sudoku-board-box sudoku-board-box-empty";
115 } else {
116 currentSudokuBoardBox.className =
117 "sudoku-board-box sudoku-board-box-unsolved";
118 currentSudokuBoardBox.innerHTML = currentBoxData[0];
119 for (let boxDataIndex in currentBoxData.slice(1)) {
120 currentSudokuBoardBox.innerHTML +=
121 ", " + currentBoxData.slice(1)[boxDataIndex];
122 }
123 }
124 }
125 }
126}
127
128function runIteration() {
129 if (shouldBeSolving) {
130 sudokuBoard = iterativelySolveSudokuBoard(sudokuBoard);
131 updateDisplay(sudokuBoard);
132 let solved = true;
133 for (let x in sudokuBoard) {
134 let sudokuBoardRow = sudokuBoard[x];
135 for (let y in sudokuBoard) {
136 let sudokuBox = sudokuBoardRow[y];
137 if (!(sudokuBox.length === 1)) {
138 solved = false;
139 }
140 }
141 }
142 if (!solved) {
143 setTimeout(runIteration, speedOfSolve);
144 } else {
145 shouldBeSolving = false;
146 }
147 }
148}
149
150function loadUserInput() {
151 for (let boxX = 0; boxX < 9; boxX++) {
152 for (let boxY = 0; boxY < 9; boxY++) {
153 let currentSudokuBoardBoxInput = document.getElementById(
154 "sudoku-board-box-input-" + boxX + "-" + boxY
155 );
156 if (currentSudokuBoardBoxInput.value == "") {
157 sudokuBoard[boxX][boxY] = [];
158 } else {
159 sudokuBoard[boxX][boxY] = [parseInt(currentSudokuBoardBoxInput.value)];
160 }
161 }
162 }
163}
164
165let shouldBeSolving = false;
166function runSolver() {
167 shouldBeSolving = true;
168 loadUserInput();
169 runIteration();
170}
171
172function haltSolverAndReset() {
173 shouldBeSolving = false;
174 sudokuBoard = generateEmptyBoard();
175 console.log(sudokuBoard);
176 updateDisplay(sudokuBoard);
177 setTimeout(initDisplay, 500);
178}
179
180initDisplay();