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 相关文章推荐
javascript图像处理—仿射变换深度理解
Jan 16 Javascript
jquery中获取id值方法小结
Sep 22 Javascript
JS批量修改PS中图层名称的方法
Jan 26 Javascript
微信小程序商城项目之购物数量加减(3)
Apr 17 Javascript
vue中component组件的props使用详解
Sep 04 Javascript
在angular 6中使用 less 的实例代码
May 13 Javascript
jQuery.validate.js表单验证插件的使用代码详解
Oct 22 jQuery
jQuery实现获取当前鼠标位置并输出功能示例
Jan 05 jQuery
node基于async/await对mysql进行封装
Jun 20 Javascript
JS字符串常用操作方法实例小结
Jun 24 Javascript
Vue 实现前端权限控制的示例代码
Jul 09 Javascript
八种Vue组件间通讯方式合集(推荐)
Aug 18 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 小乘法表实现代码
2009/07/16 PHP
使用php将某个目录下面的所有文件罗列出来的方法详解
2013/06/21 PHP
php+mysql数据库查询实例
2015/01/21 PHP
如何解决phpmyadmin导入数据库文件最大限制2048KB
2015/10/09 PHP
ThinkPHP 3使用OSS的方法
2018/07/19 PHP
jquery实现背景墙聚光灯效果示例分享
2014/03/02 Javascript
Node.js中使用事件发射器模式实现事件绑定详解
2014/08/15 Javascript
数据分析软件之FineReport教程:[5]参数界面JS(全)
2015/08/13 Javascript
AngularJS 让人爱不释手的八种功能
2016/03/23 Javascript
easyUI实现(alert)提示框自动关闭的实例代码
2016/11/07 Javascript
利用浮层使select不可选的实现方法
2016/12/03 Javascript
ionic3实战教程之随机布局瀑布流的实现方法
2017/12/28 Javascript
Vue的elementUI实现自定义主题方法
2018/02/23 Javascript
echarts鼠标覆盖高亮显示节点及关系名称详解
2018/03/17 Javascript
nodejs多版本管理总结
2018/04/03 NodeJs
vue生成token并保存到本地存储中
2018/07/17 Javascript
js数据类型检测总结
2018/08/05 Javascript
菊花转动的jquery加载动画效果
2018/08/19 jQuery
详解微信小程序-扫一扫 wx.scanCode() 扫码大变身
2019/04/30 Javascript
JS 实现发送短信验证码的“59秒后重新发送验证短信”功能
2019/08/23 Javascript
[01:02:34]TFT vs VGJ.T Supermajor 败者组 BO3 第二场 6.5
2018/06/06 DOTA
Python中的ctime()方法使用教程
2015/05/22 Python
Python cookbook(字符串与文本)针对任意多的分隔符拆分字符串操作示例
2018/04/19 Python
Django中使用Celery的教程详解
2018/08/24 Python
python 制作自定义包并安装到系统目录的方法
2018/10/27 Python
Python实现读取txt文件中的数据并绘制出图形操作示例
2019/02/26 Python
Python代码注释规范代码实例解析
2020/08/14 Python
解决Python 写文件报错TypeError的问题
2020/10/23 Python
将不规则的Python多维数组拉平到一维的方法实现
2021/01/11 Python
体育教师求职信
2014/05/24 职场文书
电影建党伟业观后感
2015/06/01 职场文书
幼儿园园长新年寄语
2015/08/17 职场文书
关于销售人员的年终工作总结要点
2019/08/15 职场文书
Python如何利用正则表达式爬取网页信息及图片
2021/04/17 Python
MySQL令人大跌眼镜的隐式转换
2021/08/23 MySQL
nginx日志格式分析和修改
2022/04/28 Servers