拼图游戏逻辑分析和源码分享(复制黏贴到本地就能玩)

前言

最近看到一篇博客,实现了拼图游戏并分享了源码。我感觉很好玩,就拿来改了改,实现了一个自己的版本。核心逻辑没有变,主要是优化了样式和交互,增加了些游戏的趣味性。

原文代码实现是用原生 js 面向对象的方式写的,这让习惯了使用 vue 语法糖的我,再次感到了用原生 js 好麻烦。好在,最近也是在重温原生js,打算再把基础学扎实一点,所以我遵循了原作者,也先用原生 js 做优化,后面还是打算改写为 vue 版本,是为了可以打包为移动端的 App,这样就可以在手机上玩了,哈哈。想拼什么图,就拼什么图,完美。

参考博文

https://blog.csdn.net/dkm123456/article/details/111991734#comments_15924279

拼图逻辑分析

1、一张图分割成几块,怎么分割?

定义构造函数,初始化数据。

function Jigsaw(row,boxWidth){
  this.row=row;
  this.itemWidth= boxWidth/this.row;
  this.fragment=[];//拼图碎片的dom数组
  this.originalKeys=[];//拼图碎片的下标,记录最初的正确顺序,方便后面对照拼图是否正确完成。
  this.keys=[];//拼图碎片的下标,游戏开始时会被打乱顺序。
  this.len=this.row*this.row;
  this.init();
}

拼图的尺寸是固定的,难度系数,确定了一张图分割为横纵的多少块,这样每块的宽高也就可以计算了。

分割使用背景图 background 属性,定位呈现整张图的固定部分区域。

background-position 属性设置背景图像的起始位置。

以 900px 的拼图大小分割为 3*3 的拼图碎片为例

(x , y)

x 随着每次换行 归零

y 随着每次换行 自增

游戏初始化

  //初始化
  init:function(){
    var fragment=dom.createDocumentFragment();
    var url = imgView.src;
    for(var i=0;i<this.len;i++){
        var div=dom.createElement('div');  
        div.style.cssText=`
          background:url(${url}) no-repeat -${(i%this.row)*this.itemWidth}px -${Math.floor(i/this.row)*this.itemWidth}px;
          height:${this.itemWidth}px;
          width:${this.itemWidth}px;
        `;

        this.fragment.push(div);//每个拼图碎片,都对应唯一的keys[i] 和 originalKeys[i]
        this.keys.push(i);
        this.originalKeys.push(i);
        fragment.appendChild(div);
    }
    box.innerHTML="";
    box.appendChild(fragment);
  },

完整的拼图就是多个应用了背景图属性的 div 组合而成的。

2、随机位置实现

随机位置实现,首先要打乱拼图碎片的下标数组。

arrayObject.sort(sortby)

排序函数的巧妙使用,用来打乱拼图碎片的下标数组。

sort 一般用于给乱序的数组排序,这里反其道用之,给正序的数组打乱顺序。参数 a b是数组中的元素。新的排序 依据 排序函数的返回值 来决定 a 和 b 在数组中的前后位置。

this.keys.sort(function(a,b){

      console.log('a = '+a+' , b = '+b)

      //return a-b

      //return Math.random()>0.5?1:-1;

})

乱序

this.keys.sort(function(a,b){

      console.log("a = "+a+' , b = '+b)

      return Math.random()>0.5?1:-1;

})

经测试,这里 sort()不传参数 a,b 也是可以的,应该是sort()方法在源码实现时,做了默认参数处理。

根据拼图碎片的随机下标,获取拼图碎片的随机 dom ,然后依次给拼图碎片应用绝对定位。

以 900px 的拼图大小分割为 3*3 的拼图碎片为例(原理同上使用背景图定位,所以后面代码实现也可以同上优化)

(x , y)

x 随着每次换行 归零

y 随着每次换行 自增

最外层相对定位,拼图碎片绝对定位。

this.item 是存储的拼图碎片 element 数组

也是在此时,给每个拼图碎片绑定鼠标事件。

start:function(){
    //随机位置
    this.keys.sort(function(a,b){
      return Math.random()>0.5?1:-1;
    })

    var keys = this.keys;//随机打乱的拼图碎片下标
    var colNum=0;
    var rowNum=0;

    box.innerHTML="";

    for(var i=0;i<keys.length;i++){
      if(i>0){
        if(i%this.row===0){
          rowNum++;
          colNum=0;
        }
      }
    
      var item = this.fragment[keys[i]];
          item.style.position='absolute';
          item.style.left=`${colNum++*this.itemWidth}px`;
          item.style.top=`${rowNum*this.itemWidth}px`;
          item.pos=i;//pos:item数组元素在 keys 数组中对应的下标 index
          item.key=keys[i];//key::item数组元素在 keys 数组中对应的值
      
      th
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Irene1991

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值