亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

jQuery編寫網(wǎng)頁版2048小游戲

 更新時間:2017年01月06日 10:14:21   作者:老板丶魚丸粗面  
本文主要分享了jQuery編寫網(wǎng)頁版2048小游戲的示例代碼,具有一定的參考價值,下面跟著小編一起來看下吧

大致介紹

看了一個實現(xiàn)網(wǎng)頁版2048小游戲的視頻,覺得能做出自己以前喜歡玩的小游戲很有意思便自己動手試了試,真正的驗證了這句話-不要以為你以為的就是你以為的,看視頻時覺得看懂了,會寫了,但是自己實現(xiàn)起來會遇到各種問題。比如,在最后判斷游戲是否結(jié)束的時候,我寫的語句語法是對的,但就是不執(zhí)行。最后通過對視頻源碼的分析對比,發(fā)現(xiàn)原作者寫的一個setTimeout定時器有額外的意思,本來我以為它就是簡單的一個延時動畫,其實他是在等待另外一個函數(shù)執(zhí)行完畢。-_-||。最后還是很高興能寫出來,也改進了一些源代碼的不足。

這篇博客并不是詳細的講解,只是大致介紹函數(shù)的作用,其中實現(xiàn)的細節(jié)注釋中有解釋,網(wǎng)上的這個源碼有點亂,如果想看比較整齊的源碼或者視頻的可以QQ聯(lián)系我(免費)(找共同學(xué)習(xí)的伙伴)

思路

這個小游戲可以抽象化分為3層(我覺得這樣能更好理解)

◆最底下的一層是基本的樣式(可見的)

◆中間的層是最主要的,是一個4x4的二維數(shù)組,游戲中我們都是對這個二維數(shù)組進行操作(不可見的)

◆最上面的一層也是一個4x4的二維數(shù)組,它只是根據(jù)第二層數(shù)組的每個數(shù)顯示樣式(可見的)

我們通過最底下的一層顯示最基本的16個小方格,通過鍵盤的按鍵或者手指在屏幕的滑動來操作中間層的數(shù)組,最后在通過最上面的一層顯示出數(shù)字

基本結(jié)構(gòu)與樣式

基本的結(jié)構(gòu)和樣式都挺簡單,直接看代碼

結(jié)構(gòu):

<div id="test2048">
 <div id="header">
  <h1>2048</h1>
  <a href="javascript:newgame()" >開始新的游戲</a>
  <p>分數(shù):<span id="score">0</span></p>
 </div>
 <div id="container">
  <div class="cell" id="cell-0-0"></div>
  <div class="cell" id="cell-0-1"></div>
  <div class="cell" id="cell-0-2"></div>
  <div class="cell" id="cell-0-3"></div>
  <div class="cell" id="cell-1-0"></div>
  <div class="cell" id="cell-1-1"></div>
  <div class="cell" id="cell-1-2"></div>
  <div class="cell" id="cell-1-3"></div>
  <div class="cell" id="cell-2-0"></div>
  <div class="cell" id="cell-2-1"></div>
  <div class="cell" id="cell-2-2"></div>
  <div class="cell" id="cell-2-3"></div>
  <div class="cell" id="cell-3-0"></div>
  <div class="cell" id="cell-3-1"></div>
  <div class="cell" id="cell-3-2"></div>
  <div class="cell" id="cell-3-3"></div>
 </div>
 </div>

樣式:

*{
 margin: 0;
 padding: 0;
}
#test2048{
 font-family: Arial;
 margin: 0 auto;
 text-align: center;
}
#header{
 margin: 20px;
}
#header a{
 font-family: Arial;
 text-decoration: none;
 display: block;
 color: white;
 margin: 20px auto;
 width: 125px;
 height: 35px;
 text-align: center;
 line-height: 40px;
 background-color: #8f7a66;
 border-radius: 10px;
 font-size: 15px;
}
#header p{
 font-family: Arial;
 font-size: 20px;
}
#container{
 width: 460px;
 height: 460px;
 background-color: #bbada0;
 margin: 0 auto;
 border-radius: 10px;
 position: relative;
 padding: 20px;
}
.cell{
 width: 100px;
 height: 100px;
 border-radius: 6px;
 background-color: #ccc0b3;
 position: absolute;
}

從CSS樣式可以看出,我們并沒有對每個格子的位置進行設(shè)置,因為如果用CSS給每個格子設(shè)置樣式代碼量太大,而且他們的位置有一定的規(guī)律,所以我們可以用js循環(huán)來完成每個格子樣式的設(shè)置

