See the Pen
2048 by 喇賽人 (@weber87na )
on CodePen .
剛開工整個很沉悶 , 剛好看到 2048 這個遊戲 , 刷了一陣子覺得滿有趣的 , 就自己寫看看 , 想了半天也是挺燒腦的
其實最主要就一個規則 , 做出來後上下左右滑都可以套用 , 我是由往右滑開始思考
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 function right() { for (let x = 4 - 1; x >= 0; x--) { if (x === 3) { rightX3(0, x) rightX3(1, x) rightX3(2, x) rightX3(3, x) } if (x === 2) { rightX2(0, x) rightX2(1, x) rightX2(2, x) rightX2(3, x) } if (x === 1) { rightX1(0, x) rightX1(1, x) rightX1(2, x) rightX1(3, x) } if (x === 0) { rightX0(0, x) rightX0(1, x) rightX0(2, x) rightX0(3, x) } } }
第一格邏輯 首先當 x === 3
的狀況就單純移動方塊 , 關鍵就是套個 while 迴圈 , 當目前元素為 0 時就開始不斷移動元素 另外要防止這條橫線全為 0 的狀況 , 所以用 every
判斷如果全為 0 就直接 return
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function rightX3(y, x) { if (board[y].every(c => c === 0)) return let current = board[y][x] while (current === 0) { board[y][x] = board[y][x - 1] board[y][x - 1] = board[y][x - 2] board[y][x - 2] = board[y][x - 3] board[y][x - 3] = 0 //重新設定值 current = board[y][x] } }
第二格邏輯 接著 第二格邏輯
寫出來了就基本全寫出來 , 後面的格子就是看有幾格跑幾次進行微調 , code 應該可以更精簡不過太晚了 -. - 首先也是要防止全部為 0 的狀況 接著跑 3 次
迴圈動態的把元素也給往右邊移動 當目前元素為 0 的話單純的把元素往右推 , 當推到最後一個則設定為 0 , 如果你是最後一格這個動作就可以直接省略 然後當目前元素與右邊的元素相等時則需要把兩數加起來更新分數 , 因為加起來這個動作只會有一次 , 所以外圍設定 flag 來控制 , 如果已經加過了就不給加第二次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 function rightX2(y, x) { if (board[y].every(c => c === 0)) return let flag = false for (let counter = 0; counter < 3; counter++) { let current = board[y][x] //如果為 0 的情況 //則移動左邊兩個 if (current === 0) { board[y][x] = board[y][x - 1] board[y][x - 1] = board[y][x - 2] board[y][x - 2] = 0 } //如果目前這個跟最右邊那個數值相等的話 //則兩數相乘 //接著移動左邊兩個 if (flag === false) { let prev = board[y][x + 1] if (current === prev) { updateScore(current) board[y][x + 1] = current * 2 board[y][x] = board[y][x - 1] board[y][x - 1] = board[y][x - 2] board[y][x - 2] = 0 flag = true } } } }
gg 判斷 最後是判斷 gg 的規則 , 這個還挺簡單的 , 就是先看棋盤滿了沒board[y]
表示取得那一條 row 橫條
接著搭配 some
是否有任意元素為 0 有的話表示沒滿 , 反之就是滿了 接著以兩個元素為一組橫向掃瞄 , 接著直向掃描 , 當目前元素與後面那個元素相等時 , 表示還可以繼續玩 , 如果全掃描完了則表示已經結束了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 //是否棋盤全滿 function isFull() { let result = false for (let y = 0; y < 4; y++) { if (board[y].some(c => c === 0)) { return false } } return true } function isGoodGame() { if (isFull() === true) { for (let y = 0; y < 4; y++) { for (let x = 0; x < 4 - 1; x++) { let current = board[y][x] let next = board[y][x + 1] if (current === next) return false } } for (let x = 0; x < 4; x++) { for (let y = 0; y < 4 - 1; y++) { let current = board[y][x] let next = board[y + 1][x] if (current === next) return false } } return true } else { return false } }