那现在就开始本篇内容:通过一个简单的算法自动获取数独需要的二维数组。虽然和canvas没太大关系,但是做游戏嘛,总是需要算法的。
首先初始化一个9×9的数组,全部填入初始值0。

function getArrInit(rowA, colB){//获取9*9的数组,全部初始化为0let arr = [];for(let i = 0; i < rowA; i++){arr[i] = [];for(let j = 0; j < colB; j++){arr[i][j] = 0;}}return arr;
}

然后就开始算法部分。
思路是,先将1-9数字打乱存入一个一维数组中,然后填入到第一个3×3格子中。那这里要注意的是,斜对角的3个3×3的格子是独立的,可以分别填入打乱的1-9数字。
实现如下:

function scrambleNum(min, max){//打乱1-9数字let arrA = getAllNumArr(min, max);//获取1-9顺序数组arrA.sort(function(a, b){return 0.5 - Math.random()});return arrA;
}
function setDiagonallyArr(arr){//斜对角3*3格子设置值let n = 0;//斜对角for(let n = 0; n < 3; n++){let arrA = scrambleNum(1, 9);let index = 0;for(let i = n*3; i < n*3+3; i++){for(let j = n*3; j < n*3+3; j++){arr[i][j] = arrA[index];index++;}}}return arr;
}

那这里就可以看下效果了,先定义一个函数,用来获取最终的数独数组。

function getArr(){//获取数独数组let arr = getArrInit(9, 9);//9*9数组arr = setDiagonallyArr(arr);//斜对角3*3设值//...后续还有操作return arr;
}

将之前写的固定二维数组替换成由getArr()函数得到的。

let arr = getArr();

运行后效果如下:

接下里就更简单了,就按数独的解法来。每个格子能填哪几个值,然后挨个试,就是最简单粗暴的方式。
思路是,先获取一个[1-9]数组,然后通过行、列和3×3的格子去掉不能填入的值。从剩下的值中随机拿一个填入空格中,再继续下一个。
先给数组定义一个remove方法:比如原先有数组[1-9],去掉数字9,那这个数组就只剩[1-8]了,数组长度也变为8。

Array.prototype.remove = function(val) {//给数组添加remove方法var index = this.indexOf(val);if (index > -1) {this.splice(index, 1);}
};

接下来就获取某行某列的格子可填入的值。

function getArrB(arr, row, col){//获取某行某列可填入的值let arrB = getAllNumArr(1, 9);//获取1-9顺序数组//检查行for(let j = 0; j < 9; j++){if(arr[row][j] != 0){arrB.remove(arr[row][j]);}}//检查列for(let i = 0; i < 9; i++){if(arr[i][col] != 0){arrB.remove(arr[i][col]);}}//检查3*3的格子let gi = Math.floor(row/3) * 3;//横向第gi个格子(下标)let gj = Math.floor(col/3) * 3;//纵向第gj个格子(下标)for(let i = gi; i < gi+3; i++){for(let j = gj; j < gj+3; j++){if(arr[i][j] != 0){arrB.remove(arr[i][j]);}}}return arrB;
}

arrB[]这个一维数组里存储的就是当前这个格子中剩下来可填入的值了。再从这个数组里随机拿一个数字。

function randomArrB(arrB){//随机获取一个一维数组的值let index = Math.floor(Math.random() * arrB.length);return index;
}

那准备工作都做好了,就可以开始解数独了。

function solutionArr(arr){//解数独的方式填值for(let i = 0; i < arr.length; i++){for(let j = 0; j < arr[i].length; j++){if(arr[i][j] == 0){let arrB = getArrB(arr, i, j);if(arrB.length == 0){//本次没有可填入的值,解失败了return arr;} else {let index = randomArrB(arrB);arr[i][j] = arrB[index];}}}}return arr;
}

当然这个解法每次运行只会解一次。那很小的几率能解出来,人玩的时候还可能走入死胡同呢,代码就执行一次解不出很正常。这里不妨碍可以先看看效果。
在getArr()函数中调用解数独方法。

