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 限制输入脚本大全
Nov 03 Javascript
获取body标签的两种方法
Oct 13 Javascript
Angular实现form自动布局
Jan 28 Javascript
JavaScript递归操作实例浅析
Oct 31 Javascript
react-native使用react-navigation进行页面跳转导航的示例
Sep 07 Javascript
使用D3.js创建物流地图的示例代码
Jan 27 Javascript
vue.js实现插入数值与表达式的方法分析
Jul 06 Javascript
详解Node.js 中使用 ECDSA 签名遇到的坑
Nov 26 Javascript
JS实现返回上一页并刷新页面的方法分析
Jul 16 Javascript
vue+eslint+vscode配置教程
Aug 09 Javascript
layui默认选中table的CheckBox复选框方法
Sep 19 Javascript
vue+Element-ui实现登录注册表单
Nov 17 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
建立文件交换功能的脚本(三)
2006/10/09 PHP
使用php发送有附件的电子邮件-(PHPMailer使用的实例分析)
2013/04/26 PHP
php简单的上传类分享
2016/05/15 PHP
php中array_unshift()修改数组key注意事项分析
2016/05/16 PHP
javaScript面向对象继承方法经典实现
2013/08/20 Javascript
js完美实现@提到好友特效(兼容各大浏览器)
2015/03/16 Javascript
javascript 实现map集合
2015/04/03 Javascript
AngularJS基础 ng-click 指令示例代码
2016/08/01 Javascript
jQuery 如何实现一个滑动按钮开关
2016/12/01 Javascript
基于js实现的限制文本框只可以输入数字
2016/12/05 Javascript
原生js实现查询天气小应用
2016/12/09 Javascript
javascript常用经典算法详解
2017/01/11 Javascript
详解React Native顶|底部导航使用小技巧
2017/09/14 Javascript
angular4模块中给标签添加背景图的实现方法
2017/09/15 Javascript
vue框架下部署上线后刷新报404问题的解决方案(推荐)
2019/04/03 Javascript
什么时候不能在 Node.js 中使用 Lock Files
2019/06/24 Javascript
vuex入门最详细整理
2020/03/04 Javascript
JavaScript/TypeScript 实现并发请求控制的示例代码
2021/01/18 Javascript
[01:20]DOTA2上海特级锦标赛现场采访:谁的ID最受青睐
2016/03/25 DOTA
[01:02:30]Mineski vs Secret 2019国际邀请赛淘汰赛 败者组 BO3 第三场 8.22
2019/09/05 DOTA
python实现目录树生成示例
2014/03/28 Python
pytorch + visdom CNN处理自建图片数据集的方法
2018/06/04 Python
python实现简易动态时钟
2018/11/19 Python
python Pexpect 实现输密码 scp 拷贝的方法
2019/01/03 Python
Pandas-Cookbook 时间戳处理方式
2019/12/07 Python
opencv中图像叠加/图像融合/按位操作的实现
2020/04/01 Python
快速解决Django关闭Debug模式无法加载media图片与static静态文件
2020/04/07 Python
浅谈如何使用python抓取网页中的动态数据实现
2020/08/17 Python
物业管理员岗位职责范文
2013/11/25 职场文书
迟到检讨书1000字
2014/01/15 职场文书
运动会广播稿400字
2014/01/25 职场文书
2014学习全国两会精神心得体会2000字
2014/03/11 职场文书
违反交通法规检讨书
2014/09/10 职场文书
立项申请报告范本
2015/05/15 职场文书
Python标准库之typing的用法(类型标注)
2021/06/02 Python
oracle delete误删除表数据后如何恢复
2022/06/28 Oracle