代碼:

// 初始化棋盤格
function initialize(){
 for(var i=0;i<4;i++){
  for(var j=0;j<4;j++){
   // 設(shè)置棋盤格的位置
   var everyCell = $('#cell-'+ i +'-'+ j);
   everyCell.css({top:getPos(i),left:getPos(j)});
  }
 }
}
// 獲取位置
function getPos(num){
 return 20 + num*120;
}

這樣我們的第一層就好了

效果:

 

現(xiàn)在構(gòu)造第二層,即構(gòu)建一個4x4的值全部為0的數(shù)組,由于在構(gòu)造第二層時,有兩層循環(huán),所以我們可以在構(gòu)造第一層時也能構(gòu)造第二層

第三層是用js生成16個格子,它和第一層的16個格子一一對應(yīng)

代碼:

// 數(shù)字格
function numFormat(){
 for(var i=0;i<4;i++){
  for(var j=0;j<4;j++){
   $('#container').append('<div class="number" id="number-'+ i +'-'+ j +'"></div>')
   // 設(shè)置數(shù)字格的位置,樣式
   var everyNumber = $('#number-'+ i +'-'+ j);
   if(checkerboard[i][j] == 0){
    everyNumber.css({
     width:'0px',
     height:'opx',
     top:getPos(i) + 50,
     left:getPos(j) + 50
    })
   }else{
    everyNumber.css({
     width:'100px',
     height:'100px',
     top:getPos(i),
     left:getPos(j),
backgroundColor:getBackgroundColor(checkerboard[i][j]),
     color:getColor(checkerboard[i][j])
    });
    everyNumber.text(checkerboard[i][j]);
   }
  }
 }
}
// 獲取相應(yīng)數(shù)字的背景顏色
function getBackgroundColor(number){
 switch (number) {
  case 2:return "#eee4da";break;
  case 4:return "#ede0c8";break;
  case 8:return "#f2b179";break;
  case 16:return "#f59563";break;
  case 32:return "#f67c5f";break;
  case 64:return "#f65e3b";break;
  case 128:return "#edcf72";break;
  case 256:return "#edcc61";break;
  case 512:return "#9c0";break;
  case 1024:return "#33b5e5";break;
  case 2048:return "#09c";break;
  case 4096:return "#a6c";break;
  case 8192:return "#93c";break;
 }
}
// 設(shè)置相應(yīng)數(shù)字的文字顏色
function getColor(number){
 if (number <= 4) {
  return "#776e65"
 }
 return "white";
}

初始化

在每次游戲重新開始時,都會在隨機的位置出現(xiàn)兩個隨機的數(shù)字,我們寫一個在隨機位置出現(xiàn)一個隨機數(shù)的函數(shù),只要調(diào)用兩次就可以實現(xiàn)了

代碼:

// 隨機的在一個位置上產(chǎn)生一個數(shù)字
function randomNum(){
 // 隨機產(chǎn)生一個坐標值
 var randomX = Math.floor(Math.random() * 4);
 var randomY = Math.floor(Math.random() * 4);
 // 隨機產(chǎn)生一個數(shù)字(2或4)
 var randomValue = Math.random() > 0.5 ? 2 : 4;
 // 在數(shù)字格不為0的地方生成一個隨機數(shù)字
 while(true){
  if(checkerboard[randomX][randomY] == 0){
   break;
  }else{
   var randomX = Math.floor(Math.random() * 4);
   var randomY = Math.floor(Math.random() * 4);
  }
 }
 // 將隨機產(chǎn)生的數(shù)字顯示在隨機的位置上
 checkerboard[randomX][randomY] = randomValue;
 // 動畫
 randomNumAnimate(randomX,randomY,randomValue);
}
// 隨機產(chǎn)生數(shù)字的動畫
function randomNumAnimate(randomX,randomY,randomValue){
 var randomnum = $('#number-'+ randomX +'-'+ randomY);
 randomnum.css({
  backgroundColor:getBackgroundColor(randomValue),
  color:getColor(randomValue),
 })
    .text(randomValue)
    .animate({
     width:'100px',
     height:'100px',
     top:getPos(randomX),
     left:getPos(randomY)
    },50);
}

基本操作

我們通過switch循環(huán),來根據(jù)用戶不同的輸入進行不同的操作

代碼:

