资讯专栏INFORMATION COLUMN

Vue+Webpack 实战 实现小游戏:2048

kyanag / 1053人阅读

摘要:前言最近学习和,刚好搞个小游戏练练手。当向下运动时,我们先将利用算法将想象中的方阵顺时针旋转一次,然后可以用向左运动处理的方法合并移动方格,完毕后再顺时针旋转次,或者逆时针旋转次还原即可。

前言

最近学习Vue和webpack,刚好搞个小游戏练练手。
2048游戏规则:

每次可以选择上下左右其中一个方向去滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢外,系统也会在空白的地方乱数出现一个数字方块,相同数字的方块在靠拢、相撞时会相加。不断的叠加最终拼凑出2048这个数字就算成功。

当然有些细微的合并规则,比如:
当向左滑动时,某列2 2 2 2 合并成 4 4 0 0 而非 8 0 0 0
也就是说,同列的某个数字最多只被合并一次。
在线挑战一把?
(瞎折腾一阵后发现移动端无法正常显示了,赶紧调试去)
http://www.ccc5.cc/2048/
移动端扫下面的二维码即可(微信会转码,请点击扫描后底部的‘访问原网页’)

思路

4x4的方格,用一个16个成员的数组表示。当某个方格没有数字的时候用""表示;

创建Vue的模板,绑定数据,处理数据与相关class的关系;

把数组当作一个4x4的矩阵,专注数据方面的处理,Dom方面的就交给vue更新

模板

其中getclassgetposition为自定义指令:

getclass根据当前框数字设置不同的class

getposition根据当前框的索引位置,设置css样式的topleft

关键实现 初始化数据

初始化一个长度为16的数组,然后随机选两个地方填入2或者4。

这里有必要说明下,在segmentfault看到很多人洗牌算法习惯这么写:

var arr = arr.sort(_=> {
    return Math.random() - 0.5
});

但是经过很多人的测试,这样洗牌其实是不太乱的,具体参考
数组的完全随机排列:https://www.h5jun.com/post/ar...
如何测试洗牌程序:http://coolshell.cn/articles/...

继续回到主题,数据初始化完成之后,添加两个自定义指令,功能前面已经讲过了,实现也很简单,
方格里面数字不同,对应的class不一样,我这里定义的规则是
数字2对应.s2
数字4对应.s4
...

事件处理

监听4个方向键和移动端的滑动事件,在ready环节处理

    ready: function () {
        document.addEventListener("keyup", this.keyDown);
        document.querySelector("#app ul").addEventListener("touchstart", this.touchStart);
        document.querySelector("#app ul").addEventListener("touchend", this.touchEnd);
        //document上获取touchmove事件 如果是由.box触发的 则禁止屏幕滚动
        document.addEventListener("touchmove", e=>{
            e.target.classList.contains("box") && e.preventDefault();
        });
    },
    methods:{
        touchStart(e){
            //在start中记录开始触摸的点
            this.start["x"] = e.changedTouches[0].pageX;
            this.start["y"] = e.changedTouches[0].pageY;
        },
        touchEnd(e){
            //handle...
        },
        /*
        *方向键 事件处理
        */
        keyDown(e){
            //handle...
        }
    }    

我们将nums这个数组想象成一个4x4的方阵。

        2 2 2 2
        x x x x
        x x x x
        x x x x

向左合并的时候,以第一列来说,从左至右:

inxde=0位置的2在合并时是不需要动的,index=1位置的2和index=0位置的2数值相同,合并成4,放在index=0的位置,第一列变成4 "" 2 2

index=2位置的2,向左挪到index=1空出的位置,变成4 2 "" 2,同时,index=3位置的2一直向左运动,直到碰上index=1处的2,二者在这轮都没有过合并,所以这里可以合并为4 4 "" ""

从这里我们可以看出,向左运动时,最左的位置,也就是index%4 === 0的位置,是无需挪动的,其他位置,若有数字,其左侧有空位的话则向左挪动一位,其左侧有个与其相同的数字时,且二者在此轮中没有合并过,则二者合并,空出当前位:

2 2 2 2 => 4 4 "" ""

4 2 2 2 => 4 4 2 ""

"" 4 2 2=> 4 4 "" ""

2 2 4 2 => 4 4 2 ""

...

如果打算将向上,向右,向下都这么处理一遍并非不可以,但比较容易出错。我们既然都将nums想象成了一个4x4的方阵,那么何不将该方阵旋转一下呢。
向下运动时,我们先将nums利用算法将想象中的方阵顺时针旋转一次,然后可以用向左运动处理的方法合并、移动方格,完毕后再顺时针旋转3次,或者逆时针旋转1次还原即可。

旋转算法:


有了这个函数,我们就只要写向左运动的处理函数了

详细的方向转换及处理过程

