//clear all the input
function clc() {
for (let i = 0; i < 81; i++) {
document.getElementsByTagName("input")[i].value = "";
document.getElementsByTagName("input")[i].style.color = '#00d3ff';
}
alert("已清理所有单元格");
}
//press "show answer" button and show answer then
function get_answer() {
let bool = check_input();
if (bool) {
let grid = readAPuzzle();
if (!isValidGrid(grid)) {
alert("输入无效,请重试!(可能误输重复数字)");
} else {
if (search(grid)) {
output_ans();
} else {
alert("找不到解决方案!(无解)");
}
}
}
}
//check if the input are valid
function check_input() {
let arr = new Array();
for (let i = 0; i < 81; i++) {
arr[i] = Number(document.getElementsByTagName("input")[i].value);
if (isNaN(arr[i])) {
alert('输入应该是1到9之间的任何数字!');
return false
}
}
if (arr.every(function isZero(x) {
return x == 0
})) {
alert('没有输入!');
return false
}
return true
}
//read a puzzle from the web page
function readAPuzzle() {
let arr = new Array();
for (let i = 0; i < 81; i++) {
arr[i] = Number(document.getElementsByTagName("input")[i].value);
}
let grid = new Array();
for (let i = 0; i < 9; i++) {
grid[i] = new Array();
for (let j = 0; j < 9; j++) {
grid[i][j] = 0;
}
}
for (let i = 0; i < 81; i++) {
grid[Math.floor(i / 9)][i % 9] = arr[i];
}
return grid
}
//Obtain a list of free cells from the puzzle
function getFreeCellList(grid) {
let freeCellList = new Array();
let index = 0
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
if (grid[i][j] == 0) {
freeCellList[index] = new Array(i, j);
index++;
}
}
}
return freeCellList
}
//Check whether grid[i][j] is valid in the grid
function isValid(i, j, grid) {
//Check whether grid[i][j] is valid at the i's row
for (var column = 0; column < 9; column++) {
if ((column != j) && (grid[i][column] == grid[i][j])) {
return false
}
}
//Check whether grid[i][j] is valid at the j's column
for (var row = 0; row < 9; row++) {
if ((row != i) && (grid[row][j] == grid[i][j])) {
return false
}
}
//Check whether grid[i][j] is valid at the 3-by-3 box
for (var row = Math.floor(i / 3) * 3; row < Math.floor(i / 3) * 3 + 3; row++) {
for (var col = Math.floor(j / 3) * 3; col < Math.floor(j / 3) * 3 + 3; col++) {
if ((row != i) && (col != j) && (grid[row][col] == grid[i][j])) {
return false
}
}
}
return true //The current value at grid[i][j] is valid
}
//Check whether the fixed cells are valid in the grid
function isValidGrid(grid) {
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++) {
if ((grid[i][j] < 0) || (grid[i][j] > 9) || ((grid[i][j] != 0) && (!isValid(i, j, grid)))) {
return false
}
}
}
return true
}
//Search for a solution
function search(grid) {
var freeCellList = getFreeCellList(grid);
var numberOfFreeCells = freeCellList.length;
if (numberOfFreeCells == 0) {
return true
}
var k = 0; //Start from the first free cell
while (true) {
var i = freeCellList[k][0];
var j = freeCellList[k][1];
if (grid[i][j] == 0) {
grid[i][j] = 1;
}
if (isValid(i, j, grid)) {
if (k + 1 == numberOfFreeCells) {
//no more free cells
return true //A solution is found
} else {
//Move to the next free cell
k++;
}
} else {
if (grid[i][j] < 9) {
//Fill the free cell with the next possible value
grid[i][j]++;
} else {
//grid[i][j] is 9,backtrack
while (grid[i][j] == 9) {
if (k == 0) {
return false //No possible value
}
grid[i][j] = 0; //Reset to free cell
k--; //Backtrack to the preceding free cell
i = freeCellList[k][0];
j = freeCellList[k][1];
}
//Fill the free cell with the next possible value
//search continues from this free cell at k
grid[i][j]++;
}
}
}
return true //A solution is found
}
//output the answer on the web page
function output_ans() {
var grid = readAPuzzle();
var grid_original = readAPuzzle();
if (search(grid)) {
for (var i = 0; i < 81; i++) {
if (grid[Math.floor(i / 9)][i % 9] != grid_original[Math.floor(i / 9)][i % 9]) {
document.getElementsByTagName("input")[i].value = grid[Math.floor(i / 9)][i % 9];
document.getElementsByTagName("input")[i].style.color = '#2DFF97';
}
}
}
}