数独游戏 js
规则:玩家需要根据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的更多相关文章
- 用html5 canvas和JS写个数独游戏
为啥要写这个游戏? 因为我儿子二年级数字下册最后一章讲到了数独.他想玩儿. 因为我也想玩有提示功能的数独. 因为我也正想决定要把HTML5和JS搞搞熟.熟悉一个编程平台,最好的办法,就是了解其原理与思 ...
- 用 JS 做一个数独游戏(二)
用 JS 做一个数独游戏(二) 在 上一篇博客 中,我们通过 Node 运行了我们的 JavaScript 代码,在控制台中打印出来生成好的数独终盘.为了让我们的数独游戏能有良好的体验,这篇博客将会为 ...
- 用 JS 做一个数独游戏(一)
用 JS 做一个数独游戏(一) 数独的棋盘由 9x9 的方格组成,每一行的数字包含 1 ~ 9 九个数字,并且每一列包含 1 ~ 9 这 9 个不重复的数字,另外,整个棋盘分为 9 个 3x3 的块, ...
- Swift数独游戏优化——C++与OC混编、plist自动生成
一.为什么要C++与OC混编? 在我之前的数独游戏中涉及到的数独游戏生成算法是参考的网上其他人的算法,是利用C++来实现的. 但是在我的例子中我发现这样存在一定的局限性: 1.我是利用Termin ...
- 150+行Python代码实现带界面的数独游戏
150行代码实现图形化数独游戏 Github地址,欢迎各位大佬们fork.star啥的,感谢: 今天闲着没事干,以前做过html+js版的数独,这次做个python版本的,界面由pygame完成,数独 ...
- Scrum4.0+5.0 数独游戏
1.题目: 1.准备看板. 形式参考图4. 2.任务认领,并把认领人标注在看板上的任务标签上. 先由个人主动领任务,PM根据具体情况进行任务的平衡. 然后每个人都着手实现自己的任务. 3.为了团队合作 ...
- android数独游戏
最近没事干,照着视频教程写了一个数独游戏,很粗糙还有很多要修改的地方.下面就来说说这个游戏吧 1.自定义一个View控件,用来在屏幕上显示一个9*9的格子,其实就是横着画8条线,竖着画8跳线,然后将其 ...
- android开发——数独游戏
最近研究了一下android,写了一个数独游戏,具体如下: 游戏界面需要重写一个ShuduView继承View, 然后自定义一个Dialog: 1.需要继承 Dialog 类, 2.并要定义一个有参构 ...
- C语言学习 数独游戏
摘要:花了1周多时间学习了C语言,开始练手写解数独游戏的程序. C语言学习 数独游戏 作者:乌龙哈里 时间:2015-11-22 平台:Window7 64bit,TCC 0.9.26(x86-64 ...
随机推荐
- IDEA修改显示星号*和热部署
IDEA修改显示*星号: IDEA热部署: 两步: 1. 2. Ctrl+Alt+Shift+/ 打开下面界面,选Registry 对于Springboot应用,可能无法启动,在上述两步不起作用的情况 ...
- 使用proces explorer查看系统gdi
用mfc开发,使用双缓冲刷新屏幕时,可能会造成GDI的增长,当增长到一定数量[10000]时,软件会崩,可以通过 proces explorer来监测GDI,调试代码 打开proces explore ...
- oracle sql生成临时递增数据
1.生成1至10记录 select rownum from dual connect 结果: 12345678910 2.生成最近12个月记录 ), 'yyyyMM') time from dual ...
- Ubuntu 18.04.1安装IntelliJ IDEA
1.下载安装包 下载地址:https://www.jetbrains.com/idea/download/#section=linux 2.下载完成后,解压到/opt目录 .tar.gz -C /op ...
- python 学习笔记 5 ----> dive into python 3
字符串 文本:屏幕上显示的字符或者其他的记号 计算机认识的东西:位(bit)和字节(byte) 文本的本质:某种字符编码方式保存的内容. 字符编码:一种映射(显示的内容 ----> 内存.磁盘 ...
- java中的默认类型+spring
默认引用类型 Integer Character String(包装类)... private Integer age ; 默认是null 默认基本类型 int char string.privit ...
- 软件安装(ubuntu) --Linux基础编程
Ubuntu:一个以桌面应用为主的开源GNU/Linux操作系统 1.在线安装(Ubuntu Example) [安装]:sudo apt-get install 安装包的名字,或者:sudo apt ...
- SQL查询【根据生日计算】
根据生日日期,获取当前年龄.年龄单位. Select Case when DateDiff(Year, BirthDate, GetDate()) > 0 then DateDiff(Year, ...
- Confluence 6 升级中的一些常见问题
升级的时候遇到了问题了吗? 如果你想尝试重新进行升级的话,你需要首先重新恢复老的备份.不要尝试再次对 Confluence 进行升级或者在升级失败后重新启动老的 Confluence. 在升级过程中 ...
- Linux下的crontab定时执行任务命令详解(参考:https://www.cnblogs.com/longjshz/p/5779215.html)
在Linux中,周期执行的任务一般由cron这个守护进程来处理[ps -ef | grep cron].cron读取一个或多个配置文件,这些配置文件中包含了命令行以及调用时间. cron的配置文件成为 ...