当所有的16个方格都已经被填满,且横向与纵向都无法合并时,游戏结束

    isPass(){
            let isOver=true,hasPass=false,tmp = this.T(this.nums,1);
            this.nums.forEach((i,j)=>{
                if(this.nums[j-4] == i || this.nums[j+4] == i || tmp[j-4] == tmp[j] || tmp[j+4] == tmp[j]){
                    isOver = false;
                }
                if(i==2048){
                    hasPass = true;
                }
            });
            if(!this.blankIndex().length){
                isOver && alert("游戏结束!");
            };
        }

。。。。。。。。
如何才能PASS?你有本事可以玩到很恐怖的数字。具体能玩到多少需要用数学证明吧,已有知乎大神证明,估计在3884450左右。传送门https://www.zhihu.com/questio...

代码

奉上全部代码app.vue





index.html




    
    
    
    2048 Game
    


    
    

main.js

import Vue from "vue"
import App from "./app.vue"


new Vue({
  el: "body",
  components:{App}
});

webpack配置

const webpack = require("webpack");

module.exports = {
  entry: {
      app:["./app/main.js","webpack-hot-middleware/client","webpack/hot/dev-server"]
  },
  output: {
    path: __dirname + "/public",//打包后的文件存放的地方
    filename: "bundle.js",//打包后输出文件的文件名
    publicPath:"http://localhost:8080/"
  },
  module: {
    loaders: [
      {test: /.css$/, loader: "style!css"},
      {test: /.vue$/, loader: "vue"},
      {test: /.js$/,exclude:/node_modules|vue/dist|vue-router/|vue-loader/|vue-hot-reload-api// ,loader: "babel"}
    ]
  },
  vue:{
    loaders:{
      js:"babel"
    }
  },
  babel: {
    presets: ["es2015","stage-0"],
    plugins: ["transform-runtime"]
  },
  plugins:[
    new webpack.HotModuleReplacementPlugin()
  ],
  devServer: {
    contentBase: "./public",//本地服务器所加载的页面所在的目录
    colors: true,//终端中输出结果为彩色
    hot: true,
    inline: true//实时刷新
  },
  resolve: {
    extensions: ["", ".js", ".vue"]
  }    
}

css就不贴了,Github上托管了:https://github.com/Elity/2048...

很久没写这么长的文章了,累死。花了整整俩小时!!!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80054.html

相关文章

  • [ 逻辑锻炼] 用 JavaScript 做一个游戏 ——2048 (详解版)

    前言 这次使用了 vue 来编写 2048,主要目的是温习一下 vue。 但是好像没有用到太多 vue 的东西,==! 估计可能习惯了不用框架吧 之前由于时间关系没有对实现过程详细讲解,本次会详细讲解下比较绕的函数 由于篇幅问题简单的函数就不做详解了 代码地址: https://github.com/yhtx1997/S... 实现功能 数字合并 当前总分计算 没有可移动的数字时不进行任何...

    gxyz 评论0 收藏0
  • 7月份前端资源分享

    摘要:更多资源请文章转自月份前端资源分享的作用数组元素随机化排序算法实现学习笔记数组随机排序个变态题解析上个变态题解析下中的数字前端开发笔记本过目不忘正则表达式聊一聊前端存储那些事儿一键分享到各种写给刚入门的前端工程师的前后端交互指南物联网世界的 更多资源请Star:https://github.com/maidishike... 文章转自:https://github.com/jsfr...

    pingan8787 评论0 收藏0
  • [ 逻辑锻炼] 用 JavaScript 做一个游戏 ——2048 (初级版)

    摘要:前言前段时间发现网上有很多收费或公开课都有教用做小游戏的,然后自己就也想动手做一个,做这个小游戏主要是为了锻炼自己的逻辑能力,也算是对之前一些学习的总结吧注实现方法完全是自己边玩边想的,所有些乱还请见谅另外配色方案是在某个游戏截屏,然后用吸 前言 前段时间发现网上有很多收费或公开课都有教用 js 做 2048 小游戏的,然后自己就也想动手做一个,做这个小游戏主要是为了锻炼自己的逻辑能力...

    lidashuang 评论0 收藏0
  • 前端面试题总结(js、html、小程序、React、ES6、Vue、算法、全栈热门视频资源)

    摘要:并总结经典面试题集各种算法和插件前端视频源码资源于一身的文档,优化项目,在浏览器端的层面上提升速度,帮助初中级前端工程师快速搭建项目。 本文是关注微信小程序的开发和面试问题,由基础到困难循序渐进,适合面试和开发小程序。并总结vue React html css js 经典面试题 集各种算法和插件、前端视频源码资源于一身的文档,优化项目,在浏览器端的层面上提升速度,帮助初中级前端工程师快...

    pumpkin9 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<