数独游戏 js

规则:玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字;保证每一行,每一列,每个宫的数字刚好含1-9,并且不重复。

一、步骤:

  生成格子 ——  生成9×9满足规则的数字 ——  置空一定个数的格子,让玩家选填 ——  检查每次选填结果是否有误 —— 待全部空格被填完,检查结果;

  1、生成格子

  为方便获取格子的值,给每个格子一个对应的key。

  我们给左上点第一个格子的key值为11,那右下角的格子key值则为99,如图:

  

  下面是代码生成的格子:

  

  2、生成数独数组

    因为要保证每一行,每一列,每一宫,均含1-9且不重复,如果从第一个值 开始随机给值,有点无从下手,并且很慢。

扫描二维码关注公众号,回复: 5257778 查看本文章

    考虑到斜对角的三个宫的数字,是没有任何关系的,所以先随机出来,这样比较方便。

    

    然后从第一行还没有赋值的格子开始,获取格子所在行,所在列,所在宫已经有值的数字,排除这些数字后,从可用的数字中随机取一个。直到所以的格子都有值。

    

    

  3、置空一定个数的格子,让玩家选填

    

  4、每次输入后,检查数字是否符合规则,而不是把玩家输入的数字和自己之前生成数字做对比,因为要考虑到多种解法。

    蓝色是无误,标红是已存在

    

 二、附源码:

  

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            * {
                margin: 0;
                padding: 0;
                box-sizing: border-box;
            }
            
            ul,
            ol {
                list-style: none;
            }
            
            .shudu {
                width: 226px;
                height: 226px;
                border-top: 1px solid #000;
                border-left: 1px solid #000;
                margin: 10px auto;
            }
            
            .shudu li {
                width: 100%;
                height: 25px;
                border-bottom: 1px solid;
                border-bottom-color: #ccc;
            }
            
            .shudu li:nth-of-type(3n) {
                border-bottom-color: #000;
            }
            
            .shudu li span {
                float: left;
                width: 25px;
                height: 25px;
                line-height: 25px;
                text-align: center;
                border-right: 1px solid;
                border-right-color: #ccc;
            }
            
            .shudu li span:nth-of-type(3n) {
                border-right-color: #000;
            }
            
            .input {
                color: #08e;
            }
            
            .err {
                color: red;
            }
        </style>
    </head>

    <body>
        <div><label for="">计时:</label><span id="time"></span></div>
        <div class="shudu">
            <ul>

            </ul>
        </div>

        <script src="js/jquery-1.12.3.min.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            var sd = {
                blockNum: 30, //空白格子的数量
                sdArr: [], //生成的数组
                cacheArr: [], //保存数组
                init: function(blockNum) {
                    sd.blockNum = blockNum || sd.blockNum;
                    timer = setInterval(timing, 1000);
                    sd.createDom();
                    sd.createSdArr();
                    sd.createBlock(sd.blockNum);                    
                    sd.checkOne();
                },
                getRandom(n) { //生成随机正整数
                    return Math.floor(Math.random() * n + 1);
                },
                checkOne: function() { //单个检查
                    $(".shudu ul span[contenteditable=true]").keyup(function(event) {
                        var val = $(this).html(),
                            idx = $(this).data().index + "";
                        var reStr = /^[1-9]{1}$/;
                        if(!reStr.test(val)) {
                            $(this).html('');
                        } else {
                            var i = parseInt(idx.split('')[0]),
                                j = parseInt(idx.split('')[1]);
                            var xArr = sd.getXArr(j, sd.sdArr),
                                yArr = sd.getYArr(i, sd.sdArr),
                                palace = sd.getPalace(i, j, sd.sdArr);
                            var beExistArr = xArr.concat(yArr, palace);
                            if($.inArray(+val, beExistArr) > -1) {
                                $(this).removeClass('input').addClass('err');
                            } else {
                                $(this).removeClass('err').addClass('input');
                                sd.sdArr[parseInt(i + '' + j)] = +val;

                                var done = $(".shudu ul span.input").length,
                                    err = $(".shudu ul span.err").length;
                                if(done == sd.blockNum && err == 0) {     //检查空白格是否全部输入
                                    window.clearInterval(timer);
                                    alert('good! 用时:'+$("#time").html()+'');
                                    $("#time").html('00:00:00');
                                    sec = 0; min = 0; hour = 0;
                                    sd.init(sd.blockNum);                                    
                                }
                            }
                        }
                    });
                },
                createBlock: function(num) { //随机空白格
                    var blockArr = [];
                    var numArr = [1, 2, 3, 4, 5, 6, 7, 8, 9];

                    for(var k = 0; k < num; k++) {
                        var n;
                        do {
                            n = parseInt(numArr[sd.getRandom(9) - 1] + '' + numArr[sd.getRandom(9) - 1]);
                        } while ($.inArray(n, blockArr) > -1);      //如果已经选过此格子,再随机选一次
                        blockArr.push(n);
                        var dom = $(".shudu ul span[data-index='" + n + "']");
                        dom.attr('contenteditable', true).text(''); //元素可编辑并置空
                        sd.sdArr[n] = "block";
                    }

                },
                createDom: function() { //生成格子
                    var ul = $(".shudu ul").empty();

                    for(var i = 0; i < 9; i++) {
                        var span = '';
                        for(var j = 0; j < 9; j++) {
                            span += '<span data-index="' + (j + 1) + "" + (i + 1) + '"></span>';
                        }
                        var li = '<li>' + span + '</li>';
                        ul.append(li);
                    }

                },
                createSdArr: function() { //生成数独数组
                    sd.sdArr = [];
                    sd.diagonal(2, 2);
                    sd.diagonal(5, 5);
                    sd.diagonal(8, 8);

                    var allNum = [1, 2, 3, 4, 5, 6, 7, 8, 9];
                    for(var i = 1; i <= 9; i++) {

                        for(var j = 1; j <= 9; j++) {
                            if(!sd.sdArr[parseInt(i + '' + j)]) {
                                var xArr = sd.getXArr(j, sd.sdArr),   //获取所在行数字
                                    yArr = sd.getYArr(i, sd.sdArr),   //获取所在列数字
                                    palace = sd.getPalace(i, j, sd.sdArr);   //获取所在宫数字
                                var beExistArr = xArr.concat(yArr, palace);
                                var ableArr = sd.arrMinus(allNum, beExistArr);   //得到可用数字

                                if(ableArr.length == 0) {
                                    sd.createSdArr();
                                    return;
                                }

                                var theOne = ableArr[sd.getRandom(ableArr.length) - 1];
                                sd.sdArr[parseInt(i + '' + j)] = theOne;

                            }
                        }
                    }

                    sd.cacheArr = sd.sdArr;

                    var spans = $(".shudu ul span");
                    $.each(spans, function(i, v) {
                        var idx = parseInt(v.dataset.index);
                        if(sd.sdArr[idx]){
                            v.innerText = sd.sdArr[idx];
                        }
                        
                    });
                },
                diagonal: function(x, y) { //对角线三宫随机数字
                    var numArr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
                    var sortedNumArr = numArr.sort(function() {
                        return Math.random() - 0.5 > 0 ? -1 : 1
                    });
                    var cenNum = parseInt(x + '' + y);
                    var thIndexArr = [cenNum - 11, cenNum - 1, cenNum + 9, cenNum - 10, cenNum, cenNum + 10, cenNum - 9, cenNum + 1, cenNum + 11];
                    for(var a = 0; a < 9; a++) {
                        sd.sdArr[thIndexArr[a]] = sortedNumArr[a];
                    }
                },
                getXArr: function(j, sdArr) { //获取所在行
                    var arr = [];
                    for(var a = 1; a <= 9; a++) {
                        if(this.sdArr[parseInt(a + "" + j)]) {
                            arr.push(sdArr[parseInt(a + "" + j)])
                        }
                    }
                    return arr;
                },
                getYArr: function(i, sdArr) { //获取所在列
                    var arr = [];
                    for(var a = 1; a <= 9; a++) {
                        if(sdArr[parseInt(i + '' + a)]) {
                            arr.push(sdArr[parseInt(i + '' + a)])
                        }
                    }
                    return arr;
                },
                getPalace: function(i, j, sdArr) { //获取所在宫
                    var arr = [];
                    var cenNum = sd.getPalaceCenter(i, j);
                    var thIndexArr = [cenNum - 11, cenNum - 1, cenNum + 9, cenNum - 10, cenNum, cenNum + 10, cenNum - 9, cenNum + 1, cenNum + 11];
                    for(var a = 0; a < 9; a++) {
                        if(sdArr[thIndexArr[a]]) {
                            arr.push(sdArr[thIndexArr[a]]);
                        }
                    }
                    return arr;
                },
                getPalaceCenter: function(i, j) { //获取所在宫的中间坐标                    
                    var cenArr = [22, 52, 82, 25, 55, 85, 28, 58, 88];
                    var index = (Math.ceil(j / 3) - 1) * 3 + Math.ceil(i / 3) - 1;
                    var cenNum = cenArr[index];
                    return cenNum;
                },
                arrMinus: function(arr1, arr2) {
                    var resArr = [],
                        len = arr1.length;
                    for(var i = 0; i < len; i++) {
                        if($.inArray(arr1[i], arr2) < 0) {
                            resArr.push(arr1[i]);
                        }
                    }
                    return resArr;
                }
            }

            $("#time").html('00:00:00');
            var sec = 0, //
                min = 0, //
                hour = 0; //
            var timer;
            
            function treg(arg){
                return arg < 10 ? ("0" + arg) : arg;
            }

            function timing() {
            
                var time = treg(hour) + ":" +treg(min) + ":" + treg(sec);
                $("#time").html(time);

                sec++;

                if(sec > 59) {
                    sec = 0;
                    min++;
                }
                if(min > 59) {
                    sec = 0;
                    hour++;
                }

            }

            sd.init(35);
        </script>
    </body>

</html>

 思路和代码都有参考 https://blog.csdn.net/liusaint1992/article/details/51147149 ,感谢!

猜你喜欢

转载自www.cnblogs.com/slency-ll/p/10412400.html