2048:數字移動的邏輯實現原理
前言:
本文主要講解2048的游戲實現原理,包括游戲數字移動部分的游戲邏輯實現。
本人目前還處於 Cocos Cerator 游戲引擎的學習階段,我做了個2048游戲的項目,看似簡單,但整個游戲開發也學習了很多。
在網上搜索關於2048游戲實現原理的文章中,很多是直接給出一個界面的當前狀態,觸摸操作后運行處理只得到一個終態,2048在手指滑動同時界面直接變化,用戶體驗感覺不佳。
那么,怎么能在處理數字移動合並的同時,將數字移動的部分記錄下來呢?
問題解決:
游戲的存儲方式是什么?
游戲在存儲結構上采用1維數組來實現數據存儲,為方便后面統一稱‘數字數組’。
並且,想要讓數字能夠體現移動效果,那么還需要有數據來存儲每個數字的移動,這里也用1維數組來存儲,其中,每個索引存儲的是數字數組對應索引上移動的格數,為方便統一稱為‘移動數組’。代碼如下:
//數字數組
let numArray = [
0, 2, 2, 0,
4, 0, 2, 2,
2, 2, 0, 4,
0, 4, 0, 2];
//移動數組
let moveArray = [
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0];
游戲的邏輯原理是什么?

數字數組如何移動和合並呢?
在方法里上下左右四個方向一樣操作,變換數組索引(起始位置和下一數字索引步長)就行。
比方說向右滑動,方向上是橫向的,分為4行處理,第一行起始點索引為0,步長為1;第二行起始點為4,步長為1。向上滑動,方向上是縱向的,分為4行處理,第一列起始點索引為0,步長為4。
例如向右滑動,分4行處理,從右邊到左邊依次判斷,每個數字先移動,右方有空位向右移動,直至不能移動位置后再合並:數字左方依次判斷,不為空並且相等就合並。
我寫了一個方法來處理數字數組,並按對應的起始點索引和步長處理數字移動,並修改傳入的移動數組。代碼如下:
move(ks: number, bc: number, numArray: number[], moveArray: number[]) {
let newNumArray = numArray.slice();
for (let i = 3; i >= 0; i--) {//為空跳過判斷
if (newNumArray[ks + i * bc] !== 0) {
for (let j = i; j < 4; j++) {//先移位,將移動的數值加入移動數組moveArray,更新數字數組numArray
if (j < 3 && newNumArray[ks + (j + 1) * bc] === 0) {
moveArray[ks + i * bc] += bc > 0 ? -1 : 1;
newNumArray[ks + (j + 1) * bc] = newNumArray[ks + j * bc];
newNumArray[ks + j * bc] = 0;
continue;
}
else if (j >= 3 || newNumArray[ks + (j + 1) * bc] !== 0) {//在角落或不能移位后就合並
for (let k = j; k > 0; k--) {
if (newNumArray[ks + (k - 1) * bc] !== 0) {//不為空判斷,為空跳過
if (newNumArray[ks + (k - 1) * bc] === newNumArray[ks + j * bc]) {//合並,數組更新,將移動的數值加入移動數組moveArray
newNumArray[ks + (k - 1) * bc] = 0;
newNumArray[ks + j * bc] = newNumArray[ks + j * bc] * 2;
moveArray[ks + (k - 1) * bc] += (bc > 0 ? -1 : 1) * (j - (k - 1));
}
break;
} else {
continue;
}
}
break;
}
}
}
}
}
例子:調用向右滑動
//數字數組
let numArray = [
0, 2, 2, 0,
4, 0, 2, 2,
2, 2, 0, 4,
0, 4, 0, 2];
//移動數組
let moveArray = [
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0];
cc.log('-傳入數字數組如下-');
for (let x = 0; x < 4; x++) {
cc.log(numArray[x * 4] + ' '
+ numArray[x * 4 + 1] + ' '
+ numArray[x * 4 + 2] + ' '
+ numArray[x * 4 + 3]);
}
//向右滑動
this.move(0, -1, numArray, moveArray);
this.move(4, -1, numArray, moveArray);
this.move(8, -1, numArray, moveArray);
this.move(12, -1, numArray, moveArray);
cc.log('-修改移動數組如下-');
for (let x = 0; x < 4; x++) {
cc.log(moveArray[x * 4] + ' '
+ moveArray[x * 4 + 1] + ' '
+ moveArray[x * 4 + 2] + ' '
+ moveArray[x * 4 + 3]);
}
結果如下:

最后,用移動數組將每個移動的數字節點先移動到對應的位置,再將同個位置下重復的數字節點一個消除一個數字加倍,就能得到移動的效果了。
游戲圖(動圖太麻煩):

