規則:玩家須要根據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 ,感謝!