规则:玩家需要根据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 ,感谢!

数独游戏 js的更多相关文章

  1. 用html5 canvas和JS写个数独游戏

    为啥要写这个游戏? 因为我儿子二年级数字下册最后一章讲到了数独.他想玩儿. 因为我也想玩有提示功能的数独. 因为我也正想决定要把HTML5和JS搞搞熟.熟悉一个编程平台,最好的办法,就是了解其原理与思 ...

  2. 用 JS 做一个数独游戏(二)

    用 JS 做一个数独游戏(二) 在 上一篇博客 中,我们通过 Node 运行了我们的 JavaScript 代码,在控制台中打印出来生成好的数独终盘.为了让我们的数独游戏能有良好的体验,这篇博客将会为 ...

  3. 用 JS 做一个数独游戏(一)

    用 JS 做一个数独游戏(一) 数独的棋盘由 9x9 的方格组成,每一行的数字包含 1 ~ 9 九个数字,并且每一列包含 1 ~ 9 这 9 个不重复的数字,另外,整个棋盘分为 9 个 3x3 的块, ...

  4. Swift数独游戏优化——C++与OC混编、plist自动生成

    一.为什么要C++与OC混编? 在我之前的数独游戏中涉及到的数独游戏生成算法是参考的网上其他人的算法,是利用C++来实现的.   但是在我的例子中我发现这样存在一定的局限性: 1.我是利用Termin ...

  5. 150+行Python代码实现带界面的数独游戏

    150行代码实现图形化数独游戏 Github地址,欢迎各位大佬们fork.star啥的,感谢: 今天闲着没事干,以前做过html+js版的数独,这次做个python版本的,界面由pygame完成,数独 ...

  6. Scrum4.0+5.0 数独游戏

    1.题目: 1.准备看板. 形式参考图4. 2.任务认领,并把认领人标注在看板上的任务标签上. 先由个人主动领任务,PM根据具体情况进行任务的平衡. 然后每个人都着手实现自己的任务. 3.为了团队合作 ...

  7. android数独游戏

    最近没事干,照着视频教程写了一个数独游戏,很粗糙还有很多要修改的地方.下面就来说说这个游戏吧 1.自定义一个View控件,用来在屏幕上显示一个9*9的格子,其实就是横着画8条线,竖着画8跳线,然后将其 ...

  8. android开发——数独游戏

    最近研究了一下android,写了一个数独游戏,具体如下: 游戏界面需要重写一个ShuduView继承View, 然后自定义一个Dialog: 1.需要继承 Dialog 类, 2.并要定义一个有参构 ...

  9. C语言学习 数独游戏

    摘要:花了1周多时间学习了C语言,开始练手写解数独游戏的程序. C语言学习 数独游戏 作者:乌龙哈里 时间:2015-11-22 平台:Window7 64bit,TCC 0.9.26(x86-64 ...

随机推荐

  1. QString使用正则表达式快速去空格

    //QString去掉空格 QString str; str.remove(QRegExp("\\s"));

  2. Unity3D制作红色射线

    1.在发射射线的位置创建一个空物体用于存储发射点的位置信息. 2.制作射线,为发射射线物体添加LineRenderer组件  制作Material材质并把其类型改为Particles/Addictiv ...

  3. Struts 2 执行流程 配置信息

    Struts 2 执行流程 首先,浏览器访问,经过Filter,Filter从src/struts.xml中寻找命名空间和action的名字,获取action类,从方法中拿到返回值,接着从result ...

  4. vue中前端处理token过期的方法与axios请求拦截处理

    在处理token过期的这个问题上困扰了我很久,现在终于解决的了,所以分享出来给大家,希望能够对大家有所帮助. 首先,当然是路由进行拦截,路由拦截当然是在beforeEach中了: router.bef ...

  5. MySQL存储过程 CASE语句

    MySQL存储过程  CASE语句 除了IF语句,MySQL提供了一个替代的条件语句CASE. MySQL CASE语句使代码更加可读和高效. CASE语句有两种形式:简单的搜索CASE语句. 简单C ...

  6. Axure 矩形交互样式与单选按钮组设置

    矩形交互样式: 场景:当点击昵称的时候,密码栏会显示红框,当点击密码的时候,昵称会显示红框 补充:昵称栏和密码栏的组成其实是一个矩形框和一个文本框,这样才可以设置出场景所示的样式 这里的设置只是简单的 ...

  7. 关于被删以及限制评价后,免费更换新listing的方法

    Prime Day 刚过,review被撸空,还限制留评,之后单量一泻千里,广告都花不出去,没办法,按照网上贴出来的教程自己摸索,居然成功了解除了留评限制,优点是不用移仓,省了一比费用,缺点是list ...

  8. 移动vue项目,启动错误:Module build failed: Error: No PostCSS Config found in:

    解决办法:在根目录新建postcss.config.js module.exports = { plugins: { 'autoprefixer': {browsers: 'last 5 versio ...

  9. java第四次上机

    package bbb;public class Person { private String name; private int age; public Person(){ } public Pe ...

  10. js点击加载更多可以增加几条数据的显示

      <div class="list"> <div class="one"> <div class="img" ...