javascriptʵÏÖÊý¶À½â·¨

¡¡¡¡ÉúÉú°Ñд¹ýµÄjava°æ¸Ä³Éjavascript°æ£¬µÚÒ»´Îд£¬ºÜ²»×¨Òµ£¬¼ûÁ¡£°¦£¬ÎÒÊÇÓжàÏС£

¡¡¡¡

¸´ÖÆ´úÂë ´úÂëÈçÏÂ:

¡¡¡¡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();

¡¡¡¡ÒÔÉϾÍÊǹØÓÚʹÓÃjavascriptʵÏÖÊý¶À½â·¨µÄÈ«²¿´úÂëÁË£¬Ï£Íû´ó¼ÒÄܹ»Ï²»¶¡£