手机版

jQuery编译网页版2048游戏

时间:2021-09-06 来源:互联网 编辑:宝哥软件园 浏览:

概述

看了一个实现网页版2048迷你游戏的视频,发现玩以前喜欢的迷你游戏很有意思,自己也尝试过,真的验证了这句话——不要以为你想的就是你想的,但是我觉得看视频的时候可以理解,可以写,但是实现的时候会遇到各种问题。比如在判断游戏是否结束的最后,我写的句子语法是正确的,但是就是不执行。最后,通过对视频源代码的分析和比较,发现原作者编写的setTimeout定时器有额外的意义。本来我以为是一个简单的延时动画,其实他是在等待另一个功能的执行。-_-||。最后,我很高兴能写出来,并且改进了源代码中的一些不足。

这个博客不是详细的讲解,而是对功能的大概介绍,在实现的详细注释中有说明。网上的源代码有点乱。如果你想看一个工整的源代码或者视频,可以用QQ联系我(免费)(找个伙伴一起学)

思考

这个小游戏可以抽象成三层(我觉得可以更好理解)

底层是基本样式(可见)

中间层最重要,是一个4x4的二维数组。我们都在游戏中对这个二维数组进行操作(不可见)

顶层也是一个4x4的二维数组,只根据第二层数组的每个数字显示样式(可见)

我们通过底层显示最基本的16个方块,通过键盘的按键或者手指在屏幕上的滑动来操作中间层的数组,最后通过顶层显示数字

基本结构和风格

基本结构和风格都挺简单的,直接看代码

结构:

Div id=' test 2048 ' Div id=' header ' h 12048/h1a href=' JavaScript 3360 newgame()'开始新游戏/a p评分:span id=' score ' 0/span/p/Div id=' container ' Div class=' cell ' id=' cell-0-0 '/Div Div class=' cell ' id=' cell-0-1 '/Div class=' cell ' id=' cell-0-2 '/Div Div class=' cell ' id=' cell '

* { margin : 0;padd : 0;} # test 2048 { font-family : Arial;margin: 0 auto文本对齐:中心;} #页眉{ margin: 20px} # header a { font-family : Arial;文本装饰:无;display:块;color:白色;margin: 20px自动;宽度: 125 px;height: 35px文本对齐:中心;线高: 40px;背景-color : # 8f 7a 66;border-radius : 10px;font-size : 15px;} # header p { font-family : Arial;font-size : 20px;} #容器{ width: 460px高度: 460 px;背景-color : # bb ada0;margin: 0 autoborder-radius : 10px;相对位置:padding: 20px}.单元格{ width: 100px高度: 100像素;border-radius : 6px;背景-color : # CCC 0 B3;绝对位置:}从CSS样式可以看出,我们没有设置每个网格的位置,因为如果用CSS为每个网格设置样式的代码太多,并且它们的位置有一定的规则,我们可以使用js循环来完成每个网格样式的设置。

代码:

//初始化棋盘函数initialize(){ for(var I=0;i4;I){ for(var j=0;j4;J ){ //设置棋盘var everyCell的位置=$(' # cell-' I '-' j);everycell . CSS({ top : getpos(I),left : getpos(j)});} } }//get position函数get pos(num){返回20 num * 120}这样我们的一楼就可以了

效果:

现在构造第二层,即构建一个4x4的值全部为0的数组,由于在构造第二层时,有两层循环,所以我们可以在构造第一层时也能构造第二层

第三层是用射流研究…生成16个格子,它和第一层的16个格子一一对应

代码:

//数字格函数numFormat(){ for(var I=0;i4;I){ for(var j=0;j4;j ){ $('#container ').追加(' div class=' number ' id=' number-' I '-' j ' '/div))//设置数字格的位置,样式var EveryNumber=$(' # number-' I '-' j);如果(棋盘[I][j]==0){ everynumber。CSS({ width : ' 0px ',height:'opx ',top:getPos(i) 50,left : getpos(j)50 })else { every number。CSS({ width 3360 ' 100px ',height:'100px ',top 3360 getpos(I),left :0everyNumber.text(棋盘[I][j]);} } }}//获取相应数字的背景颜色函数getBackgroundColor(number){ switch(number){ case 2: return ' # eee 4 da ';打破;案例4:return ' # ede0c8打破;案例8:return ' # f2b179打破;案例16:return ' # f59563打破;案例32:return ' # f67c5f打破;案例64:return ' # f65e3b打破;案例128:return ' # edcf72打破;案例256:return ' # edcc61打破;案例512:return ' # 9c0打破;案例1024:return ' # 33b5e5打破;案例2048:return ' # 09c打破;案例4096:return ' # a6c打破;案例8192:return ' # 93c打破;}}//设置相应数字的文字颜色函数GetColor(number){ if(number=4){ return ' # 776 e65 ' }返回白色';}初始化

