數獨遊戲 js

規則:玩家須要根據9×9盤面上的已知數字,推理出全部剩餘空格的數字;保證每一行,每一列,每一個宮的數字恰好含1-9,而且不重複。javascript

1、步驟:css

  生成格子 ——  生成9×9知足規則的數字 ——  置空必定個數的格子,讓玩家選填 ——  檢查每次選填結果是否有誤 —— 待所有空格被填完,檢查結果;html

  一、生成格子java

  爲方便獲取格子的值,給每一個格子一個對應的key。jquery

  咱們給左上點第一個格子的key值爲11,那右下角的格子key值則爲99,如圖:數組

  

  下面是代碼生成的格子:app

  

  二、生成數獨數組dom

    由於要保證每一行,每一列,每一宮,均含1-9且不重複,若是從第一個值 開始隨機給值,有點無從下手,而且很慢。this

    考慮到斜對角的三個宮的數字,是沒有任何關係的,因此先隨機出來,這樣比較方便。spa

    

    而後從第一行尚未賦值的格子開始,獲取格子所在行,所在列,所在宮已經有值的數字,排除這些數字後,從可用的數字中隨機取一個。直到因此的格子都有值。

    

    

  三、置空必定個數的格子,讓玩家選填

    

  四、每次輸入後,檢查數字是否符合規則,而不是把玩家輸入的數字和本身以前生成數字作對比,由於要考慮到多種解法。

    藍色是無誤,標紅是已存在

    

 

 2、附源碼:

  

<!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 ,感謝!

相關文章
相關標籤/搜索