// 獲取鍵盤事件,檢測不同的按鍵進行不同的操作
$(document).keydown(function(event){
 switch(event.keyCode){
  case 37://左
   if(canMoveLeft(checkerboard)){
    // 如果可以向左移動
    MoveLeft();
    // 向左移動
    setTimeout(function(){
     randomNum();
    },200);
    // 隨機產(chǎn)生一個數(shù)字
   }
   break;
  case 38://上
   if(canMoveUp(checkerboard)){
    // 如果可以向上移動
    MoveUp();
    // 向上移動
    setTimeout(function(){
     randomNum();
    },200);
    // 隨機產(chǎn)生一個數(shù)字
   }
   break;
  case 39://右
   if(canMoveRight(checkerboard)){
    // 如果可以向右移動
    MoveRight();
    // 向右移動
    setTimeout(function(){
     randomNum();
    },200);
    // 隨機產(chǎn)生一個數(shù)字
   }
   break;
  case 40://下
   if(canMoveDown(checkerboard)){
    // 如果可以向下移動
    MoveDown();
    // 向下移動
    setTimeout(function(){
     randomNum();
    },200);
    // 隨機產(chǎn)生一個數(shù)字
   }
   break;
  default:
   break;
 }
});

由于數(shù)字格的移動只有左、上、右、下四種方式,并且他們都是大同小異的,所以就拿向左移動為例,

向左移動,我們首先需要判斷它是否能向左移動,能向左移動有兩種情況

第一種:當(dāng)前格子的左邊的格子是空的即值為0

第二種:當(dāng)前格子的值和左邊格子的值相同

由于向左移動,所以第一列的格子不可能向左移動,所以不需要判斷

代碼:

// 判斷是否可以向左移動
function canMoveLeft(checkerboard){
 for(var i=0;i<4;i++){
  for(var j=1;j<4;j++){
   if(checkerboard[i][j] != 0){
    // 如果這個數(shù)字格它左邊的數(shù)字格為空或者左邊的數(shù)字格和它相等,則可以向左移動
    if(checkerboard[i][j-1] == 0 || checkerboard[i][j] == checkerboard[i][j-1]){
     return true;
    }
   }
  }
 }
 return false;
}

判斷能否向左移動后,我們就要對可以移動的格子進行移動,這里需要特別注意,向哪個方向移動就要先從哪個方向開始判斷

代碼:

// 向左移動
function MoveLeft(){
 for(var i=0;i<4;i++){
  for(var j=1;j<4;j++){
   if(checkerboard[i][j] != 0){
    for(var k=0;k<j;k++){
     if(checkerboard[i][k] == 0 && noMiddleNumRow(i,k,j,checkerboard)){
      moveAnimation(i,j,i,k);
      checkerboard[i][k] = checkerboard[i][j];
      checkerboard[i][j] = 0;
     }else if(checkerboard[i][k] == checkerboard[i][j] && noMiddleNumRow(i,k,j,checkerboard) && !hasConflicted[i][k]){
      moveAnimation(i,j,i,k);
      checkerboard[i][k] += checkerboard[i][j];
      checkerboard[i][j] = 0;
     }
    }
   }
  }
 }
 // 設(shè)置刷新的時間是為了讓運動的動畫走完在進行更新數(shù)字格,否則數(shù)字格運動的動畫將會被打斷
 setTimeout(function(){
  numFormat();
 },200);
}
// 判斷中間的數(shù)字格是否為0(行)
function noMiddleNumRow(row,col1,col2,checkerboard){
 for(var i=col1+1;i<col2;i++){
  if(checkerboard[row][i] != 0){
   return false;
  }
 }
 return true;
}

將上、右、下四個方向?qū)懲暌院?,游戲基本的操作就已?jīng)完成了。

游戲分數(shù)和判斷游戲結(jié)束

游戲的分數(shù)是每個相加的數(shù)的和,所以我們在每個數(shù)相加的時候更新分數(shù)就可以了

代碼:

// 更新分數(shù)
score += checkerboard[k][j];
updateScore(score);
 // 設(shè)置分數(shù)
function updateScore(num){
 $('#score').text(num);
}

判斷游戲是否結(jié)束很簡單,用我們之前定義的方法就可以實現(xiàn)

代碼:

