分享一个原创的经典拼图游戏(JS版)
刚刚昨天手头没啥活,闲来无事,突然想到用JS做个拼图游戏玩玩。于是说做就做,开始动手了。
先来看一下游戏的预览图:
这个拼图游戏大家都懂的,规则不介绍了。
游戏用的图片是一张300*300的完整图片,界面中3*3的九个格子,是九个100*100的DIV,九个DIV使用的背景都是同一张图片,利用CSS背景位置偏移,拼出一张完整的图片。
游戏支持鼠标点击与方向键移动两种方式。
下面简单介绍一下代码:
数据存储
1 squareds = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [-1, -1, 0]]; 2 space = {row: 3, cell: 2};
squareds数组,记录的是九宫格中每个格子当前是哪一块编号,最后一行的两个-1是不可用空位,0表示是暂存位,游戏就是利用这一个空位来实现完成拼图的。
space数组,就是记录游戏过程中,当前编号为0的这个空位在哪一行、哪一列。
游戏初始化
开始一个新局,首先要将九个格子的顺序随机打乱,我利用的是一步一步随机移位的方式,打乱顺序的。其实就是一个拼图的反过程。即初始是完整的状态,如图:
第一步:在空位(0)的周围随机找一个可移动格子,第一步只有9这个格子,移动9到0的位置,变成如下形式:
第二步0的周围有3个可移动的位置,分别是6、8、9,随机取一个位置,如随机到的是6或8,交换6或8和0的位置,变成如下图的形式:
或
这里要说明的是,程序里判断了移位是否与上一步形成往返,如果是往返的,则丢弃重新随机,第二步如果随机到的是9,跟上一步就形成往返了,要丢弃,重来。我这里设定的是这样随机移动25步。
随机取移动块的算法,是找出空格四周可被移动的块,记录到availableCoords数组中,最后随机在数组中取一个,作为这一步要打乱的格子。代码如下:
1 var randomAround = function(){ 2 var u = {row: space.row - 1, cell : space.cell}, 3 d = {row: space.row + 1, cell: space.cell}, 4 l = {row: space.row, cell: space.cell - 1}, 5 r = {row: space.row, cell: space.cell + 1}; 6 var availableCoords = []; 7 var isAvailable = function(coord){ 8 var r = coord.row >= 0 && coord.row <= 2 && coord.cell >= 0 && coord.cell <= 2; 9 10 if(!r) 11 r = coord.row == 3 && coord.cell == 2; 12 return r; 13 }; 14 15 isAvailable(u) && availableCoords.push(u); 16 isAvailable(d) && availableCoords.push(d); 17 isAvailable(l) && availableCoords.push(l); 18 isAvailable(r) && availableCoords.push(r); 19 20 return availableCoords[Math.floor(Math.random() * availableCoords.length)]; 21 };
这样经过25步以后,空位(0)这个格子可能不是在初始位置,不太美观,又经过以下代码,将空位(0)移动到了初始位置:
1 var lastStep = path[path.length - 1].from, 2 coord = null; 3 //将空格移到所在行的末尾。 4 for(var i = lastStep.cell + 1; i < 3; i++){ 5 coord = {row: lastStep.row, cell: i}; 6 path.push({from: coord, to:{row: space.row, cell: space.cell}, num: squareds[coord.row][coord.cell]}); 7 moveCoord(coord); 8 } 9 10 //将空格移到初始位置。 11 lastStep = coord || lastStep; 12 for(var i = lastStep.row + 1; i < 4; i++){ 13 coord = {row: i, cell: lastStep.cell}; 14 path.push({from: coord, to:{row: space.row, cell: space.cell}, num: squareds[coord.row][coord.cell]}); 15 moveCoord(coord); 16 }
这里为了展现一个打乱时的动画效果,先用一个path数组记录了打乱步骤要移动的格子,打乱步骤计算完成后,再按照path数组记录的步骤,一步一步移动。你要是记得住打乱时的步骤,反过来移动就是游戏的解了 :)
游戏用到的图片预置在images文件夹中,在初始化JS对象时,传入图片名称。
1 $(function(){ 2 var jigsaw = lhm.jigsaw.getInstance(); 3 jigsaw.init('p-2.jpg'); //初始化时传入预置在images文件夹中的图片名称 4 });
其余代码不再详述,代码也比较简单。附上源码下载地址,有兴趣的自己研究。