這個游戲JS部分全都是用原生JS代碼寫的,加有少量的CSS3動畫,並簡單的兼容了一下移動端。
先看一下在線的demo:https://yuan-yiming.github.io/2048-online-game/
github地址:https://github.com/Yuan-Yiming/2048-online-game

====================================================================
下面簡單分析一下JS代碼:
1.游戲中包含的主要事件:
new game按鈕的click事件:點擊后重新開始一次新的游戲;
game over后重新開始按鈕的click事件:點擊后重新開始一次新的游戲;
桌面端鍵盤上的方向鍵keydown的事件:按下方向鍵后數字會向相應的方向移動;
移動端的touch事件:通過計算touchstart和touchend的坐標變化,判斷手指在移動端屏幕的滑動方向;
2.業務邏輯
2.1 重新開始一次游戲:
需要清空游戲盤,並且隨機給一個格子生成一個數字2,每次生成不同數字都會給格子配相應的背景顏色;
2.2 按下方向盤或滑動屏幕時格子移動情況(核心部分)
游戲面板有4 x 4的格子,遍歷每一行的每一個格子,若為空格則不作處理,非空格則要判斷其下一步(注意每次只判斷一步的動作,方法howToGo())的運動情況,即:
a:空格,不作處理
b:非空格,進一步判斷下一步動作,有3種情況:
b1:若需要移動的格子前面是沒有數字的空格,則格子往前移動一個,即將數字插入到前面格子內,原本格子中的數字銷毀,然后從b開始循環再次判斷;
b2:若需要移動的格子前面不是空格,且與前面格子包含的數字不相等,則格子無需移動,該格子運動判斷完畢,進行下一個格子的運動判斷;
b3:若需要移動的格子前面不是空格,且與前面格子包含的數字相等,則將前面格子內的數字 x 2,原本格子中的數字銷毀,該格子運動判斷完畢,進行下一個格子的運動判斷;
注意:由於是每次運動都是由運動方向的最前面格子開始運動的,即b2,b3兩種情況碰到前面有格子時,說明前面的格子已經完成運動,前面沒有空位了,所以當前格子運動完成,繼續移動后面的格子。
以下使用圖片來說明格子運動的情況:

上面有兩行格子,如果是向左運動,首先遍歷第1行,對1~4號格子依次判斷其運動情況,首先1號格子先運動,由於是1號格子靠邊,可認為其前面是包含不同數字的格子,運動情況為b2,無需運動;2號格子為空格,運動情況為a;3號格子前面為空格,首先運動情況為b1,運動后3號格子的數字插到2號格子,3號格子數字銷毀成為空格,然后需要對2號格子再次判斷,再進行一次運動,即b3,使得1號格子數字變成4,2號格子成為空格;后面4號格子為空格不作處理。遍歷第2行,對5~8號格子依次判斷其運動情況,5號格子與1號格子情況相同,6、7、8號格子為空格,無需處理。
向左運動后的格子:

如果是向右運動,遍歷第1行要從右邊開始,4~1號格子依次運動,首先4號格子空格無需處理;然后3號格子運動情況b1,向前移動一格,數字2插入到4號格子內;2號空格無需處理;1號空格先連續進行兩次b1運動,再進行一次b3運動,碰到4號格子內數字相同,最終使得4號格子內數字變成4。遍歷第2行,8~5號格子依次運動,8、7、6號為空格均無需處理,5號格子連續3次b1運動,使得8號格子內數字變成2。
向右運動后的格子:

向上或者向下運動同理。
=====================================================================
下面廢話不說,直接上代碼。
HTML代碼:index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <title>Play 2048 Game Online!</title> <link rel="stylesheet" type="text/css" href="desktop.css"> <link media="(max-width: 860px)" rel="stylesheet" type="text/css" href="mobile.css"> <link rel="icon" href="icon.png"> </head> <body> <!-- <div class="github"><a href="https://www.baidu.com"></a></div> --> <div class="wrapper"> <div class="header"> <div class="title"> <strong>2048</strong> </div> <div class="slogan"> <p>Play 2048 Game Online!</p> </div> <div class="score"> <span>Score</span><br><span class="number">0</span><span class="score-animation">+12</span> </div> <div class="best"> <span>Best</span><br><span class="number">1024</span><span class="best-animation">+12</span> </div> <div class="new-game"> <span>New Game</span> </div> </div> <div class="game-board"> <div class="grid grid-11 row1 col1"><span></span></div> <div class="grid grid-12 row1 col2"><span></span></div> <div class="grid grid-13 row1 col3"><span></span></div> <div class="grid grid-14 row1 col4"><span></span></div> <div class="grid grid-21 row2 col1"><span></span></div> <div class="grid grid-22 row2 col2"><span></span></div> <div class="grid grid-23 row2 col3"><span></span></div> <div class="grid grid-24 row2 col4"><span></span></div> <div class="grid grid-31 row3 col1"><span></span></div> <div class="grid grid-32 row3 col2"><span></span></div> <div class="grid grid-33 row3 col3"><span></span></div> <div class="grid grid-34 row3 col4"><span></span></div> <div class="grid grid-41 row4 col1"><span></span></div> <div class="grid grid-42 row4 col2"><span></span></div> <div class="grid grid-43 row4 col3"><span></span></div> <div class="grid grid-44 row4 col4"><span></span></div> </div> <div class="popup"> <div class="game-over"> <p>Game is over...</p> <p class="try-again">Try again?</p> </div> <div class="win"> <p>You win the game!! </p><p>Congratulation!!</p> <p class="try-again">Try again?</p> </div> </div> </div> <script type="text/javascript" src="2048.js"></script> </body> </html>
CSS桌面版代碼:desktop.css
* {
list-style: none;
color: #8f7a66;
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
background-color: #ffffe0;
}
.wrapper {
position: relative;
width: 400px;
height: 540px;
/*border: 1px solid red;*/
margin: 0 auto;
}
/*頭部*/
.header {
width: 400px;
height: 140px;
/*border: 1px solid green;*/
position: relative;
/*opacity: 0.4;*/
}
.title, .slogan, .score, .best, .new-game, .github>a {
position: absolute;
}
.title strong {
display: inline-block;
width: 260px;
height: 100px;
font-size: 78px;
line-height: 100px;
/*text-align: center;*/
padding: 0 5px;
/*border: 1px solid black;*/
}
.slogan {
padding: 0 5px;
top: 85px;
/*border: 1px solid black;*/
}
.github>a {
display: inline-block;
width: 50px;
height: 50px;
/*border: 1px solid red;*/
top: 8%;
right: 5%;
/*margin: 5px;*/
background: url("Git.png") no-repeat 0 0;
border-radius: 50%;
background-size: 100%;
}
.github>span>span {
display: inline-block;
width: 100px;
height: 16px;
line-height: 16px;
position: absolute;
bottom: -24px;
left: -25px;
text-align: center;
color: #2c2c2c;
}
/*分數*/
/* 分數動畫 */
.score-animation, .best-animation{
display: none;
position: absolute;
top: 25px;
left: 10px;
width: 65px;
height: 30px;
font-size: 24px;
font-weight: bold;
}
.score {
left: 220px;
}
.best {
left: 315px;
}
.score, .best {
position: absolute;
width: 85px;
height: 60px;
line-height: 28px;
top: 20px;
background-color: #bbada0;
}
.score span, .best span, .new-game span {
color: #ffffff;
}
.score, .best, .new-game, .game-board, .grid {
text-align: center;
border-radius: 5px;
}
.best .number, .score .number, .new-game {
font-size: 22px;
font-weight: bold;
}
.new-game {
width: 180px;
height: 40px;
line-height: 40px;
left: 220px;
top: 90px;
text-align: center;
background-color: #8e7963;
cursor: pointer;
}
.new-game:hover {
width: 182px;
height: 42px;
line-height: 42px;
left: 219px;
top: 89px;
font-size: 24px;
}
/*游戲主面板*/
.game-board {
width: 400px;
height: 400px;
padding: 5px 5px;
background-color: #bbada0;
/*opacity: 0.4;*/
}
.grid {
position: relative;
float: left;
width: 87.5px;
height: 87.5px;
line-height: 87.5px;
/*font-size: 48px;*/
font-weight: bold;
margin: 5px;
background-color: #b0c4de;
}
.game-board .grid span {
/*color: */
}
/*game over or win the game彈出頁面*/
.popup .game-over, .popup .win {
position: absolute;
left: 60px;
text-align: center;
width: 280px;
height: 160px;
border-radius: 5px;
/*border: 1px solid red;*/
opacity: 1.0;
}
.popup p {
color: #8f7a66;
}
.popup .game-over {
display: none;
top: 230px;
font-size: 36px;
font-weight: bold;
}
.popup .win {
display: none;
top: 220px;
font-size: 28px;
font-weight: bold;
}
p.try-again {
color: #fff;
font-size: 22px;
width: 150px;
height: 50px;
line-height: 50px;
border-radius: 5px;
margin: 0 auto;
background-color: #8f7a66;
cursor: pointer;
}
.header, .game-board {
/*opacity: 0.4;*/
}
.new-grid {
background-color: #b0c4de !important;
}
/* 生成新格子動畫 */
@keyframes tempgrid {
from {width: 45px; height: 45px; top: 24px;left: 24px; font-size: 18px; line-height: 45px;display: block;}
to {width: 87.5px; height: 87.5px; top: 0px;left: 0px; font-size: 48px; line-height: 87.5px;display: none;}
}
@-webkit-keyframes tempgrid {
from {width: 45px; height: 45px; top: 24px;left: 24px; font-size: 18px; line-height: 45px;display: block;}
to {width: 87.5px; height: 87.5px; top: 0px;left: 0px; font-size: 48px; line-height: 87.5px;display: none;}
}
@-moz-keyframes tempgrid {
from {width: 45px; height: 45px; top: 24px;left: 24px; font-size: 18px; line-height: 45px;display: block;}
to {width: 87.5px; height: 87.5px; top: 0px;left: 0px; font-size: 48px; line-height: 87.5px;display: none;}
}
.temp-grid {
animation: tempgrid 0.15s ease-in forwards;
-webkit-animation: tempgrid 0.15s ease-in forwards;
-ms-animation: tempgrid 0.15s ease-out forwards;
-moz-animation: tempgrid 0.15s ease-out forwards;
}
CSS移動端兼容代碼:mobile.css
body {
background-color: #fffadd;
}
.wrapper {
width: 100%;
/*height: 540px;*/
/*border: 1px solid red;*/
/*margin: 0 auto;*/
}
/*頭部*/
.header {
width: 100%;
/*height: 140px;*/
position: relative;
}
.title, .slogan, .score, .best, .new-game {
position: absolute;
float: left;
text-align: center;
}
.title, .slogan {
width: 100%;
}
.title strong {
display: inline-block;
width: 100%;
/*height: 260px;*/
font-size: 487%; /* 100% 16px */
/*line-height: 192%;*/
text-align: center;
/*padding: 0 5px;*/
/*border: 1px solid black;*/
}
.slogan {
/*margin-top: 10px;*/
top: 65%;
}
/* github */
/*.github>a {
top: 4%;
right: 6.25%;
}*/
/*分數*/
.score, .best, .new-game {
width: 25%;
/*border: 1px solid green;*/
}
/* 分數動畫 */
.score-animation, .best-animation{
display: none;
/*position: absolute;*/
top: 25px;
left: 10px;
width: 65px;
height: 30px;
font-size: 24px;
font-weight: bold;
}
.score, .best {
/*position: absolute;*/
line-height: 28px;
top: 90%;
background-color: #bbada0;
}
.score {
left: 47.5%;
}
.best {
left: 75%;
}
.new-game {
width: 45%;
height: 60px;
line-height: 60px;
left: 0;
top: 90%;
text-align: center;
background-color: #8e7963;
cursor: pointer;
/*padding-bottom: 2em;*/
font-size: 28px;
}
.new-game:hover {
width: 45%;
/*height: 42px;*/
/*line-height: 42px;*/
height: 60px;
line-height: 60px;
left: 0;
top: 90%;
/*line-height: 2e;*/
font-size: 28px;
}
.score span, .best span, .new-game span {
color: #ffffff;
}
.score, .best, .new-game, .game-board, .grid {
text-align: center;
border-radius: 5px;
}
.best .number, .score .number {
font-size: 22px;
font-weight: bold;
}
/*游戲主面板*/
.game-board {
position: absolute;
/*display: none;*/
width: 100%;
height: auto;
/*height: 400px;*/
/*padding: 10px 10px;*/
background-color: #bbada0;
/*opacity: 0.4;*/
top: 36%;
}
.grid {
/*position: relative;*/
float: left;
width: 22%;
/*height: */
/*padding-bottom: 21.95%;*/
/*height: 100%;*/
line-height: 80px;
/*font-size: 48px;*/
font-weight: bold;
/*padding-bottom: 410px;*/
padding: 1.5%;
background-color: #b0c4de;
}
/* 生成新格子動畫 */
@keyframes tempgrid {
from {width: 50%; height: 50%; top: 25%;left: 25%; font-size: 24px; line-height: 192%;display: block;}
to {width: 100%; height: 100%; top: 0px;left: 0px; font-size: 48px; line-height: 192%;display: none;}
}
@-webkit-keyframes tempgrid {
from {width: 50%; height: 50%; top: 25%;left: 25%; font-size: 24px; line-height: 192%;display: block;}
to {width: 100%; height: 100%; top: 0px;left: 0px; font-size: 48px; line-height: 192%;display: none;}
}
@-moz-keyframes tempgrid {
from {width: 50%; height: 50%; top: 25%;left: 25%; font-size: 24px; line-height: 192%;display: block;}
to {width: 100%; height: 100%; top: 0px;left: 0px; font-size: 48px; line-height: 192%;display: none;}
}
js代碼:2048.js
// 頁面加載時
window.onload = function () {
// var temp = tempGrid(2);
giveNumber(2);
newGameBotton();
getReady();
backgroundColorToNumber();
scaleWidth();
touch();
}
// 在移動端使得格子寬高比例1:1
function scaleWidth() {
// 獲取格子的寬度
var grid = document.getElementsByClassName("grid"),
width = window.getComputedStyle(grid[0], null)["width"];
// width = grid[0].style.width;
//給格子高度賦值
for (var i = 0; i < 16; i++) {
grid[i].style.height = width;
}
}
// 創建一個臨時的格子
function createTempGrid(num) {
var temp = document.createElement("div");
temp.innerHTML = "<span>" + num + "</span>";
temp.style.position = "absolute";
temp.style.backgroundColor = "#fff8dc";
temp.style.width = "87.5px";
temp.style.height = "87.5px";
temp.style.lineHeight = "87.5px";
temp.style.fontWeight = "bold";
temp.style.fontSize = "48px";
temp.style.borderRadius = "5px";
temp.style.top = "0";
temp.style.left = "0";
// temp.style.display = "none";
// console.log(temp);
temp.classList.add("temp-grid");
return temp;
};
// 刪除臨時格子
function deleteTempGrid() {
var temp = document.getElementsByClassName("temp-grid");
for (var i = 0; i < temp.length; i ++) {
temp[i].remove();
}
var newGrid = document.getElementsByClassName("new-grid");
// console.log(newGrid);
if (newGrid) {
// console.log(newGrid.length);
for (var i = 0; i < newGrid.length; i ++) {
newGrid[i].classList.remove("new-grid");
// console.log(newGrid.length);
}
}
}
// giveNumber:隨機生成一個空格子,每個空格子里面放一個數字num
function giveNumber(num) {
// console.log("give!!!!");
var x, y, newGrid, tempGrid;
tempGrid = createTempGrid(num);
while (true) {
// if (tempGrid && tempGrid.parentElement) {
// tempGrid.parentElement.removeChild(tempGrid);
// }
x = Math.floor(Math.random() * 4) + 1;
y = Math.floor(Math.random() * 4) + 1;
newGrid = document.getElementsByClassName("grid-" + x + y)[0];
// newGrid.style.backgroundColor = "#b0c4de";
if (newGrid.innerHTML == "<span></span>") {
newGrid.classList.add("new-grid");
newGrid.innerHTML = "<span>" + num + "</span>";
newGrid.appendChild(tempGrid);
break;
}
}
// return blankGrid;
}
// clearGrid:清空格子及分數歸零
function clearGrid() {
var grid = document.getElementsByClassName("grid"),
score = document.getElementsByClassName("score")[0].children[2];
score.innerText = "0";
for (var i = 0; i < grid.length; i ++) {
grid[i].innerHTML = "<span></span>";
// grid[i].style.backgroundColor = "#b0c4de";
}
backgroundColorToNumber();
}
// 重新開始一次游戲
function newGame() {
clearGrid();
giveNumber(2);
backgroundColorToNumber();
return true;
}
// 觸發新一次游戲的按鈕
function newGameBotton() {
var newGameBtn = document.getElementsByClassName("new-game")[0];
newGameBtn.addEventListener("click", function () {
newGame();
}, false);
newGameBtn.addEventListener("touchend", function () {
newGame();
}, false);
}
// backgroundColorToNumber:數字跟背景顏色/數字大小對應
function backgroundColorToNumber() {
var gridNum,
// child,
grid = document.getElementsByClassName("grid");
for (var i = 0; i < grid.length; i ++) {
gridNum = getGridNum(grid[i]);
// child = grid[i].children[0];
grid[i].style.fontSize = "48px";
// if ((" " + grid[i].className + " ").indexOf(" " + "new-grid" + " ") == -1) {
switch (gridNum) {
case 2:
grid[i].style.backgroundColor = "#fff8dc";
// grid[i].children[0].style.color = "#fff"; // 這句代碼會使得頁面癱瘓!!
break;
case 4:
grid[i].style.backgroundColor = "#e9967a";
// grid[i].children[0].style.color = "#8f7a66";
break;
case 8:
grid[i].style.backgroundColor = "#FFA07A";
break;
case 16:
grid[i].style.backgroundColor = "#F4A460";
break;
case 32:
grid[i].style.backgroundColor = "#FA8072";
break;
case 64:
grid[i].style.backgroundColor = "#ff7f50";
break;
case 128:
grid[i].style.backgroundColor = "#FF6347";
grid[i].style.fontSize = "40px";
break;
case 256:
grid[i].style.backgroundColor = "#FF8800";
grid[i].style.fontSize = "40px";
break;
case 512:
grid[i].style.backgroundColor = "#FF6600";
grid[i].style.fontSize = "40px";
break;
case 1024:
grid[i].style.backgroundColor = "#F53";
grid[i].style.fontSize = "32px";
break;
case 2048:
grid[i].style.backgroundColor = "#F40";
grid[i].style.fontSize = "32px";
break;
default:
grid[i].style.backgroundColor = "#b0c4de";
// grid[i].children[0].style.color = "#fff";
}
// }
}
}
// 游戲主入口
function getReady() {
window.onkeydown = function(e) {
deleteTempGrid(); // 在其他位置
keyDown(e.keyCode);
// backgroundColorToNumber();
}
}
// getGridNum(ele):傳入div元素,返回格子里面的數字
function getGridNum(ele) {
return parseInt(ele.children[0].innerText); // 空格返回NaN
}
// 各個方向的prevGrid,即所對應方向的前一個格子
function getPrevGrid(ele, direction) {
var prevEle,
count = 0;
// 各個方向
if (direction == "left") {
return ele.previousElementSibling || null;
} else if (direction == "right") {
return ele.nextElementSibling || null;
} else if (direction == "up") {
for (var i = 0; i < 4; i ++) {
ele = ele.previousElementSibling;
if (!ele) {
return null;
}
}
return ele;
} else if (direction == 'down') {
for (var i = 0; i < 4; i ++) {
ele = ele.nextElementSibling;
if (!ele) {
return null;
}
}
return ele;
}
}
// #滑塊移動#
// 桌面版通過監聽方向鍵來控制滑塊移動方向
function keyDown(keyCode) {
var dir,
arr,
go,
count = 0, // 用於疊加每次運動得到的分數
signal = 0; // 用於判斷格子是否運動
switch (keyCode) {
case 37:
dir = "left";
break;
case 38:
dir = "up";
break;
case 39:
dir = "right";
break;
case 40:
dir = "down";
break;
}
for (var i = 1; i < 5; i ++) {
if (dir == "up" || dir == "down") {
arr = document.getElementsByClassName("col" + i);
}else if (dir == "left" || dir == "right") {
arr = document.getElementsByClassName("row" + i);
}
if (dir == "up" || dir == "left") {
for (var j = 1; j <= 3; j ++) {
// console.log(col[j]);
max = j;
go = howToGo(arr[j], dir, max); // 疊加返回得分
// console.log("go2:" + go);
signal += go;
if (go > 1) {
count += go; // 累計每一次運動的得分
}
}
} else if (dir == "down" || dir == "right") {
for (var j = 2; j >= 0; j --) {
max = 3 - j;
go = howToGo(arr[j], dir, max);
// gridMove(arr[j], dir, 1);
// console.log("go:" + go);
signal += go;
if (go > 1) {
count += go; // 累計每一次運動的得分
}
}
}
}
// 格子有運動signal > 0
if (signal > 0) {
// console.log("signal:" + signal);
giveNumber(2);
backgroundColorToNumber();
testGameOver();
}
// 格子移動,且得分>0
if (count > 0) {
addScore(count);
}
return count;
}
// 移動端使用touch事件來監聽滑塊移動
function touch() {
var gameBoard = document.getElementsByClassName("game-board")[0];
gameBoard.addEventListener("touchstart",function (e) {
// e.preventDefault();
startX = e.changedTouches[0].pageX;
startY = e.changedTouches[0].pageY;
},false);
gameBoard.addEventListener('touchend',function(e){
e.preventDefault(); // 阻止瀏覽器的默認行為,例如滾動、跳轉等!!
//獲取滑動屏幕時的X,Y
endX = e.changedTouches[0].pageX,
endY = e.changedTouches[0].pageY;
//獲取滑動距離
distanceX = endX-startX;
distanceY = endY-startY;
//判斷滑動方向,滑動角度大於15°
if(Math.abs(distanceX) / Math.abs(distanceY) > 1.73 && distanceX > 0){
deleteTempGrid();
keyDown(39);
}else if(Math.abs(distanceX) / Math.abs(distanceY) > 1.73 && distanceX < 0){
deleteTempGrid();
keyDown(37);
}else if(Math.abs(distanceY) / Math.abs(distanceX) > 1.73 && distanceY < 0){
deleteTempGrid();
keyDown(38);
}else if(Math.abs(distanceY) / Math.abs(distanceX) > 1.73 && distanceY > 0){
deleteTempGrid();
keyDown(40);
}else{
// console.log('點擊未滑動');
}
});
}
// 3.記錄分數,分數會增加,
function addScore(score) {
var span = document.getElementsByClassName("number"),
currentScore = parseInt(span[0].innerText),
bestScore = parseInt(span[1].innerText);
span[0].innerText = score + currentScore;
scoreUpAnimaton("score", score);
if (span[0].innerText > bestScore) {
scoreUpAnimaton("best", score);
span[1].innerText = span[0].innerText;
}
}
// howToGoLeft(ele, direction, max):該函數判斷單個格子怎么移動
function howToGo(ele, direction, max, testMode) {
var prevGrid,
prevGridNum,
gridNum = 0,
go,
addNum,
numLen,
doubleNumGrid;
// console.log(prevGrid);
// 各個方向
prevGrid = getPrevGrid(ele, direction);
gridNum = getGridNum(ele);
if (prevGrid) {
prevGridNum = getGridNum(prevGrid);
} else {
prevGridNum = "null";
}
// 前面是空格,要繼續判斷。。。。。。。。。。。。。。。。。。。。。
if (gridNum && !prevGridNum) {
prevGrid.innerHTML = ele.innerHTML;
ele.children[0].innerText = "";
max -= 1;
// gridMove(ele, direction, 1);
if (max) {
go = howToGo(prevGrid, direction, max);
// 0、double、continue
}
// 返回1
// console.log("go:" + (go || 1));
// if (max == 0) {
// console.log("before:" + typeof(go));
// go = 1;
// console.log("after" + typeof(go));
// }
return go || 1;
// 若go = 0,返回1;go = double,返回double,go = underfied,返回1
// 和前面數字相同
} else if (gridNum == prevGridNum) {
if (!testMode) {
gridNum *= 2;
// addScore(gridNum);
// gridMove(ele, direction, 1);
prevGrid.children[0].innerText = gridNum + "";
// 在這里添加數字變大的動畫:
// numLen = (gridNum + "").length;
ele.children[0].innerText = "";
// console.log('gridNum:' + gridNum)
if (gridNum == 2048) {
popup("win");
}
// 如果數字疊加,就返回得分,且得分≥4
}
// console.log("gridNum: " + gridNum);
return gridNum;
} else {
// 格子沒動,返回0
return 0;
}
}
// 4.怎么判斷game over,或者達到2048為winner
// test geme over
function testGameOver() {
var content,
leftTest,
rightTest,
upTest,
downTest,
count = 0;
grid = document.getElementsByClassName("grid");
for (var i = 0; i < grid.length; i ++) {
content = grid[i].innerHTML;
if (content != "<span></span>") {
count += 1;
}
}
// console.log("count:" + count);
if (count == 16) {
if (getGridNum(grid[3]) == getGridNum(grid[4])) {
count -= 2;
}
if (getGridNum(grid[7]) == getGridNum(grid[8])) {
count -= 2;
}
if (getGridNum(grid[11]) == getGridNum(grid[12])) {
count -= 2;
}
for (var i = 0; i < grid.length; i ++) {
if(!howToGo(grid[i], "left", 1, true) && !howToGo(grid[i], "right", 1, true) && !howToGo(grid[i], "up", 1, true) && !howToGo(grid[i], "down", 1, true)) {
count --;
if (count == 0) {
popup("game-over");
return true;
}
}
}
}
return false;
}
// game over 后彈出
function popup(popType) {
var num,
tryAgainEle,
ele = document.getElementsByClassName(popType)[0],
headerEle = document.getElementsByClassName("header")[0],
gameBoardEle = document.getElementsByClassName("game-board")[0];
ele.style.display = "block";
headerEle.style.opacity = "0.4";
gameBoardEle.style.opacity = "0.4";
// tryAgain(num);
if (popType == "game-over") {
num = 0;
}
if (popType == "win") {
num = 1;
}
tryAgainEle = document.getElementsByClassName("try-again")[num];
tryAgainEle.addEventListener("click", function () {
tryAgain(ele, headerEle, gameBoardEle);
}, false);
tryAgainEle.addEventListener("touchend", function () {
tryAgain(ele, headerEle, gameBoardEle);
}, false);
}
// 再來一次
function tryAgain(ele, headerEle, gameBoardEle) {
ele.style.display = "none";
headerEle.style.opacity = "1.0";
gameBoardEle.style.opacity = "1.0";
newGame();
}
// 5.測試
function test() {
var randomInt,
timer;
timer = setInterval(function() {
randomInt = Math.floor(Math.random() * 4) + 37;
keyDown(randomInt);
// console.log(randomInt);
if (testGameOver()) {
clearInterval(timer);
}
}, 300);
}
// 分數增加的動畫
function scoreUpAnimaton(type, score) {
var ele,
score,
timer,
count = 0;
if (type == "score") {
ele = document.getElementsByClassName("score-animation")[0];
} else if (type == "best") {
ele = document.getElementsByClassName("best-animation")[0];
}
score = "+" + score;
ele.innerText = score;
ele.style.top = "25px";
ele.style.color = "#8f7a66";
ele.style.opacity = "1.0"
timer = setInterval(function() {
count ++;
ele.style.display = "inline-block";
ele.style.top = parseInt(ele.style.top) - 8 + "px";
ele.style.opacity = parseFloat(ele.style.opacity) - 0.1;
if (count == 6) {
clearInterval(timer);
ele.style.display = "none";
}
}, 80);
}
