【困难】算法nodeJs:Sudoku

109 阅读2分钟

数独(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(" "));
    }
})();

代码解释:

  1. isValid(sudoku, row, col, num) :检查在给定位置 (row, col) 放置 num 是否符合数独规则,具体包括:检查行、列、小方格。
  2. solve(sudoku) :这是回溯算法的核心函数,它遍历每个空格并尝试填充数字。遇到冲突时回溯并尝试其他可能的数字。
  3. 最终,若能够填充完整个数独,输出结果。