// 判斷游戲是否結(jié)束
function wheGameOver(checkerboard){
 if(!canMoveLeft(checkerboard) && !canMoveUp(checkerboard) && !canMoveRight(checkerboard) && !canMoveDown(checkerboard) ){
  showGameOver();
 }
}
// 顯示游戲結(jié)束
function showGameOver(){
 $('#container').append("<div id='gameover'><p>最終得分</p><span>"+ score +"</span><a href='javascript:resert();'>重新開始游戲</a></div> ")
}
// 重新開始游戲
function resert(){
 $('#gameover').remove();
 newgame();
}

最后優(yōu)化

1、游戲中會出現(xiàn)一次移動,一個數(shù)會被累加很多次

在原游戲中,每個數(shù)在每次操作中只能累加一次,所以我們在定義一個4x4的值為false的數(shù)組,與中間層的數(shù)組一一對應(yīng),專門用來防止一個數(shù)的多次累加,如果是false則可以累加,并將值改為false,否則不可以累加

2、結(jié)束死循環(huán)

由于在設(shè)置隨機數(shù)的時候用到了一個死循環(huán),但是在游戲結(jié)束后,該循環(huán)還在,所以我們在死循環(huán)中在添加一個條件,如果游戲結(jié)束就跳出循環(huán)

3、最后的結(jié)束游戲提示不執(zhí)行

case 37://左
   if(canMoveLeft(checkerboard)){
    // 如果可以向左移動
    MoveLeft();
    // 向左移動
    setTimeout(function(){
     wheGameOver(checkerboard)
    },300);
    // 判斷游戲是否結(jié)束,這里設(shè)置延時是因為要等到隨機產(chǎn)生數(shù)字后再進行判斷,如果不加
    // 延時,則最后一次的判斷因為canMoveLeft(checkerboard)為false就不會再執(zhí)行了
    setTimeout(function(){
     randomNum();
    },200);
    // 隨機產(chǎn)生一個數(shù)字
   }
   break;

從代碼中可以看出,判斷游戲是否結(jié)束是在隨機產(chǎn)生一個數(shù)字前執(zhí)行的,所以在判斷游戲結(jié)束時,總是有一個空的格子,所以代碼執(zhí)行后認為游戲沒有結(jié)束,但是當(dāng)這個隨機數(shù)字產(chǎn)生后,所有的格子不能移動,當(dāng)我們按鍵時,if條件不通過,判斷游戲是否結(jié)束的函數(shù)不能執(zhí)行。所以我們要給判斷游戲結(jié)束的函數(shù)設(shè)置定時器,讓他在隨機產(chǎn)生一個數(shù)字后再進行判斷

4、在移動端可以執(zhí)行

由于原作者沒有寫有關(guān)移動端的操作,所以我在網(wǎng)上找的判斷移動端觸屏手機滑動位置的代碼,加入了游戲的事件就可以執(zhí)行了

//返回角度 
   function GetSlideAngle(dx, dy) { 
    return Math.atan2(dy, dx) * 180 / Math.PI; 
   } 
   //根據(jù)起點和終點返回方向 1:向上,2:向下,3:向左,4:向右,0:未滑動 
   function GetSlideDirection(startX, startY, endX, endY) { 
    var dy = startY - endY; 
    var dx = endX - startX; 
    varresult = 0; 
    //如果滑動距離太短 
    if(Math.abs(dx) < 2 && Math.abs(dy) < 2) { 
     returnresult; 
    } 
    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; 
    } 
    return result; 
   } 
   //滑動處理 
   var startX, startY; 
   document.addEventListener('touchstart',function (ev) { 
    startX = ev.touches[0].pageX; 
    startY = ev.touches[0].pageY; 
   }, false); 
   document.addEventListener('touchend',function (ev) { 
    var endX, endY; 
    endX = ev.changedTouches[0].pageX; 
    endY = ev.changedTouches[0].pageY; 
    var direction = GetSlideDirection(startX, startY, endX, endY); 
    switch(direction) { 
     case 0: 
      //沒滑動 
      break; 
     case 1: 
      if(canMoveUp(checkerboard)){
      // 如果可以向上移動
      MoveUp();
      // 向上移動
      setTimeout(function(){
       wheGameOver(checkerboard)
      },300);
      // 判斷游戲是否結(jié)束
      setTimeout(function(){
       randomNum();
      },200);
      // 隨機產(chǎn)生一個數(shù)字
      } 
      break; 
     case 2: 
      if(canMoveDown(checkerboard)){
      // 如果可以向下移動
      MoveDown();
      // 向下移動
      setTimeout(function(){
       wheGameOver(checkerboard)
      },300);
      // 判斷游戲是否結(jié)束
      setTimeout(function(){
       randomNum();
      },200);
      // 隨機產(chǎn)生一個數(shù)字
      } 
      break; 
     case 3: 
      if(canMoveLeft(checkerboard)){
      // 如果可以向左移動
      MoveLeft();
      // 向左移動
      setTimeout(function(){
       wheGameOver(checkerboard)
      },300);
      // 判斷游戲是否結(jié)束,這里設(shè)置延時是因為要等到隨機產(chǎn)生數(shù)字后再進行判斷,如果不加
      // 延時,則最后一次的判斷因為canMoveLeft(checkerboard)為false就不會再執(zhí)行了
      setTimeout(function(){
       randomNum();
      },200);
      // 隨機產(chǎn)生一個數(shù)字
      } 
      break; 
     case 4: 
      if(canMoveRight(checkerboard)){
      // 如果可以向右移動
      MoveRight();
      // 向右移動
      setTimeout(function(){
       wheGameOver(checkerboard)
      },300);
      // 判斷游戲是否結(jié)束
      setTimeout(function(){
       randomNum();
      },200);
      // 隨機產(chǎn)生一個數(shù)字
      } 
      break; 
     default:    
    } 
   }, false);

