思路

  1. 决定内容区域的大小和图片种类数量

  • 图片应该放多少行,多少列。必须是偶数

  • 整个区域应该是在图片外多围上一圈,也就是行数和列数都应该比图片的多1

  • 放多少对图片,一对两张。注意对数不能超过所有图片总数

  2. 根据行列数来创建两个必要的数组

  • 一个数组保存所有小格子的行数和列数

         ♦ 应该使用一个二维数组

         ♦ 一维代表当前行数

         ♦ 二维当前当前列数

  • 一个数组保存按一对一对的形式来保存图片名

         ♦ 图片名以1,2,3...来命名,容易使用

         ♦ 数组中保存的值就是以[1,1,2,2....]这样保存图片名

  3. 开始渲染出整个游戏的页面

  • 打乱保存了图片名的数组

  • 遍历保存了所有小格子的数组,根据行数创建tr,根据列数创建td

  • 如果这个这个td不是第一行,最后一行,第一列,最后一列。因为最外围需要给后面连线留空位。

  • 根据打乱后的图片数组(以下称随机数组),往保存了小格子的数组(以下称为大数组)中添加图片名。

  • 创建图片对象,添加到td中,根据随机数组中的值来添加图片的src属性

  • 给图片对象中添加两个关键值。即对应的行数和列数。行数就是大数组的一维值,列数就是二维值。

  • 给所有的图片都注册一个点击事件

  4. 点击图片查找路径是否符合要求

  这是最里面最关键的部分,这里涉及到我们怎么来判断两张图是否能连通的问题。后面我们用一张图来看看连连看中怎样才能相连。

  • 点击的两张图片相邻,直接可消除。

  • 点击的两张图片不相邻。(以下简称两张图片分别为A点和B点)

         ♦ 获取A点和B点的十字线上的点的行列数。

         ♦ 遍历A点十字线上的点,当上面有一个点上面没有图片并且与A点之间没有任何一张图片,我们称这个点为有效点A(至于怎么判断有没有图片,只需要判断点的行列数在大数组中的值是否是0,非0即为有图片)

         ♦ 当存在有效点A,我们再拿到B点十字线和A点行数相等或者列数相等的两个点的坐标。

         ♦ 判断B点十字线上的获得到的两个点上是否有图片并且它们的坐标和B点之间是否有图片,没有图片的话我们称那个点为有效点B

         ♦ 判断有效点A和有效点B之间有没有图片,没有图片即为连通。即这两张图片可以消除。

         注意这四个点非常有用 ,而且能够连通的路线并不只有一条。

  5. 根据路径来连线

  这里需要配合CSS来连线,CSS中已经写好了线的类样式,后面只要找准方向,添加相应的类样式即可

  • 拿到所有能够连通的四个点。

  • 根据这四个点获取其中的最短路径的一个路线

         ♦ 如果路线只有一条,那么这一条就是最短路径

         ♦ 如果有一条路线中 有效点A和有效点B 重合了,那么这条路径就是最短路径。

         ♦ 如果是四个不一样的点,那么根据 A点和有效点A的距离 + B点和有效点B的距离 + 有效点A和有效点B之间的距离的和的大小来判断,最小的那一个即为最短路径。

  • 判断有效点上画线的方向

         ♦ 有效点A在A点右边,画线的方向就往左

         ♦ 有效点A在有效点B的下面,有效点A画线的方向就往上,有效点B画线的方向就往下。

         ♦ 有效点B在B点右边,画线的方向就往作

         ♦ 最后把方向拼接起来,格式化之后得到 topLeft,topRight,bottomLeft,bottomRight四个值。

         ♦ 这里注意下,如果4个点在一条线上就不用计算方向了

  • 判断普通的路径是水平方向还是垂直方向连。

  • 得到 A点到有效点A之间的所有路径和方向,B点到有效点B之间的所有路径和方向,有效点A到有效点B之间的所有路径和方向

  • 根据得到的路径和方向,来画线。

  我们用图片来看看怎样才算两张图连通

用JS写一个连连看小程序

关于连连看中两张图片能否连通

  这里标明了A点,有效点A,B点,有效点B,路径中有图片的地方表示路线不通。

  我们来看看关键代码

  1. 获取十字线。

JavaScript代码
  1. getPaths:function(element){  //获取点击图片的行数和列数  
  2.   //定义一个数组来存放十字线  
  3.   var paths = [];  
  4.   //遍历一共的行数  
  5.   for(var i=0;i<this.imgRow;i++){  
  6.       //列数不变,行数从0到最大  
  7.       paths.push({x:i,y:element.y});  
  8.   }  
  9.   //遍历一共的列数  
  10.   for(var j=0;j<this.imgCol;j++){  
  11.       //行数不变,列数从0到最大  
  12.       paths.push({x:element.x,y:j});  
  13.   }  
  14.   
  15.   return paths;  
  16. }  

  2. 判断两个点的连线上是否有图片

