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

上一篇博客 中,我们通过 Node 运行了我们的 JavaScript 代码,在控制台中打印出来生成好的数独终盘。为了让我们的数独游戏能有良好的体验,这篇博客将会为生成好的数独终盘做一个比较完善的界面。最终的效果如下:

你也可以访问网页上的 demo 进行数独游戏的体验。

完善挖洞算法

上一篇博客 中提到过挖洞算法,实际上那并不完整,因为算法里面只有生成数独终盘的部分,并没有进行挖洞处理(也就是隐藏部分格子)。为了补充完整挖洞的算法,我们在 Game 对象里面加上随机隐藏格子的代码:

// class Game
/**
* 挖去一部分格子,将属性设为隐藏
*/
digBoard() {
let dig = 0, block;
for(let i = 0; i < 3; i++) {
for(let j = 0; j < 3; j++) {
for( let k = 0; k < this.digTimes; k++) {
block = this.board.getBlockGrids(i, j);
dig = Math.floor( Math.random() * 9 ); if( block[dig].isVisible() ) {
// avoid duplicated hiding
block[dig].setVisible(false);
}
}
}
}
// Utils.printAll(this.board);
}

实际上就是很简单的取随机数,在每个 block 块(一个块是一个 3x3 的大方格)中进行 n 次循环,每次循环都将随机的数作为索引,修改块中的 grid 对象的 visible 属性,将其设为隐藏。

挖洞法比较简单,通过预设的三种难度:

Game.DifficutyEasy = 1;
Game.DifficutyNormal = 2;
Game.DifficutyHard = 3;

每种难度隐藏不同数目的格子,然后只要将其显示在界面上即可。

编写界面代码

界面是用网页的方式实现的,主要的 html 代码如下:

<div align="center">
<div id="gamediv" align="center"> </div>
<div>
<p id="result-label" class="result-normal"></p>
</div>
<hr />
<div id="time">
<p id="time-label">00:00:00</p>
</div>
<div id="difficuty">
<input type="radio" name="difficuty" value="1" onmouseup="changeDifficuty(this.value)" checked="checked" />Easy
<input type="radio" name="difficuty" value="2" onmouseup="changeDifficuty(this.value)" /> Normal
<input type="radio" name="difficuty" value="3" onmouseup="changeDifficuty(this.value)" /> Hard
</div>
<div id="buttons">
<button onclick="genBoard()" type="button">Restart game</button>
<button onclick="tu.startTimer()" type="button">Start Game</button>
</div>
</div>
<script src="./NumberPlaceCore.js"></script>
<script src="./game.js"></script>

预留了一个 div 用于显示数独棋盘。有用时记录,两个按钮,和难度选择。

数独棋盘的显示是由 JavaScript 代码完成的。首先查找页面中是否已有数独棋盘,若已有棋盘,则先将其删除,再重新创建,这样做是为了重新开始游戏后保证页面中只有一个棋盘。

let tBoard;
tBoard = document.getElementById("board");
if( tBoard ) {
tBoard.remove();
}
tBoard = document.createElement("table");

然后通过循环依次创建各个格子,对于未显示的值的格子,将其用一个 input 组件表示,留给玩家填数字,最后将填充好的格子添加到预览的 div 中:

let tr, td, grid, value;
let ginput;
for(let i = 0; i < 9; i++) {
tr = document.createElement("tr");
for(let j = 0; j < 9; j++) {
td = document.createElement("td");
value = g.getValueAt(new Number(i), new Number(j));
td.setAttribute("class", "grid-show");
if( value ) {
td.innerHTML = value;
}
else {
ginput = document.createElement("input");
inputs.push(ginput);
// ... 省略部分代码
td.appendChild(ginput);
}
tr.appendChild(td);
}
tBoard.appendChild(tr);
} gamediv.appendChild(tBoard);

其中有个 inputs 数组用于记录待填的格子,每当玩家向格子中填一个数,就会调用函数 placeGrid,将玩家填写的值传递给底层的 board 对象。每次填写数字时,都会判断一次是否所有的待填格子都已经填充完毕:

function checkInputs() {
let valid = true;
inputs.forEach( e => {
if( !e.value ) {
valid = false;
}
});
return valid;
}

若该函数返回 true 的话,那么就应该提示用于游戏结束,给出结果,例如:

总结

