javascript實(shí)現(xiàn)數(shù)獨(dú)解法
生生把寫(xiě)過(guò)的java版改成javascript版,第一次寫(xiě),很不專(zhuān)業(yè),見(jiàn)諒。唉,我是有多閑。
var Sudoku = {
init: function (str) {
this.blank = [];
this.fixed = [];
this.cell = [];
this.trials=[];
for (i = 0; i < 81; i++) {
var chr = str.charCodeAt(i);
if (chr == 48) {
this.cell[i] = 511;
this.blank.push(i);
} else {
this.cell[i] = 1 << chr - 49;
this.fixed.push(i);
}
}
},
showBoard: function () {
var board = "";
for (var i = 0; i < 81; i++) {
if (i % 9 == 0) {
board = board.concat("\n");
}
board = board.concat("[");
for (var j = 0; j < 9; j++) {
if ((this.cell[i] >> j & 1) == 1) {
board = board.concat(String.fromCharCode(j + 49));
}
}
board = board.concat("]");
}
return board;
},
check: function () {
var checkpoint = [0, 12, 24, 28, 40, 52, 56, 68, 80];
for (var i in checkpoint) {
var r, b, c;
r = b = c = this.cell[checkpoint[i]];
for (j = 0; j < 8; j++) {
c ^= this.cell[this.getX(checkpoint[i])[j]];
b ^= this.cell[this.getX(checkpoint[i])[8 + j]];
r ^= this.cell[this.getX(checkpoint[i])[16 + j]];
}
if ((r & b & c) != 0x1FF) {
return false;
}
}
return true;
},
bitCount: function (i) {
var n = 0;
for (var j = 0; j < 9; j++) {
if ((i >> j & 1) == 1)
n++;
}
return n;
},
numberOfTrailingZeros: function(i){
var n = 0;
for (var j = 0; j < 9; j++) {
if ((i >> j & 1) ==0)
n++;
else{
break;
}
}
return n;
},
updateCandidates: function () {
for (var i in this.fixed) {
var opt = 0x1FF ^ this.cell[this.fixed[i]];
for (var j = 0; j < 24; j++) {
this.cell[this.getX(this.fixed[i])[j]] &= opt;
//!notice
if (this.cell[this.getX(this.fixed[i])[j]] == 0) {
//console.log("Error-0 candidate:"+x[this.fixed[i]][j]);
return false;
}
}
}
return true;
},
seekUniqueCandidate: function () {
for (var bidx in this.blank) {
var row = 0, col = 0, box = 0;
for (i = 0; i < 8; i++) {
row |= this.cell[this.getX(this.blank[bidx])[i]];
box |= this.cell[this.getX(this.blank[bidx])[8 + i]];
col |= this.cell[this.getX(this.blank[bidx])[16 + i]];
}
if (this.bitCount(this.cell[this.blank[bidx]] & ~row) == 1) {
this.cell[this.blank[bidx]] &= ~row;
continue;
}
if (this.bitCount(this.cell[this.blank[bidx]] & ~col) == 1) {
this.cell[this.blank[bidx]] &= ~col;
continue;
}
if (this.bitCount(this.cell[this.blank[bidx]] & ~box) == 1) {
this.cell[this.blank[bidx]] &= ~box;
}
}
},
seekFilledable: function () {
this.fixed = [];
var _del=[];
for (var i in this.blank) {
if (this.bitCount(this.cell[this.blank[i]]) == 1) {
this.fixed.push(this.blank[i]);
//console.log("fixed:"+this.blank[i]+"=>"+this.cell[this.blank[i]]);
//this.blank.splice(i, 1);//to delete it in the loop would cause bug
_del.push(i);
}
}
while(_del.length>0){
this.blank.splice(_del.pop(), 1);
}
},
seekMutexCell: function () {
var two = [];
for (var n in this.blank) {
if (this.bitCount(this.cell[this.blank[n]]) == 2) {
two.push(this.blank[n]);
}
}
for (var i = 0; i < two.length; i++) {
for (var j = i + 1; j < two.length; j++) {
if (this.cell[two[i]] == this.cell[two[j]]) {
var opt = ~this.cell[two[i]];
if (parseInt(two[i] / 9) ==parseInt(two[j] / 9)) {
for (n = 0; n < 8; n++) {
this.cell[this.getX(two[i])[n]] &= opt;
}
}
if ((two[i] - two[j]) % 9 == 0) {
for (n = 8; n < 16; n++) {
this.cell[this.getX(two[i])[n]] &= opt;
}
}
if ((parseInt(two[i] / 27) * 3 + parseInt(two[i] % 9 / 3)) == (parseInt(two[j] / 27) * 3 + parseInt(two[j] % 9 / 3))) {
for (n = 16; n < 24; n++) {
this.cell[this.getX(two[i])[n]] &= opt;
}
}
this.cell[two[j]] = ~opt;
}
}
}
},
basicSolve: function () {
do {
if (!this.updateCandidates(this.fixed)) {
this.backForward();
}
this.seekUniqueCandidate();
this.seekMutexCell();
this.seekFilledable();
} while (this.fixed.length != 0);
return this.blank.length == 0;
},
setTrialCell: function() {
for (var i in this.blank) {
if (this.bitCount(this.cell[this.blank[i]]) == 2) {
var trialValue = 1 << this.numberOfTrailingZeros(this.cell[this.blank[i]]);
var waitingValue = this.cell[this.blank[i]] ^ trialValue;
//console.log("try:[" + this.blank[i] + "]->" + (this.numberOfTrailingZeros(trialValue) + 1) + "#" + (this.numberOfTrailingZeros(waitingValue) + 1));
this.cell[this.blank[i]] = trialValue;
this.trials.push(this.createTrialPoint(this.blank[i], waitingValue, this.cell));
return true;
}
}
return false;
},
backForward: function() {
if (this.trials.length==0) {
console.log("Maybe no solution!");
return;
}
var back = this.trials.pop();
this.reset(back.data);
this.cell[back.idx] = back.val;
this.fixed.push(back.idx);
//console.log("back:[" + back.idx + "]->" + (this.numberOfTrailingZeros(back.val) + 1));
},
reset: function(data) {
this.blank=[];
this.fixed=[];
this.cell=data.concat();
for (var i = 0; i < 81; i++) {
if (this.bitCount(this.cell[i]) != 1) {
this.blank.push(i);
} else {
this.fixed.push(i);
}
}
},
trialSolve: function() {
while (this.blank.length!=0) {
if (this.setTrialCell()) {
this.basicSolve();
} else {
if (this.trials.length==0) {
//console.log("Can't go backforward! Maybe no solution!");
break;
} else {
this.backForward();
this.basicSolve();
}
}
}
},
play: function() {
console.log(this.showBoard());
var start = new Date().getMilliseconds();
if (!this.basicSolve()) {
this.trialSolve();
}
var end = new Date().getMilliseconds();
console.log(this.showBoard());
if (this.check()) {
console.log("[" + (end - start) + "ms OK!]");
} else {
console.log("[" + (end - start) + "ms, cannot solve it?");
}
//return this.showBoard();
},
getX:function(idx){
var neighbors=new Array(24);
var box=new Array(0,1,2,9,10,11,18,19,20);
var r=parseInt(idx/9);
var c=idx%9;
var xs=parseInt(idx/27)*27+parseInt(idx%9/3)*3;
var i=0;
for(var n=0;n<9;n++){
if(n==c)continue;
neighbors[i++]=r*9+n;
}
for(var n=0;n<9;n++){
if(n==r)continue;
neighbors[i++]=c+n*9;
}
for(var n=0;n<9;n++){
var t=xs+box[n];
if(t==idx)continue;
neighbors[i++]=t;
}
return neighbors;
},
createTrialPoint:function(idx, val, board) {
var tp = {};
tp.idx = idx;
tp.val = val;
tp.data = board.concat();
return tp;
}
};
//Sudoku.init("000000500000008300600100000080093000000000020700000000058000000000200017090000060");
//Sudoku.init("530070000600195000098000060800060003400803001700020006060000280000419005000080079");
Sudoku.init("800000000003600000070090200050007000000045700000100030001000068008500010090000400");
Sudoku.play();
以上就是關(guān)于使用javascript實(shí)現(xiàn)數(shù)獨(dú)解法的全部代碼了,希望大家能夠喜歡。
相關(guān)文章
JS實(shí)現(xiàn)的新聞列表自動(dòng)滾動(dòng)效果示例
這篇文章主要介紹了JS實(shí)現(xiàn)的新聞列表自動(dòng)滾動(dòng)效果,涉及javascript基于時(shí)間函數(shù)的頁(yè)面元素屬性動(dòng)態(tài)變換相關(guān)操作技巧,需要的朋友可以參考下2019-01-01javascript trim 去空格函數(shù)實(shí)現(xiàn)代碼
去除字符串左右兩端的空格,在vbscript里面可以輕松地使用 trim、ltrim 或 rtrim,但在js中卻沒(méi)有這3個(gè)內(nèi)置方法,需要手工編寫(xiě)。下面的實(shí)現(xiàn)方法是用到了正則表達(dá)式,效率不錯(cuò),并把這三個(gè)方法加入String對(duì)象的內(nèi)置方法中去。2008-10-10前端date.locale?is?not?a?function錯(cuò)誤的簡(jiǎn)單解決辦法
這篇文章主要給大家介紹了關(guān)于前端date.locale?is?not?a?function錯(cuò)誤的簡(jiǎn)單解決辦法,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09Area 區(qū)域?qū)崿F(xiàn)post提交數(shù)據(jù)的js寫(xiě)法
這篇文章主要介紹了在Area區(qū)域的里 實(shí)現(xiàn)post 提交數(shù)據(jù) 的js寫(xiě)法,需要的朋友可以參考下2014-04-04js實(shí)現(xiàn)前端分頁(yè)頁(yè)碼管理
本文主要介紹了js實(shí)現(xiàn)前端分頁(yè)頁(yè)碼管理的具體方法。具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-01-01JavaScript使用prototype原型實(shí)現(xiàn)的封裝繼承多態(tài)示例
這篇文章主要介紹了JavaScript使用prototype原型實(shí)現(xiàn)的封裝繼承多態(tài),涉及javascript prototype與面向?qū)ο蟪绦蛟O(shè)計(jì)相關(guān)操作技巧,需要的朋友可以參考下2018-08-08JavaScript+HTML5 canvas實(shí)現(xiàn)放大鏡效果完整示例
這篇文章主要介紹了JavaScript+HTML5 canvas實(shí)現(xiàn)放大鏡效果,結(jié)合完整實(shí)例形式分析了javascript+HTML5 canvas針對(duì)圖片元素的獲取、響應(yīng)鼠標(biāo)事件變換元素屬性相關(guān)操作技巧,需要的朋友可以參考下2019-05-05javascript textContent與innerText的異同分析
因?yàn)榘l(fā)現(xiàn)網(wǎng)絡(luò)上很少有這方面的內(nèi)容,因此就把自己私有blog上的這篇文章搬出來(lái)到Boluor的公開(kāi)blog,方便其它人查閱。2010-10-10ES6擴(kuò)展運(yùn)算符的理解與使用場(chǎng)景
擴(kuò)展運(yùn)算符( spread )是三個(gè)點(diǎn)(...),它好比 rest 參數(shù)的逆運(yùn)算,將一個(gè)數(shù)組轉(zhuǎn)為用逗號(hào)分隔的參數(shù)序列,這篇文章主要給大家介紹了關(guān)于ES6擴(kuò)展運(yùn)算符的理解與使用場(chǎng)景的相關(guān)資料,需要的朋友可以參考下2021-09-09