const col = {}; //缓存列
const box = {}; //缓存块
//以上三个缓存用来排除,并且持续维护,每个里面有至多9个栈
//初始化一个拷贝二维数组
const cb = new Array(N).fill(0).map(© => new Array(N).fill(D));
//初始化字符串1-9的枚举
const emnu = new Array(N).fill(0).map((c, i) => i + 1 + “”);
//封装一个根据坐标转化成第k块的函数
const getk = (i, j) => (((i / 3) | 0) * 3 + j / 3) | 0;
//fx函数用来获取拷贝二维数组或者单元格的排除数组
const fx = (i, j) => {
//如果本来九宫格有数字就用它,没有则说明是需要填的
if (cb[i][j][0] !== D) return cb[i][j];
//过滤得到单元格可能出现的数字
return emnu.filter((item) => filter(i, j, item));
};
//用于判断一个数字是否在缓存中,不在就返回true
const filter = (i, j, item) => {
//k就是计算得到的第k块
let k = getk(i, j);
if ((row[i] || []).indexOf(item) > -1) return false;
if ((col[j] || []).indexOf(item) > -1) return false;
if ((box[k] || []).indexOf(item) > -1) return false;
return true;
}
//添加一个数字到缓存
const add = (i, j, cur) => {
let k = getk(i, j);
row[i] ? row[i].push(cur) : (row[i] = [cur]);
col[j] ? col[j].push(cur) : (col[j] = [cur]);
box[k] ? box[k].push(cur) : (box[k] = [cur]);
};
//如果这个数字不能用,不好意思只能弹出,不能影响接下来的判断
const pop = (i, j) => {
let k = getk(i, j);
row[i].pop();
col[j].pop();
box[k].pop();
};
//以上都是函数和初始化
//下面开始才是运行流程
//先便利原二维数组,得到缓存row、col、box、cb,如果是’.‘就给个[’.']
let start = 0; //start优化开始跳过最开始的一串原始数字
let first = true; //用来判断是否经历过空单元格
for (let i = 0; i < N; i++) {
for (let j = 0; j < N; j++) {
let cur = board[i][j];
if (first) start = i * N + j;
if (cur !== D) {
if (!filter(i, j, cur)) return(‘不是有效数独’)
add(i, j, cur)
cb[i][j] = [cur];
} else {
first = false;
cb[i][j] = [D];
}
}
}
//深度递归函数,以index序号0-80为递归依据
//每个单元格根据fx函数拿到nums数组
const dfs = (index) => {
//根据序号拿到坐标值
let [x, y] = [(index / N) | 0, index % N | 0];
const nums = fx(x, y);
//nums返回的数组可能长度为0、1、或者多个,要么来源于初始,要么来源于cb
//如果是0说明已经没有选择了(题目中表示一定有唯一解,所以可以忽略)
//如果是1说明只能选择这个
//进入循环
for (let i = 0; i < nums.length; i++) {
//将这个数字加入缓存排除
add(x, y, nums[i]);
board[x][y] = nums[i];
//如果只有一个数字,到了终点,说明结束了
if (index === N * N - 1 && nums.length === 1) {
success = true;
return true;
}
//如果之后的递归都返回true
if (dfs(index + 1)) return true;
//如果不满足递归正确的条件,则说明现在为止的数字都是不对的
//恢复board的区域并弹出缓存
board[x][y] = cb[x][y][0];
pop(x, y);
}
return false;
};
dfs(start);
if (!success) return ‘对不起,解不出来~~~’
return board;
};
const ax=[
[“5”, “.”, “.”, “.”, “7”, “.”, “.”, “.”, “.”],
[“6”, “.”, “.”, “1”, “9”, “5”, “.”, “.”, “.”],
[“.”, “9”, “8”, “.”, “.”, “.”, “.”, “6”, “.”],
[“8”, “.”, “.”, “.”, “6”, “.”, “.”, “.”, “3”],
[“4”, “.”, “.”, “8”, “.”, “3”, “.”, “.”, “1”],
[“7”, “.”, “.”, “.”, “2”, “.”, “.”, “.”, “6”],
[“.”, “6”, “.”, “.”, “.”, “.”, “2”, “8”, “.”],
[“.”, “.”, “.”, “4”, “1”, “9”, “.”, “.”, “5”],