arr = solutionArr(arr);

运行后,并多次刷新,效果如下。

那不能由我们手动操作刷新来获取一个完整的数独吧。就可以直接使用循环,多次循环下,总有机会拿到一个正确的解。
需要判断下,当前是否已全部解出。因为每次填值都是填对的值,所以当这个数组中全部有值即不为0时,就是解出来了。写一个方法来判断。

function checkArr(arr){//判断数独是否解开for(let i = 0; i < arr.length; i++){for(let j = 0; j < arr[i].length; j++){if(arr[i][j] == 0){return false;}}}return true;
}

这里循环需要注意的是,每次我们拿到了数组填了值,那原数组的值就变了。所以重新解的时候需要将最开始斜对角3×3完成后的数组复制一份。

function copyArr(arr){//复制一个数组。只复制值。let arrBF = [];for(let i = 0; i < arr.length; i++){arrBF[i] = [];for(let j = 0; j < arr[i].length; j++){arrBF[i][j] = arr[i][j];}}return arrBF;
}

接下来就可以调用尝试下了。在getArr()函数中加入代码。

let arrBF = copyArr(arr);//备份数组
do{arr = copyArr(arrBF);arr = solutionArr(arr);
}while(!checkArr(arr));

运行效果如下。

当然这肯定不是我们想要的最终答案,全解出来了,我们还玩啥。接下来就要去掉一些值,让玩家通过剩下来的值自己解数独了。
这里的思路是,数独有9×9一共81个数字。那就先获取一个[1-81]的数组,分别按顺序对应每个格子。将[1-81]数组的顺序打乱,取前50个位置去掉(这里就能发现难易程度和去掉的值多少还是有一定关系的,可以自己设置难度)。

function getMyArr(arr, n){//随机去掉数独n个值let sumArr = scrambleNum(1,81);//获取1-81打乱的数组for(let a = 0; a < n; a++){//去掉前n个值let numA = sumArr[a];let numi = Math.floor(numA/9) - (numA%9==0 ? 1 : 0);let numj = numA%9==0 ? 8 : (numA%9-1);arr[numi][numj] = 0;}return arr;
}

在getArr()函数中加入代码。

arr = getMyArr(arr, 50);//随机去掉50个值

运行效果如下,还是一直点击刷新来看。(这里使用火狐浏览器时,好像打乱的数组并不是太随机,就用的是搜狗浏览器)

那到这呢,一个简易的数独就完成了。后面的也还可以实现一些,就上面说的难度选择,还有就是完成后可以由程序检测是否解成功。当然这些我也还没实现,有空的话再来研究学习下,那有关Canvas数独的下一篇就随缘啦。