在每次游戏重新开始时,都会在随机的位置出现两个随机的数字,我们写一个在随机位置出现一个随机数的函数,只要调用两次就可以实现了

代码:

//随机的在一个位置上产生一个数字函数randomNum(){ //随机产生一个坐标值var randomX=数学。地板(数学。random()* 4);var randomY=数学。地板(数学。random()* 4);//随机产生一个数字(2或4)var randomValue=math。随机()0.5?2 : 4;//在数字格不为0的地方生成一个随机数字while(true){ if(棋盘[randomX][randomY]==0){ break;} else { var randomX=math。地板(数学。random()* 4);var randomY=数学。地板(数学。random()* 4);} } //将随机产生的数字显示在随机的位置上棋盘[randomX][randomY]=randomValue;//动画randomNumAnimate(randomX、randomY、randomValue);}//随机产生数字的动画函数randomNumAnimate(randomX,randomY,randomValue){ var randomnum=$(' # number-' randomX '-' randomY);随机数字。CSS({底色:获取底色(随机值),颜色:获取颜色(随机值),}).文本(随机值)。动画({ width:'100px ',height:'100px ',top:getPos(randomX),left:getPos(randomY) },50);}基本操作

我们通过转换循环,来根据用户不同的输入进行不同的操作

代码:

//获取键盘事件,检测不同按键,执行不同操作$(文档)。按键(功能(事件){开关(事件。键码){case373360//left if(可以向左移动(棋盘)){//如果可以向左移动();//向左移动settimeout(function(){ random num());},200);//随机生成一个数字} break关于案例38://if(canMoveUp(棋盘)){ //如果可以MoveUp上移();//上移settimeout(function(){ random num();},200);//随机生成一个数字} break案例39://右if(可以右移(棋盘)){//如果可以右移();//向右移动settimeout(function(){ random num());},200);//随机生成一个数字} breakCase 40://Down if(可以下移(棋盘)){//如果可以下移就下移();//下移settimeout(function(){ random num());},200);//随机生成一个数字} breakdefault: break}});由于数字网格的移动方式只有左、上、右、下,而且都是相似的,所以以左移动为例。

要向左移动,首先需要判断它是否可以向左移动。有两种情况它可以向左移动

第一种类型:当前网格的左网格为空,即值为0

第二:当前网格的值与左网格的值相同

因为向左移动,所以第一列的网格不能向左移动,所以不需要判断

代码:

//判断函数是否可以左移(棋盘){ for(var I=0;i4;I){ for(var j=1;j4;j ){ if(棋盘[i][j]!=0){ //如果这个数字单元格的左边数字单元格为空或等于它,则可以向左移动If(棋盘[I] [j-1]==0 | |棋盘[I] [j]==棋盘[I][j-1]){ return true;} } }返回false}判断是否可以向左移动后,还要移动移动网格。这里需要特别注意往哪个方向走,首先要判断往哪个方向出发。

代码:

//move函数MoveLeft(){ for(var I=0;i4;I){ for(var j=1;j4;j ){ if(棋盘[i][j]!=0){ for(var k=0;kj;k ){ if(棋盘[I][k]==0 nomidlenumrow(I,k,j,棋盘)){ moveAnimation(i,j,I,k);棋盘[i][k]=棋盘[I][j];棋盘[I][j]=0;}else if(棋盘[i][k]==棋盘[I][j]nomidlenumrow(I,k,j,棋盘)!has conflict[I][k]){ move animation(I,j,I,k);棋盘[i][k]=棋盘[I][j];棋盘[I][j]=0;} } } } } }//刷新时间设置为移动动画结束后更新数字网格,否则数字网格移动动画将被settimeout(function(){ numformat())中断;},200);}//判断中间数字单元格是否为0(行)函数nomidle numrow(row,col1,col2,checker board){ for(var I=col 1 1;icol2i ){ if(棋盘[row][i]!=0){返回false} }返回true}写好上下左右方向后,游戏的基本操作已经完成。

游戏评分并判断游戏结束

游戏的分数是每个相加数字的总和,所以我们可以在每个数字相加时更新分数

代码:

//更新得分得分=棋盘[k][j];updateScore(分数);//设置score函数updatescore (num) {$ ('# score ')。文本(数字);}判断游戏是否结束非常简单,可以用我们之前定义的方法来实现

代码:

//游戏结束时判断游戏是否结束功能(棋盘){if(!canMoveLeft(棋盘)!canMoveUp(棋盘)!canMoveRight(棋盘)!canMoveDown(棋盘)){ showGameOver();} }//show game end函数show game over () {$ ('# container ')。追加(' div id=' game over ' p final score/PS pan ' score '/spana href=' JavaScript 3360 resert();重启游戏/a/div ')}//重启游戏功能reset () {$ ('# gameover ')。移除();new game();}最终优化

1.游戏中会有一个动作,一个数字会累积很多次

在原来的游戏中,每个数字在每次操作中只能累加一次,所以我们定义的是一个假值的4x4数组,与中间层的数组一一对应,专门用来防止一个数字被多次累加。如果为假,可以累加,值可以改为假,否则不能累加。

2.结束无限循环

因为在设置随机数时使用了无限循环,但游戏结束后循环仍然存在,所以我们在无限循环中增加一个条件,如果游戏结束就跳出循环。

3.最终结束游戏提示不会执行

Case 37://Left if(可以向左移动(棋盘)){//如果可以向左移动();//向左移动settimeout(function(){当游戏结束时(棋盘)},300);//判断游戏是否结束。这里设置延迟是因为您必须等到数字随机生成。如果不添加//delay,就不会对最后一个判断执行settimeout(function(){ random num()),因为canMoveLeft(棋盘)为false。},200);//随机生成一个数字} break从代码中可以看出,判断游戏是否结束是在随机生成一个数字之前进行的,所以在判断游戏是否结束的时候总会有一个空的格子,所以在执行完代码之后就认为游戏结束了,但是当这个随机数生成之后,所有的格子都不能移动,当我们按下一个键的时候,if条件失效,判断游戏是否结束的功能就无法执行了。因此,我们应该为该功能设置一个计时器来判断游戏的结束,这样他就可以在随机生成一个数字后做出判断

4.它可以在移动端执行

因为原作者没有写移动终端的操作,所以我在网上找到的判断移动触屏手机滑动位置的代码,添加游戏事件后就可以执行了

//返回角度函数GetSlideAngle(dx,dy) { return Math.atan2(dy,dx) * 180/Math .PI;} //根据起点和终点返回方向1:向上,2:向下,3:向左,4:向右,0:未滑动函数GetSlideDirection(startX,startY,endX,endY){ var dy=startY-endY;var dx=ENDx-startX;var结果=0;//如果滑动距离太短if(数学。ABS(dx)2数学。ABS(dy)2){返回结果;} var angle=GetSlideAngle(dx,dy);if(angle=-45 angle 45){ result=4;} else if(angle=45 angle 135){ result=1;} else if(angle=-135 angle-45){ result=2;} else if((angle=135 angle=180)| |(angle=-180 angle-135)){ result=3;}返回结果;} //滑动处理var startX,startYdocument。addeventlistener(' touch start ',function(ev){ startX=ev。触摸[0].pageXstartY=ev。触摸[0].佩吉;},false);文件。addeventlistener(' touch end ',function (ev) { var endX,endYendX=ev.changedTouches[0]).pageXendY=ev.changedTouches[0].佩吉;var direction=GetSlideDirection(startX,startY,endX,endY);开关(方向){ case 0: //没滑动打破;案例1: if(canMoveUp(棋盘)){ //如果可以向上移动MoveUp();//向上移动setTimeout(函数(){ wheGameOver(棋盘)},300);//判断游戏是否结束setTimeout()函数(){ randomNum();},200);//随机产生一个数字}休息案例2: if(canMoveDown(棋盘)){ //如果可以向下移动moveDown();//向下移动setTimeout(函数(){ wheGameOver(棋盘)},300);//判断游戏是否结束setTimeout()函数(){ randomNum();},200);//随机产生一个数字}休息案例3: if(canMoveLeft(棋盘)){ //如果可以向左移动MoveLeft();//向左移动setTimeout(函数(){ wheGameOver(棋盘)},300);//判断游戏是否结束,这里设置延时是因为要等到随机产生数字后再进行判断,如果不加//延时,则最后一次的判断因为向左移动(棋盘)为错误的就不会再执行了setTimeout()函数(){ randomNum();},200);//随机产生一个数字}休息案例4: if(canMoveRight(棋盘)){ //如果可以向右移动向右移动();//向右移动setTimeout(函数(){ wheGameOver(棋盘)},300);//判断游戏是否结束setTimeout()函数(){ randomNum();},200);//随机产生一个数字} breakdefault: } },false);总结

总体来说这个游戏实现起来并不是太难,就是许多小的操作集合起来

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持我们!

版权声明:jQuery编译网页版2048游戏是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。