说明
用数字1-9填满一个99的矩阵,要求每行和每列有这9个数字构成,矩阵还包含方块(33)的矩阵,他们同样需要分别用这9个数字填满。谜题在开始的时候给出已填了部分的矩阵,如图所示
例子
使用下面代码进行测试
const sudokuGrid = [
[5, 3, 0, 0, 7, 0, 0, 0, 0],
[6, 0, 0, 1, 9, 5, 0, 0, 0],
[0, 9, 8, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 2, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 9],
];
思路
- 在空白(0)的位置使用尝试填入1-9中的每个数字
- 如果当前填入的数字符合条件,则尝试填写下一个位置(递归)。如果有一数字填在了不正确的位置,则会将此位置标记为空(0)
- 如果当前填入数字不符合条件,尝试下一个数字
代码
function sudokuSolver(matrix) {
if (solveSudoku(matrix)) {
return matrix;
}
return "数独错误";
}
function solveSudoku(matrix) {
// 从[0][0]开始,如果位置为空(0)则尝试在此位置填入数字
let row = 0;
let col = 0;
let isBlank = false;
for (row = 0; row < matrix.length; row++) {
for (col = 0; col < matrix.length; col++) {
if (matrix[row][col] === 0) {
isBlank = true;
break;
}
}
if (isBlank) {
break;
}
}
if (!isBlank) {
return true;
}
// 当前位置为空[row][col],尝试填入1-9的数字
for (let num = 1; num <= 9; num++) {
// 判断当前数字是否安全
if (isSafe(row, col, matrix, num)) {
// 当前数字安全,则递归调用此方法,看下一个位置是否能填入安全的数字
matrix[row][col] = num;
if (solveSudoku(matrix)) {
return true;
}
// 如果下一个位置不能填入安全的数字,则证明当前数字有误,重置当前的位置为空(0)
matrix[row][col] = 0;
}
}
// 这时没有数字是安全的
return false;
}
// 判断当前数字是否安全
function isSafe(row, col, matrix, num) {
if (
!usedInRow(row, matrix, num) &&
!usedInCol(col, matrix, num) &&
!usedInBox(row, col, matrix, num)
) {
return true;
}
return false;
}
// 使用的数字是否已经在当前行了
function usedInRow(row, matrix, num) {
return matrix[row].includes(num);
}
// 使用的数字是否已经在当前列了
function usedInCol(col, matrix, num) {
return matrix.map((row) => row[col]).includes(num);
}
// 使用数字收已经在当前box(3*3)
function usedInBox(row, col, matrix, num) {
const rowIndex = Math.floor(row / 3);
const colIndex = Math.floor(col / 3);
return matrix
.slice(rowIndex*3, 3)
.map((row) => row.slice(colIndex*3, 3))
.flat()
.includes(num);
}
const sudokuGrid = [ [5, 3, 0, 0, 7, 0, 0, 0, 0],
[6, 0, 0, 1, 9, 5, 0, 0, 0],
[0, 9, 8, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 2, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 9],
];
console.log(sudokuSolver(sudokuGrid));