数独游戏 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 ...
随机推荐
- java和js中int和String相互转换常用方法整理
java中int和String的相互转换常用的几种方法: int > String int i=10;String s="";第一种方法:s=i+""; ...
- 使用tp访问数据库时提示错误: 'PDO' not found, 和not defined constant mysql_attr_init_command 和call an undefined function Think\Template\simpleXml_load_string()函数
第一个问题: PDO not found 是因为 php没有安装pdo扩展, 无法提供给 php 以 数据库访问功能, 所以 报错是在文件: Think/Db.class.php的里面. 解决方法是: ...
- 关于 diff 和patch
参考: https://blog.csdn.net/zygblock/article/details/53384862 diff和patch是 版本控制 git 的不可缺少的工具 diff 是用来比较 ...
- 论文笔记:Fast Neural Architecture Search of Compact Semantic Segmentation Models via Auxiliary Cells
Fast Neural Architecture Search of Compact Semantic Segmentation Models via Auxiliary Cells 2019-04- ...
- idea使用的小技巧总结
1.需要一个快捷清爽的控制台? 下面这段配置是你需要的,在workspace.xml里面添加 <component name="RunDashboard"> <o ...
- js回调函数以及同步与异步
1. 背景介绍javascript的单线程特性由于javascript语言是一门“单线程”的语言,所以,javascript就像一条流水线,仅仅是一条流水线而已,要么加工,要么包装,不能同时进行多个任 ...
- linux,vim和bash命令小册
linux命令 命令 功能 cd old 进入old文件夹 ll -a 当前文件列表(包含隐藏文件) rm -rf old 删除old文件夹(包含子文件夹) mkdir old 新建old文件夹 ps ...
- Date中before和after方法的使用
Date1.after(Date2),当Date1大于Date2时,返回TRUE,当小于等于时,返回false: Date1.before(Date2),当Date1小于Date2时,返回TRUE,当 ...
- [Linux] 关闭防火墙以及开放端口
一. service iptables stop 临时关闭, chkconfig iptables off完全关闭 service iptables status状态, service iptable ...
- python爬虫-入门-了解爬虫
作为一个爬虫新手,我觉得首先要了解爬虫是的作用以及应用. 作用:通过爬虫获取网页内的信息.包括:标题(title)图片(image)链接(url)等等 应用:抽取所需信息,进行数据汇总及分析(从事网页 ...