JavaScript代码
  1. checkTwoPath:function(target,current){  
  2. //如果是同一列  
  3. if(current.y == target.y){  
  4.     //遍历一行上不为点击的图片的行的所有十字线上的点  
  5.     for(var i=target.x;i<current.x?i<current.x:i>current.x;i<current.x?i++:i--){  
  6.         //如果含有图片 就返回false  
  7.         if(this.dimenArr[i][current.y]){  
  8.             return false;  
  9.         }  
  10.     }  
  11.   
  12. }else{  
  13.     //如果是同一行  
  14.     if(current.x == target.x){  
  15.         //遍历一列上不为点击的图片的列的所有十字线上的点  
  16.         for(var j=target.y;j<current.y?j<current.y:j>current.y;j<current.y?j++:j--){  
  17.             //如果含有图片 就返回false  
  18.             if(this.dimenArr[current.x][j]){  
  19.                 return false;  
  20.             }  
  21.         }  
  22.     }  
  23. }  
  24. return true;  

  3. 获取B点和有效点A同行同列的两个点。

JavaScript代码
  1. getSamePostions:function(target,current){  
  2. //定义一个数组存放同行同列的两个点的位置  
  3. var paths = [{x:0,y:0},{x:0,y:0}]  
  4. //遍历目标位置的十字线  
  5. for(var i=0;i<target.length;i++){  
  6.     //如果在同一行  
  7.     if(current.x == target[i].x){  
  8.         paths[0].x = target[i].x;  
  9.         paths[0].y = target[i].y;  
  10.     }  
  11.   
  12.     //如果在同一列  
  13.     if(current.y == target[i].y){  
  14.         paths[1].x = target[i].x;  
  15.         paths[1].y = target[i].y;  
  16.     }  
  17. }  
  18. return paths;  

  4. 获取最短路径。

JavaScript代码
  1. getShortPath:function(nearPath){  
  2. var flag = true;  
  3.   
  4. // 定义一个数组用来存放路径的长度  
  5. var pathLength = [];  
  6.   
  7. // 定义一个最短路径   
  8. var shortPath = null;  
  9.   
  10. // 如果只有一条路径  
  11. if(nearPath.length==1){  
  12.     // console.log(nearPath);  
  13.     shortPath = nearPath[0];  
  14.     // this.direction(nearPath[0]);  
  15. }else{  
  16.     // 遍历这个对象  
  17.     for (var i = 0; i < nearPath.length; i++) {  
  18.         // 如果两个交点重合的话,此时就是最短路径  
  19.         if(nearPath[i].crossA.x == nearPath[i].crossB.x && nearPath[i].crossA.y==nearPath[i].crossB.y){  
  20.             flag = false;  
  21.             shortPath = nearPath[i];  
  22.             break;  
  23.         }  
  24.     }  
  25.   
  26.     if(flag){  
  27.         for (var i = 0; i < nearPath.length; i++) {  
  28.             pathLength.push({'index':i,"value":this.getPathLength(nearPath[i].crossA,nearPath[i].A)+this.getPathLength(nearPath[i].crossB,nearPath[i].B)+this.getPathLength(nearPath[i].crossA,nearPath[i].crossB)});                      
  29.         }  
  30.   
  31.         // 升序排序得到最小值,拿到的值就是最短路径的索引  
  32.         pathLength.sort(function(obj1,obj2){  
  33.             return obj1.value>obj2.value ? 1 : -1;  
  34.         })  
  35.         // 获得到最短路径  
  36.         console.log("这是算出来的最短路径");  
  37.         shortPath = nearPath[pathLength[0].index];  
  38.     }  
  39.   
  40. }  
  41.   
  42. return shortPath;  

  5. 获取路径的长度值,以便比较出最短路径。

JavaScript代码
  1. getPathLength:function(currentCoords,targetCoords){  
  2.   
  3. // 如果x值坐标相等就获取y值的差值的绝对值,如果y值相等就获取x值差值的绝对值  
  4. if(currentCoords.x==targetCoords.x){  
  5.     return Math.abs(currentCoords.y-targetCoords.y-1);  
  6. }else if(currentCoords.y == targetCoords.y){  
  7.     return Math.abs(currentCoords.x-targetCoords.x-1);  
  8. }  

  关于代码中运行时控制台的值所代表的含义

用JS写一个连连看小程序

关于控制台中打印的值到底是什么

  1. 第一个console.log()打印出的数组代表中共有多少种连通方式,当前只有一种,存入的对象是 A点,有效点A,B点和有效点B

  2. 第二个console.log()打印出的对象中存入的是最短路径的四个点的坐标对象

  3. 第三个console.log()打印出的是存入的四个点的坐标对象和有效点A和有效点B的绘制线的方向

  4. 后面打印的就是路径坐标了。

  有兴趣的朋友可以自行下载看看代码,可能命名上由于词穷想不到比较好的名字,但是注释写的还比较全。

  代码保存在了github上,点击github跳转后下载即可。

  总结

  • 首先代码还有缺陷,没有判断所有的点都不能连通的情况。·

         ♦ 不过写起来的应该不难,我能想到的办法就是在每次开始之前,复制一份大数组,然后从中取出一个值,再获取到这个数组中和取出的值想同的这个值,然后让这两个值试着连通,当不能连通的时候,从这个数组中去除掉这两个元素。然后接着取值比较。最后赋值出的数组为空即代表所有的点不能连通。

  • 其实连线部分我总觉得做的复杂了,本来做到一半的时候想用canvas来画线,毕竟点的行列数都知道,计算坐标也比较容易。不过既然做了,就硬着头皮做下去了。

  文/Magician_Shiro

除非特别注明,鸡啄米文章均为原创
转载请标明本文地址:http://www.jizhuomi.com/software/653.html
2016年11月8日
作者:鸡啄米 分类:软件开发 浏览: 评论:0