javascript实现数独解法


Posted in Javascript onMarch 14, 2015

生生把写过的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实现数独解法的全部代码了,希望大家能够喜欢。

Javascript 相关文章推荐
XHTML下,JS浮动代码失效的问题
Nov 12 Javascript
javascript Event对象详解及使用示例
Nov 22 Javascript
js实现图片旋转的三种方法
Apr 10 Javascript
JavaScript编程学习技巧汇总
Feb 21 Javascript
Bootstrap每天必学之日期控制
Mar 07 Javascript
详解JS中定时器setInterval和setTImeout的this指向问题
Jan 06 Javascript
获取当前按钮或者html的ID名称实例(推荐)
Jun 23 Javascript
weex里Vuex state使用storage持久化详解
Sep 09 Javascript
详解使用mpvue开发github小程序总结
Jul 25 Javascript
原生js拖拽实现图形伸缩效果
Feb 10 Javascript
Node.js+Vue脚手架环境搭建的方法步骤
Mar 08 Javascript
JS如何调用WebAssembly编译出来的.wasm文件
Nov 05 Javascript
SuperSlide标签切换、焦点图多种组合插件
Mar 14 #Javascript
纯javascript实现简单下拉刷新功能
Mar 13 #Javascript
Jquery插件实现点击获取验证码后60秒内禁止重新获取
Mar 13 #Javascript
node.js [superAgent] 请求使用示例
Mar 13 #Javascript
JavaScript中逗号运算符介绍及使用示例
Mar 13 #Javascript
JavaScript原生对象之String对象的属性和方法详解
Mar 13 #Javascript
JQuery报错Uncaught TypeError: Illegal invocation的处理方法
Mar 13 #Javascript
You might like
php 面试碰到过的问题 在此做下记录
2011/06/09 PHP
php字符串分割函数explode的实例代码
2013/02/07 PHP
基于php-fpm的配置详解
2013/06/03 PHP
php冒泡排序与快速排序实例详解
2015/12/07 PHP
thinkPHP导出csv文件及用表格输出excel的方法
2015/12/30 PHP
thinkphp Apache配置重启Apache1 restart 出错解决办法
2017/02/15 PHP
关于php开启错误提示的总结
2019/09/24 PHP
JavaScript 学习笔记(六)
2009/12/31 Javascript
javascript回车完美实现tab切换功能
2014/03/13 Javascript
js获取页面传来参数的方法
2014/09/06 Javascript
javascript Deferred和递归次数限制实例
2014/10/21 Javascript
JS获取时间的方法
2015/01/21 Javascript
详谈javascript中的cookie
2015/06/03 Javascript
详谈JS中实现种子随机数及作用
2016/07/19 Javascript
webpack打包js的方法
2018/03/12 Javascript
vue2.0 如何在hash模式下实现微信分享
2019/01/22 Javascript
Node.js 进程平滑离场剖析小结
2019/01/24 Javascript
JavaScript实现图片轮播特效
2019/10/23 Javascript
在vue中使用防抖和节流,防止重复点击或重复上拉加载实例
2019/11/13 Javascript
如何用JS模拟实现数组的map方法
2020/07/30 Javascript
[02:15]2014DOTA2国际邀请赛 专访LGD.lin小兔子是大腿
2014/07/14 DOTA
详解Python函数作用域的LEGB顺序
2016/05/14 Python
PyQt5每天必学之像素图控件QPixmap
2018/04/19 Python
Python制作exe文件简单流程
2019/01/24 Python
Python 中判断列表是否为空的方法
2019/11/24 Python
简单介绍一下pyinstaller打包以及安全性的实现
2020/06/02 Python
Pycharm连接gitlab实现过程图解
2020/09/01 Python
Python批量获取并保存手机号归属地和运营商的示例
2020/10/09 Python
基于Python模拟浏览器发送http请求
2020/11/06 Python
Madda Fella官网:美国冒险家服装品牌
2020/01/16 全球购物
俄语专业毕业生推荐信
2013/10/28 职场文书
博士学位自我鉴定范文
2013/12/26 职场文书
捐助倡议书范文
2014/04/15 职场文书
招标保密承诺书
2015/01/20 职场文书
Python pygame实现中国象棋单机版源码
2021/06/20 Python
elasticSearch-api的具体操作步骤讲解
2021/06/28 Java/Android