数独(Sudoku)是一款大众喜爱的数字逻辑游戏。玩家需要根据 9×9 盘面上的已知数字,推算出所有剩余空格的数字,并且满足每一行、每一列、每一个 3×3 粗线宫内的数字均含 1∼9 这九个数字,且不重复。
保证输入的数独是合法的,且存在唯一解。
输入描述:
输入一个 9×9 的不完整数独矩阵,矩阵中的数字为 0∼9 。其中,0 表示该位置的数字尚未填入,1∼9 表示该位置的数字已经填入。
输出描述:
输出一个 9×9 的完整数独矩阵。
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void (async function () {
const sudoku = [];
while ((line = await readline())) {
sudoku.push(line.split(" ").map(Number)); // 将输入转换为数字数组
}
// 检查某个数字是否可以放置在位置 (row, col)
function isValid(sudoku, row, col, num) {
// 检查行
for (let i = 0; i < 9; i++) {
if (sudoku[row][i] === num) return false;
}
// 检查列
for (let i = 0; i < 9; i++) {
if (sudoku[i][col] === num) return false;
}
// 检查小方格
const startRow = Math.floor(row / 3) * 3;
const startCol = Math.floor(col / 3) * 3;
for (let i = startRow; i < startRow + 3; i++) {
for (let j = startCol; j < startCol + 3; j++) {
if (sudoku[i][j] === num) return false;
}
}
return true;
}
// 递归回溯法
function solve(sudoku) {
for (let row = 0; row < 9; row++) {
for (let col = 0; col < 9; col++) {
if (sudoku[row][col] === 0) { // 找到一个空格
for (let num = 1; num <= 9; num++) {
if (isValid(sudoku, row, col, num)) {
sudoku[row][col] = num; // 尝试填入数字
if (solve(sudoku)) {
return true; // 继续递归
}
sudoku[row][col] = 0; // 回溯,重置为空
}
}
return false; // 如果没有数字符合要求,返回 false
}
}
}
return true; // 所有空格都已填充完
}
// 解决数独
solve(sudoku);
// 输出结果
for (let i = 0; i < 9; i++) {
console.log(sudoku[i].join(" "));
}
})();
代码解释:
isValid(sudoku, row, col, num):检查在给定位置(row, col)放置num是否符合数独规则,具体包括:检查行、列、小方格。solve(sudoku):这是回溯算法的核心函数,它遍历每个空格并尝试填充数字。遇到冲突时回溯并尝试其他可能的数字。- 最终,若能够填充完整个数独,输出结果。