为啥要写这个游戏?

  1. 因为我儿子二年级数字下册最后一章讲到了数独。他想玩儿。
  2. 因为我也想玩有提示功能的数独。
  3. 因为我也正想决定要把HTML5和JS搞搞熟。熟悉一个编程平台,最好的办法,就是了解其原理与思想之后,做个真正完整的东西练练。

之前一直搞.net,后来管理事务多了,很多技术就没跟上,看过一些JS的书,但一直没动手,前几个月,写了第一个JS程序,是一个简单的产品规则引擎,利用v8引擎集成在.net程序中,用脚本来处理产品费用有关的计算。但那个只涉及数值计算。

这几天因为儿子的课本上学逻辑推理,有个数独游戏,儿子大感兴趣,玩了几个,想到如果能自动计算可选数字的话,就会很容易解开数独,在网上找来找去,发现都没有这样功能的数独。正好有点空闲,就决定自已写一个。

所以这个数独是我写的第二个JS程序。在写的过程中也在同时学习。

几个要点

canvas与windows的图形程序原理的不同

一开始,免不了受之前经验的影响,想用winform的图形程序原理来处理html5 canvas的绘图。但发现有点水土不服:windows的图形程序原理是说系统不管保存程序自己窗口里内容,有需要显示时——比如从后台切到前台啦、刚从别的程序下面露出脸来啦等等——就请程序自己再画一遍。所以,程序只需要重写form的OnPaint方法(对于win32程序,则是响应WM_PAINT消息),在其中绘制图形就行了。

在windows程序中,不能直接随时向窗口上画图,比如你想在鼠标点击时画个点,但你没法在鼠标或键盘事件的响应方法中得到窗口的绘图上下文句柄(对winform,是Graphics参数,对于win32程序是WM_PAINT消息里的某个参数),于是,你只好记下来“现在有个家伙点了鼠标了,某某地方应该有个点!”,然后调用Invalidate()方法,这个方法会强制系统向窗口程序发重绘消息,然后,你事先准备好的OnPaint方法被调用,在这个方法里,你有机会得到绘图句柄了,于是你检查之前有没有记录过要在某个地方画点的,并在这个地方画个点。

有点像MVC的意思,哈?

但在html5的canvas中,我发现浏览器是会帮canvas保存图形的,无论是被其他窗口盖到,切到后台,都没问题,只要一露出到屏幕上,原来的图形就还是在那里。这表示只要你并不想做动画效果,用canvas写图形程序要比windows程序原理更简单一些:你只要在合适的时候(鼠标点击、键盘事件等)向canvas上画图就是了,画上的东西就会总是在那里。绘图上下文context也不会消失掉,我把它在一开始时做为构造方法的参数传入,并保存为类成员,随时用随时取。

唯一要注意的,是要快点画完,别占太长时间。

滚屏后座标的问题

从网上看到的代码都是用e.pageXY来得到位置的。这个位置是鼠标事件在整个文档中的绝对位置。也就是说,滚屏不会影响这个值。

只不过我用了getBoundingClientRect这个方法来取得canvas对应的box座标,用于把全局座标转换到canvas内的座标。而这个方法取得的座标是相对于浏览窗口的,而不是相对于整个文档的。这就与e.PageXY对不上了。

所以,这里只好用e.XY,工作得非常好。

支持Retina屏

一开始在一个旧笔记本上写的这个程序,运行得挺好,但放到MacBook Pro上一看,功能挺正常,但内容很模糊。

仲么办!

模糊的原理是canvas在浏览器中的大小是由style中的width与height来决定的,但其画布的大小是以canvas.width与height决定的。如果两者不一样大,就会进行拉伸缩放,把画布拉伸(或缩小)到style的大小。

在普通屏幕上,其style定义的像素大小与屏上的显示结果是一对一的,所以没问题。但在retina屏上,style的大小定义与屏幕上的像素大小是有个放大比例的(在MBP上,是2),也就是说,style定义的400px,显示时会用到800px个屏幕像素。但由于canvas里画布的大小是400px的,所以内容被拉伸,还自动消除了锯齿,看起来就很模糊。

所以,解决办法是就是:根据放大比例,把画布的大小设置为比外部大小更大的大小。

但是注意,鼠标器事件中的座标是按原点数值来提供的。比如说,你内部画布大小是800px, 但屏幕大小算成了400px, 当鼠标点击后,给的位置是(100,100),这个位置是按屏幕点数来计算的,要在画布中计算其对应的点,应该把这个值乘以那个放大系数才对。