總結(jié)

總體來說這個游戲?qū)崿F(xiàn)起來并不是太難,就是許多小的操作集合起來

以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!

相關(guān)文章

  • jQuery過濾選擇器用法分析

    jQuery過濾選擇器用法分析

    這篇文章主要介紹了jQuery過濾選擇器用法,實例分析了:first、:last、:odd、:even等等常用的過濾選擇器的使用技巧,非常具有實用價值,需要的朋友可以參考下
    2015-02-02
  • jquery實現(xiàn)拖拽小方塊效果

    jquery實現(xiàn)拖拽小方塊效果

    這篇文章主要為大家詳細介紹了jquery實現(xiàn)拖拽小方塊效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • jQuery實現(xiàn)form表單序列化轉(zhuǎn)換為json對象功能示例

    jQuery實現(xiàn)form表單序列化轉(zhuǎn)換為json對象功能示例

    這篇文章主要介紹了jQuery實現(xiàn)form表單序列化轉(zhuǎn)換為json對象功能,結(jié)合實例形式分析了表單數(shù)據(jù)傳輸中使用serializeJson進行序列化操作相關(guān)實現(xiàn)技巧,需要的朋友可以參考下
    2018-05-05
  • JQuery遍歷元素的后代和同胞實現(xiàn)方法

    JQuery遍歷元素的后代和同胞實現(xiàn)方法

    下面小編就為大家?guī)硪黄狫Query遍歷元素的后代和同胞實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • jquery 多行文本框(textarea)高度變化

    jquery 多行文本框(textarea)高度變化

    這篇文章介紹了多行文本框(textarea)高度變化的操作,有需要的朋友可以參考一下
    2013-07-07
  • 淺談jQuery中的checkbox問題

    淺談jQuery中的checkbox問題

    下面小編就為大家?guī)硪黄獪\談jQuery中的checkbox問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-08-08
  • jquery插件 autoComboBox 下拉框

    jquery插件 autoComboBox 下拉框

    大家在做省市區(qū)下拉框聯(lián)動,或者是產(chǎn)品分類聯(lián)動,或者是部門聯(lián)動等下拉框時怎么做? 是用ajaxpro.dll 還是jquery ajax呢
    2010-12-12
  • jQuery隱藏和顯示效果實現(xiàn)

    jQuery隱藏和顯示效果實現(xiàn)

    這篇文章主要介紹了jQuery隱藏和顯示效果實現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2016-04-04
  • jQuery實現(xiàn)倒計時按鈕功能代碼分享

    jQuery實現(xiàn)倒計時按鈕功能代碼分享

    這篇文章主要介紹了jQuery實現(xiàn)倒計時按鈕功能代碼分享,一般用在短信發(fā)送倒計時按鈕情景,本文給出了幾個例子,需要的朋友可以參考下
    2014-09-09
  • JQuery教學(xué)之性能優(yōu)化

    JQuery教學(xué)之性能優(yōu)化

    jQuery是一款非常優(yōu)秀的javascript框架,當(dāng)我們使用到j(luò)Query后就再也不想回到j(luò)avascript時冗長的代碼,那么jQuery的優(yōu)化就擺在了我們的面前。那么我們優(yōu)化JQuery應(yīng)該從那些方面入手呢?
    2014-05-05

最新評論