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 相关文章推荐
js验证电话号码与手机支持+86的正则表达式
Jan 23 Javascript
jquery中键盘事件小结
Feb 24 Javascript
JS实现touch 点击滑动轮播实例代码
Jan 19 Javascript
AngularJS使用ng-class动态增减class样式的方法示例
May 18 Javascript
使用原生js写ajax实例(推荐)
May 31 Javascript
JavaScript实现的斑马线表格效果【隔行变色】
Sep 18 Javascript
解决Jstree 选中父节点时被禁用的子节点也会选中的问题
Dec 27 Javascript
vue 组件中slot插口的具体用法
Apr 03 Javascript
JS封装的模仿qq右下角消息弹窗功能示例
Aug 22 Javascript
vue表单自定义校验规则介绍
Aug 28 Javascript
JS如何把字符串转换成json
Feb 21 Javascript
一文帮你理解PReact10.5.13源码
Apr 03 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(3)
2006/10/09 PHP
php随机输出名人名言的代码
2012/10/07 PHP
PHP5.3的垃圾回收机制(动态存储分配方案)深入理解
2012/12/10 PHP
php实现encode64编码类实例
2015/03/24 PHP
PHP CURL中传递cookie的方法步骤
2019/05/09 PHP
jQuery模拟超链接点击效果代码
2013/04/21 Javascript
多个datatable共存造成多个表格的checkbox都被选中
2013/07/11 Javascript
javascript如何创建表格(javascript绘制表格的二种方法)
2013/12/10 Javascript
js获取上传文件大小示例代码
2014/04/10 Javascript
javascript跨域原因以及解决方案分享
2015/04/08 Javascript
基于JavaScript实现文字超出部分隐藏
2016/02/29 Javascript
js遍历json对象所有key及根据动态key获取值的方法(必看)
2017/03/09 Javascript
vue结合Echarts实现点击高亮效果的示例
2018/03/17 Javascript
Vue.js 通过jQuery ajax获取数据实现更新后重新渲染页面的方法
2018/08/09 jQuery
Vue中的v-for指令不起效果的解决方法
2018/09/27 Javascript
Vue+Element实现网页版个人简历系统(推荐)
2019/12/31 Javascript
JavaScript构造函数原理及实现流程解析
2020/11/19 Javascript
Python中apply函数的用法实例教程
2014/07/31 Python
Python从MP3文件获取id3的方法
2015/06/15 Python
python logging 日志轮转文件不删除问题的解决方法
2016/08/02 Python
Python与Java间Socket通信实例代码
2017/03/06 Python
python2.7无法使用pip的解决方法(安装easy_install)
2018/04/03 Python
Python单元测试实例详解
2018/05/25 Python
Windows下Anaconda2安装NLTK教程
2018/09/19 Python
python提取包含关键字的整行数据方法
2018/12/11 Python
python 定时器,实现每天凌晨3点执行的方法
2019/02/20 Python
利用python-docx模块写批量生日邀请函
2019/08/26 Python
Python3加密解密库Crypto的RSA加解密和签名/验签实现方法实例
2020/02/11 Python
Python 实现二叉查找树的示例代码
2020/12/21 Python
Matplotlib animation模块实现动态图
2021/02/25 Python
浅谈cookie和localStorage那些事
2019/08/27 HTML / CSS
特色蛋糕店创业计划书
2014/01/28 职场文书
马丁路德金演讲稿
2014/05/19 职场文书
中秋客户感谢信
2015/01/22 职场文书
爱心捐款活动总结
2015/05/09 职场文书
Python基础之赋值,浅拷贝,深拷贝的区别
2021/04/30 Python