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 event 事件解析
Jan 31 Javascript
从零开始学习jQuery (十) jQueryUI常用功能实战
Feb 23 Javascript
jQuery对下拉框,单选框,多选框的操作
Feb 21 Javascript
node.js中的console用法总结
Dec 15 Javascript
jQuery使用after()方法在元素后面添加多项内容的方法
Mar 26 Javascript
jQuery中$.extend()用法实例
Jun 24 Javascript
jquery单击事件和双击事件冲突解决方案
Mar 02 Javascript
JS使用cookie设置样式的方法
Jun 30 Javascript
BootstrapTable请求数据时设置超时(timeout)的方法
Jan 22 Javascript
Vue2几种常见开局方式详解
Sep 09 Javascript
vue组件(全局,局部,动态加载组件)
Sep 02 Javascript
JavaScript检测浏览器是否支持CSS变量代码实例
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&amp;java(二)
2006/10/09 PHP
PHP 杂谈《重构-改善既有代码的设计》之三 重新组织数据
2012/04/09 PHP
PHP实现类似于C语言的文件读取及解析功能
2017/09/01 PHP
PHP实现页面静态化深入讲解
2021/03/04 PHP
dropdownlist之间的互相联动实现(显示与隐藏)
2009/11/24 Javascript
ko knockoutjs动态属性绑定技巧应用
2012/11/14 Javascript
button没写type=button会导致点击时提交
2014/03/06 Javascript
from表单多个按钮提交用onclick跳转不同action
2014/04/24 Javascript
JavaScript将取代AppleScript?
2014/09/18 Javascript
简单方法判断JavaScript对象为null或者属性为空
2014/09/26 Javascript
JavaScript通过this变量快速找出用户选中radio按钮的方法
2015/03/23 Javascript
JavaScript数组去重由慢到快由繁到简(优化篇)
2016/08/26 Javascript
Angular 2应用的8个主要构造块有哪些
2016/10/17 Javascript
浅析JavaScript中break、continue和return的区别
2016/11/30 Javascript
jQuery中each循环的跳出和结束实例
2017/08/16 jQuery
BootStrap Validator 根据条件在JS中添加或移除校验操作
2017/10/12 Javascript
详解 vue.js用法和特性
2017/10/15 Javascript
vue综合组件间的通信详解
2017/11/06 Javascript
js实现全选反选不选功能代码详解
2019/04/24 Javascript
vue 使用axios 数据请求第三方插件的使用教程详解
2019/07/05 Javascript
Vue.js组件通信之自定义事件详解
2019/10/19 Javascript
Vue设置长时间未操作登录自动到期返回登录页
2020/01/22 Javascript
浅谈vue websocket nodeJS 进行实时通信踩到的坑
2020/09/22 NodeJs
结合Python的SimpleHTTPServer源码来解析socket通信
2016/06/27 Python
python实现Adapter模式实例代码
2018/02/09 Python
pandas的resample重采样的使用
2020/04/24 Python
利用CSS3实现文字折纸效果实例代码
2018/07/10 HTML / CSS
HTML5画渐变背景图片并自动下载实现步骤
2013/11/18 HTML / CSS
美国求婚钻戒网站:Super Jeweler
2016/08/27 全球购物
乌克兰时尚鞋子和衣服购物网站:Born2be
2018/05/24 全球购物
实习老师离校感言
2014/02/03 职场文书
教师纪念9.18事件演讲稿范文
2014/09/14 职场文书
银行委托书范本
2014/09/28 职场文书
浅谈怎么给Python添加类型标注
2021/06/08 Python
MYSQL 的10大经典优化案例场景实战
2021/09/14 MySQL
Vue中使用import进行路由懒加载的原理分析
2022/04/01 Vue.js