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

一、步骤:

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

  1、生成格子

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

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

  

  下面是代码生成的格子:

  

  2、生成数独数组

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

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

    

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

    

    

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

最新文章

  1. js实现蛇形矩阵
  2. Windows动态库学习心得
  3. 复习做UWP时涉及到的几种加密签名相关
  4. 对于改善 MySQL 数据装载操作有效率的方法是怎样
  5. telnet登录路由器启动服务的shell脚本
  6. gVim 配置方案 采用Vundle管理插件
  7. Windows 驱动开发 - 5
  8. java.io.FileNotFoundException: class path resource [bean/test/User.hbm.xml] cannot be opened because it does not exist
  9. JDBC02 利用JDBC连接数据库【使用数据库连接池】
  10. sudo命令详解
  11. C# 两个datatable中的数据快速比较返回交集或差集[z]
  12. oracle函数返回结果集
  13. sql 删除默认索引,对象 依赖于 列,由于一个或多个对象访问此列
  14. python接口自动化测试二十九:yaml配置文件的写和读
  15. codevs1048石子归并
  16. python-time,datetime
  17. 使用distillery&amp;&amp;docker 部署phoenix 应用
  18. SRM 449 DIV 1 总结(550p标记下,下次做)
  19. Spring中的BeanPostProcessor
  20. jenkins权限管理,不同用户显示不同项目

热门文章

  1. 换个角度聊聊FaaS
  2. Mac剪切AVI视频
  3. openwrt如何关掉防火墙?
  4. 机器学习实战(笔记)------------KNN算法
  5. 何给域名配置https证书
  6. idea使用的小技巧总结
  7. C语言--第3次作业
  8. Ocelot概述
  9. Java问题解决:&quot;错误:编码GBK 的不可映射字符&quot;
  10. T2027 蜈蚣