这一部分其实比较简单,涉及到较多的内容是通过 JavaScript 代码对 DOM 进行操作。但是这部分代码仍然有些不足:

  1. 计时工具必须要手动点击 Start Game 按钮才会开始计时,可以考虑做成玩家进入界面时就开始计时,或者开始填充第一个数时计时。

  2. 缺乏一些提示,可以在提高待填格子数目的情况下,通过某个操作(比如说点击帮助按钮显示某个格子的值)来降低游戏难度,提高可玩性。

  3. 挖洞法的方法是随机的,不能确定是否在挖完之后的棋盘上填充数字时只有唯一解。

至此,一个简单的数独游戏就完成了。

用 JS 做一个数独游戏(二)的更多相关文章

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

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

  2. 如何用纯js做一个大富翁游戏

    下面这张是效果图: 先立个flag,一个星期内把这个坑填了

  3. 使用PixiJS做一个小游戏

    PixiJS PixiJS使用WebGL,是一个超快的HTML5 2D渲染引擎.作为一个Javascript的2D渲染器,Pixi.js的目标是提供一个快速的.轻量级而且是兼任所有设备的2D库. 官方 ...

  4. js实现一个小游戏(飞翔的jj)

    js实现一个小游戏(飞翔的jj) 源代码+素材图片在我的仓库 <!DOCTYPE html> <html lang="en"> <head> & ...

  5. python做一个数独小游戏

    最近看了下python的一些知识,在这里记载一下. 1.首先是安装,在官网下载最新的版本3.6,安装的时候要注意在下面勾选上ADD TO PATH,安装的时候会自动写入到环境变量里面,如果没有勾选,可 ...

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

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

  7. 用JS做一个简单的电商产品放大镜功能

    使用js制作一个简单的产品放大图 购物网站的产品页经常会放有一个产品展示图区.该图区有一个功能就是产品图的放大功能,移动左侧的焦点区域,可以放大细节部分观看,详情如下图.实现该功能的方法也非常简单. ...

  8. 如何使用impress.js做一个网页版本的PPT

    blockquote{font-size: 18px;line-height:1.5;margin:0;}line-height: 1.5; 要做一个网站制作规范培训,之前村长做过一次培训,但是后来一 ...

  9. 使用node.js做一个自用的天气插件

    var request = require('request') var url = 'http://www.baidu.com/home/xman/data/superload' var cooki ...

随机推荐

  1. 关于webapi练习过程中遇到的一系列问题记录

    最近在尝试本地进行webapi调用的过程中,遇到一系列的问题,demo很小但着实让人头疼,先附上demo. 前台页面,目的是展示新闻的分类: 类别模型如下: 控制器代码如下: public Actio ...

  2. ubuntu - 官方简体中文wiki,有你想要的ubuntu的一切

    ubuntu官方简体中文wiki:http://wiki.ubuntu.org.cn/%E9%A6%96%E9%A1%B5

  3. Leetcode 70. Climbing Stairs 爬楼梯 (递归,记忆化,动态规划)

    题目描述 要爬N阶楼梯,每次你可以走一阶或者两阶,问到N阶有多少种走法 测试样例 Input: 2 Output: 2 Explanation: 到第二阶有2种走法 1. 1 步 + 1 步 2. 2 ...

  4. MySQL数据查询结果导出生成文件

    select url from news where url like "%美女%"  into outfile  "/导出的文件路径" : 在这里有个坑,对于 ...

  5. php字符串中去除html标签

    strip_tags() 函数剥去字符串中的 HTML.XML 以及 PHP 的标签.

  6. 我的web安全工程师学习之路——规划篇

    据网上收集的web安全工程师需要掌握哪些技能,职位要求以及如何入门,加上学习网易推出的web安全工程师微专业课程,为了进一步学习,所以给自己做了一些小小规划,也希望给同样想成为web安全工程师的同仁们 ...

  7. Redis 工具类 java 实现的redis 工具类

    最近了解了一下非关系型数据库 redis 会使用简单的命令 在自己本地电脑 使用时必须先启动服务器端 在启动客户端 redis 简介 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内 ...

  8. eclipse 自定义 文档

    在这里写....

  9. C语言实践

    初学者往往有这样的困惑: 教程也阅读了,知识点也理解了,但是真正编写代码起来无从下手. 连一些基本的小程序都不能完成. 究其原因,就是缺少实践,没有培养起编程思维. 没有处理相关问题的经验. 编程能力 ...

  10. linux学习四x系统指令

    一.任务调度 任务调度:系统在某个时间执行特定的命令或者程序 如: 1.对于一些需要周期性执行的一些系统指令 2.定期的病毒扫描 3.定期数据库备份等   命令:crontab 设置任务调度文件: / ...