HTML5 Canvas制作数独游戏(四)相关推荐

  1. HTML5 Canvas制作数独游戏(一)

    初次接触Canvas,想做一个数独游戏,查找资料后开始着手实现.途中也遇到几个难点,也都克服了,实现了一个简单的版本,就想把过程写下来.水平有限,代码可能也有不完善的地方. 好了,废话不多说,现在开始 ...

  2. HTML5 Canvas制作数独游戏(三)

    上篇已经实现了点选后给予显示,本篇就开始讲解如何往数独中填入数字.这里使用的是在数独右边区域展示1-9数字,选择数字后自动填入. 那这1-9数字也得画出来,那就需要第3块画布了.添加标签如下(当然这里 ...

  3. [译]怎样用HTML5 Canvas制作一个简单的游戏

    这是我翻译自LostDecadeGames主页的一篇文章,原文地址:How To Make A Simple HTML5 Canvas Game. 下面是正文: 自从我制作了一些HTML5游戏(例如C ...

  4. html5上色游戏制作,怎样用HTML5 Canvas制作一个简单的游戏

    原文连接: How To Make A Simple HTML5 Canvas Game 自从我制作了一些HTML5游戏(例如Crypt Run)后,我收到了很多建议,要求我写一篇关于怎样利用HTML ...

  5. html制作状态栏数字时钟,html5 canvas制作15种数字时钟样式代码

    特效描述:html5 canvas制作 数字时钟样式.html5 canvas数字时钟代码 代码结构 1. 引入CSS 2. 引入JS 3. HTML代码 clockd1_={ "indic ...

  6. HTML5+canvas激流勇进网页游戏源码

    介绍: HTML5+canvas激流勇进网页游戏,游戏玩法:使用左键.右键和上箭头键移动. 网盘下载地址: http://kekewangLuo.cc/qn9O6AvpNW10 图片:

  7. html5在线制作教程,HTML5 Canvas 制作动画

    HTML5 Canvas 制作动画 在HTML5 canvas中绘制图像动画效果,你需要绘制出每一帧的图像,然后在一个极短的时间内从一帧过渡到下一帧,形成动画效果. 在线示例 要在HTML5画布上绘制 ...

  8. html5怎么做出旋转效果,HTML5+Canvas制作的幻彩旋转圆盘特效

    HTML5+Canvas制作的幻彩旋转圆盘特效 body { background: #000; color: #aaa; font: 100%/20px helvetica; } canvas { ...

  9. 使用html制作圆弧正方形,JavaScript+html5 canvas制作的圆中圆效果实例

    本文实例讲述了JavaScript+html5 canvas制作的圆中圆效果.分享给大家供大家参考,具体如下: 运行效果截图如下: 具体代码如下: demo #canvas { background: ...

  10. 怎样用HTML5 Canvas制作一个简单的游戏

    为了让大家清楚HTML5制作游戏的简单流程,所以先了制作一个非常简单的游戏,来看一看这个过程.   游戏非常简单,无非就是英雄抓住怪物就得分,然后游戏重新开始,怪物出现在地图的随机位置,英雄初始化在地 ...

最新文章

  1. PreparedStatement
  2. WCF常见问题之端口共享
  3. 分拆之后又有大动作,惠普的下一步怎么走?
  4. python 类属性排序_Python实现多属性排序的方法
  5. 经过几天的Scala回归Java的10个最烦人的事情
  6. Servlet中防止盗链的代码
  7. SpringBoot之Bean之多实例选择
  8. Seata多微服务互相调用_全局分布式事物使用案例_Order-Module order微服务的配置搭建---微服务升级_SpringCloud Alibaba工作笔记0060
  9. indesign教程,如何在帧之间流动文本?
  10. 转:运行yum报错Error: Cannot retrieve metalink for reposit
  11. oracle字符串转日期比较大小写,【varchar】oracle中比较日期大小日期定义的是varchar2类型的......
  12. python输出艺术字_Python中输出ASCII大文字、艺术字、字符字小技巧
  13. Error:Execution failed for task :app:mergeDebugResourcesSome file crunching failed的解决方法
  14. 聊聊Hadoop DistCp的数据切分处理方式
  15. Centos Piranha安装过程
  16. 创建一个简单的后台教务管理系统,包含动态增删改查学生,年级和课程信息及查看登录日志等功能,包含表单验证.
  17. 【专题5: 硬件设计】 之 【39.案例三:碎纸机,光电传感器电路原理图】
  18. 人工智能之自动驾驶系列(一):概要
  19. localtimestamp
  20. 【PIL案例精讲】252行Python代码制作透明背景的电子印章

热门文章

  1. 布丰投针实验 MATLAB仿真 以及报告
  2. 计算机组装教程 ppt,电脑组装教程完整.ppt
  3. 通俗地讲一下庞加莱猜想是怎么回事(from 鼓浪)
  4. OVM虚拟化开启公测,支持Docker全新体验!
  5. echarts柱形图x轴y轴的字体大小颜色调整
  6. 查看 Chrome 下载的文件的真实下载地址
  7. 儿童神经系统肿瘤有哪些,儿童神经系统肿瘤症状
  8. Comsol学习——经典案例:插销支架受力分析
  9. Deep Stream Ai落地--初体验
  10. 用Java来解析torrent文件