可注意一下程序中的getPointOnCanvas函数。

源代码在: https://github.com/haoxiaobo/SudoJS

用html5 canvas和JS写个数独游戏的更多相关文章

  1. 基于html5 canvas和js实现的水果忍者网页版

    今天爱编程小编给大家分享一款基于html5 canvas和js实现的水果忍者网页版. <水果忍者>是一款非常受喜欢的手机游戏,刚看到新闻说<水果忍者>四周年新版要上线了.网页版 ...

  2. HTML5 Canvas核心技术:图形、动画与游戏开发 PDF扫描版​

    HTML5 Canvas核心技术:图形.动画与游戏开发 内容简介: <HTML5 Canvas核心技术:图形.动画与游戏开发>中,畅销书作家David Geary(基瑞)先生以实用的范例程 ...

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

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

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

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

  5. canvas原生js写的贪吃蛇

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. html5+Canvas实现酷炫的小游戏

    最近除了做业务,也在尝试学习h5和移动端,在这个过程中,学到了很多,利用h5和canvas做了一个爱心鱼的小游戏.点这里去玩一下 PS: 貌似有点闪屏,亲测多刷新两下就好了==.代码在本地跑都不会闪, ...

  7. HTML5 Canvas核心技术—图形、动画与游戏开发.pdf1

    canvas元素可以说是HTML5元素中功能最强大的一个,它真正的能力是通过Canvas的context对象(绘图上下文)表现出来的 fillText()方法使用fillStyle属性来填充文本中的字 ...

  8. HTML5 Canvas核心技术—图形、动画与游戏开发.pdf7

    性能 运行putImageData()比drawImage()慢,同等条件下优先考虑drawImage() 操作图像数据需要遍历大量数据,应该注意几点: 1)避免在循环体中直接访问对象属性,应当保存在 ...

  9. HTML5 Canvas核心技术—图形、动画与游戏开发.pdf6

    操作图像的像素:getImageData() putImageData() ImageData对象 调用getImageData()方法实际是获取了一个指向ImageData对象的引用,返回的对象包含 ...

随机推荐

  1. Dynamics XRM Tools 2015 2016

    Download Link: Dynamics XRM Tools 2015/2016 Overview Dynamics XRM Tools brings you a quality range o ...

  2. cocos2dx骨骼动画Armature源码分析(一)

    源码分析一body { font-family: Helvetica, arial, sans-serif; font-size: 14px; line-height: 1.6; padding-to ...

  3. iOS真机测试碰到错误linker command failed with exit code 1 (use -v to see invocation)

    在模拟器上运行正常,但是在模拟器上就会报错,这是因为xocde7之后增加了一个bitcode,bitcode是被编译程序的一种中间形式的代码.包含bitcode配置的程序将会在App store上被编 ...

  4. JavaScript的个人学习随手记(一)

    JavaScript 简介  要学习的人可以到W3School http://www.w3school.com.cn/b.asp JavaScript 是世界上最流行的编程语言. 这门语言可用于 HT ...

  5. SqlServer--模糊查询-通配符

    查询所有姓张的同学Select * from student where left(sName,1)='张'   看上去很美,如果改成查询名字中带亮的学生怎么做?换一种做法 like  Select  ...

  6. .NET Framework各版本比较

    (1)本文比较了.NET Framework多个版本之间的区别,方便各位选择和切换.NET Framework. 版本号 发布日期 Visual Studio的版本 Windows上的默认情况 CLR ...

  7. SQL Server 2008 R2 升级到 Service Pack 3后Report Builder启动不了

    一同事将测试服务器从SQL Server 2008 R2 SP2升级到了SQL Server 2008 R2 SP3后发现Report Service的报表编辑时启动不了Report Builder, ...

  8. 《java JDK7 学习笔记》之对象封装

    1.构造函数实现对象初始化流程的封装.方法封装了操作对象的流程.java中还可以使用private封装对象私有数据成员.封装的目的主要就是隐藏对象细节,将对象当做黑箱子进行操作. 2.在java命名规 ...

  9. Linux 多线程可重入函数

    Reentrant和Thread-safe 在单线程程序中,整个程序都是顺序执行的,一个函数在同一时刻只能被一个函数调用,但在多线程中,由于并发性,一个函数可能同时被多个函数调用,此时这个函数就成了临 ...

  10. shell统计指定范围内的所有质数以及它们的和

    #!bin/bash a= $) ;do n= $x);do ];then n=$[$n+] fi done ];then { echo -n -e "$x\t" sum=$[$s ...