用JS實現2048小游戲


前言:

一年來一直做得是后端的東西,沒有寫前端代碼,忘干凈了,之前也只用jQuery,好歹還能做點效果。想着撿起來一點,要不然枉費了師傅的栽培。

一直在看博客,但沒有屬於自己的東西。this has to change.

why not start now?俗話說只要代碼敲得夠快,悲傷就追不上我。

此篇開博,從簡單小游戲開始。目的是做出一些可以快點看到效果的東西,撿回一點程序員的信心。

 

先看最終效果:

 

 

1. 2048游戲功能分析:

核心是4個方向的移動的處理。

往一個方向移動,先看是否有數字的合並。一次移動,一行只允許合並一次,且從終點往起點合並。

合並完成之后,將合並后的數字和其他數字移動,貼邊。

在空白位置隨機生成一個數字2,移動結束。

 

算法實現:

考慮采用二維數組存儲4*4個格子中的值,如果移動,只需要更新數組,然后用數組的值來更新dom元素即可。

(這種想法不太面向對象。要是將每個格子都理解為一個對象,不知道好不好做,等以后研究--TODO)

 

2. 要用到的東西

2.1 html頁面布局,4*4個方塊得整出來

2.2 簡單css:不同的數字設置不同顏色

2.3 簡單dom操作:取元素,變換顯示的數字,改變class

2.4 取隨機數算法

2.5 按鍵事件監聽

2.6 一點點交互操作考慮,比如判定游戲失敗結束,成功結束,返回上一步。

 

3. 代碼結構:

 

較為粗糙,js幾乎全部是直接用html引用了,不會其他方式。先實現功能;

幾個圖片是:返回上一步按鈕,上下左右按鈕,重新開始按鈕。

js區分:

arrayHelper是操作數組的;

domOperation顧文思意,操作dom;

eventListener,處理按鍵事件

common:頁面初始化,隨機數生成等

 

4. 核心代碼

4.1 向方向【左】移動的邏輯

評論:寫的比較死,一步一步,按照規則來即可

// 向一個方向移動,更新數組(左),其他方向也是一樣的
function moveLeft(arrayCopy){
    var gameSuccess = false;
    
    // 是否有合並或者移動,如果沒有合並也沒有移動,就是沒有操作那就不要生成新的數字
    var anyChange = false;
    // 每一行,從【左】往【右】對比是否有一樣的數字(排除0)--並不需要挨着!中間隔了空氣也可以合並
    for (var i=0;i<4;i++){
        var firstIndex = 0;
        var secondIndex = 1;
        while (secondIndex<4){
            if (arrayCopy[i][firstIndex] == 0){
                // 第一個是0,不可能有合並,往后移動
                firstIndex++;
                secondIndex++;
                continue;
            }
            if (arrayCopy[i][secondIndex] == 0){
                // 第二個是0,第二個繼續往后找,第一個不變
                secondIndex++;
                // 1. 后面找不到數字,一直往后找,結束循環
                continue;
            }            
            // 有一次一樣的數字:計算得到和,放到第一個位置,這一行完了
            else if (arrayCopy[i][firstIndex] == arrayCopy[i][secondIndex]){
                arrayCopy[i][firstIndex] = arrayCopy[i][firstIndex] * 2;
                arrayCopy[i][secondIndex] = 0;
                anyChange = true;
                if (arrayCopy[i][firstIndex] >= 2048){
                    // 得到了2048,游戲結束
                    gameSuccess = true;
                }
                // 2. 后面找到數字,且可以合並,就合並,結束循環
                break;
            }
            else{
                // 3. 后面找到數字,但是不能合並,更新第一個數字為當前數字,第二個數字為下一個數字
                firstIndex = secondIndex;
                secondIndex += 1;
                continue;
            }
        }
    }
    
    // 將每一行數字向【左】挪動
    for (var i=0;i<4;i++){
        var newLine = [];//臨時存儲從【左】到【右】的非0數字
        var index = 0;
        for (var j=0;j<4;j++){
            if (arrayCopy[i][j] != 0){
                newLine[index] = arrayCopy[i][j];
                index++;
            }
        }
        
        // 用臨時存儲的數字給數組更新
        for (var m=0;m<index;m++){
            if (arrayCopy[i][m] != newLine[m]){
                anyChange = true;
            }
            arrayCopy[i][m] = newLine[m];
        }
        // 剩余的位置給0
        for (var n=index;n<4;n++){
            if (arrayCopy[i][n] != 0){
                anyChange = true;
            }
            arrayCopy[i][n] = 0;
        }
    }
    
    if (!anyChange){
        console.log("no change after this move!");
        if (!isEmptyCell(arrayCopy)){
            // 本步不能移動,且沒有剩余格子,且任意相鄰格子沒有相同的,就結束游戲
            if (!canMerge(arrayCopy)){
                console.log("Game Over! Try again.");
                return 'fail';
            }
        }
        if (gameSuccess){
            return 'success';
        }
        // 沒有移動
        return 'unmoved';
    }
    
    // 給空閑位置設置數字2
    if (isEmptyCell(arrayCopy))
    {
        initOnePosition(arrayCopy);
    }
    
    if (gameSuccess){
        return 'success';
    }
    return 'moved';
}

4.2.  通用的移動處理。

因為往一個方向移動,和往其他方向移動處理是一樣的,不可能復制以上代碼4次吧。

換個方向看:往左移動和往右移動對數組的操作,只是行處理相反,列處理一樣;

其他方向移動類似,不值得copy整個方法。

// 通用方法
// 所有移動都轉換成一個方向上的移動:例如,都想象成向左移動,只需要倒轉數組即可,完成移動再倒轉回來!
function move(direction){
    if (flagSuccess){
        if (confirm("You've got your 2048! Start Another One?\n已經通關!開始新游戲?")){
            gameRestart();
        }
        return;
    }
    
    // 移動之前,記錄上一步的內容,移動失敗之后可以恢復
    var lastStepUnchange = createNewArray();
    updateFrontArray(lastStepUnchange,lastStepArray);
    // 將上一步狀態設置為當前的
    updateFrontArray(lastStepArray,arrayInit);
    
    // 將當前的去更新,更新失敗則回滾上一步的狀態
    // 1. 數組倒轉復制
    var arrayCopy = new Array();
    if (direction == 'left'){
        arrayCopy = copyArrayLeft();
    }else if (direction == 'right'){
        arrayCopy = copyArrayRight();
    }else if (direction == 'up'){
        arrayCopy = copyArrayUp();
    }else if (direction == 'down'){
        arrayCopy = copyArrayDown();
    }
    
    // 2. 都向一個方向移動
    var moveResult = moveLeft(arrayCopy);
    if ('fail' == moveResult){
        
        updateFrontArray(lastStepArray,lastStepUnchange);
        // 移動失敗,沒有任何改變
        if (confirm('Game Over! Try again?\n游戲結束,再來一次?')){
            gameRestart();
            return;
        }else{
            // 最后一步了,允許回退
            clickedLastStep = false;
            return;
        }
        return;
    }
    if ('unmoved' == moveResult){
        return;
    }
    
    // 3. 從倒轉的數組更新原數組
    if (direction == 'left'){
        restoreArrayLeft(arrayCopy);
    }else if (direction == 'right'){
        restoreArrayRight(arrayCopy);
    }else if (direction == 'up'){
        restoreArrayUp(arrayCopy);
    }else if (direction == 'down'){
        restoreArrayDown(arrayCopy);
    }
    
    // 4. 根據數字更新頁面元素
    updatePageByArray();
    updateColor();
    
    if ('success' == moveResult){
        // 因為操作DOM不是實時的,所以要等一段事件操作完成之后再彈出確認框
        setTimeout(function(){
            // 游戲通關,是否重新開始
            if (confirm('Congragulations! Start Another Game?\n恭喜通關!是否再來一把?')){
                gameRestart();
            }else{
                flagSuccess = true;
            }
        },200);
        return;
    }
    
    // 移動完成
    clickedLastStep = false;
}

 

4.3 隨機數的生成:

開始做的是生成一個隨機數,16個位置的任意一個,如果這個位置已經有人了,就放棄,重新生成一個,直到找到空位為止。

但是到空位變少的時候,這樣效率低下。

優化:只在空位中找隨機位置。

// 生成隨機數,轉化成0-15的整數;
function getRamdom(count)
{
    // 0-1
    var r0 = Math.random();
    // 0-16
    var r1 = r0 * count;
    // 只取整數位數的數
    return Math.floor(r1);
}

// 改進:只在當前可用位置中隨機找,不用找不可用的位置 
function getOneEmptyCoordinate(array)
{
    // 1. 得到當前數組
    var countEmptyCells = 0;
    var mapIndex2Coordinate = {};
    var coordinates = null;
    for (var i=0;i<4;i++){
        for (var j=0;j<4;j++){
            if (array[i][j] == 0){
                countEmptyCells++;
                coordinates = new Array();
                coordinates.push(i);
                coordinates.push(j);
                mapIndex2Coordinate[countEmptyCells] = coordinates;
            }
        }
    }
    // 取可用位置的隨機位置
    var random = getRamdom(countEmptyCells);
    return mapIndex2Coordinate[random];
}

 

 

5. 欠缺:

5.1 布局,樣式的調整比較嫌麻煩,瞎調的。

5.2 js代碼關系--沒什么關系,忘了前端是怎么組織的了;

5.3 刷新頁面多次,可能出現從初始化異常,可能是文件加載順序問題,初始化時dom操作比較慢等原因

5.4 看看別人實現思路如何 

-- http://www.cnblogs.com/-lizi/p/8431030.html 這個寫的很漂亮

 

6. 總結:

 開發時間:5天下班時間,實際投入:15個小時左右。

 代碼規模:js400行;

 

7. 完整代碼粘貼

index.html

<head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8">
</head>
<link href="../css/common.css" rel="stylesheet">

<body>
    <script type="text/javascript" src="../js/common.js"></script>
    <script type="text/javascript" src="../js/eventListener.js"></script>
    <script type="text/javascript" src="../js/domOperation.js"></script>
    <div id="main">
        <div id="refreshDiv" onclick="gameRestart()">
            <span id="refreshButton">
                <img src="../resource/refreshButton.png"  alt="refresh" />
                <a>重新開始</a>
            </span>
        </div>
        <div id="mainTable">
        </div>
        <div id="explation">
            <span>
             2048游戲說明:<br>
             按上下左右方向鍵可以移動有數字的方塊,<br>
             相鄰的相同數字的方塊往一個方向移動會合並成更大的數字。<br>
             當最大數字出現2048時,游戲勝利!<br>
             溫馨提示:你可以使用空格鍵回退上一步。
            </span>
        </div>
        <div id="rights">
            <span>
                All rights reserved to S.C. Contact me at 857025773@qq.com. 
            </span>
        </div>
    </div>
    
    <!-- 操作 -->
    <div id="keys">
        <div>
            <span id="moveUpButton"onclick="move('up')">
                <img src="../resource/direction.png"  alt="direction" />
            </span>
        </div>
        <div>
            <span id="moveLeftButton"onclick="move('left')">
                <img src="../resource/direction.png"  alt="direction" />
            </span>
            <span id="moveBackButton" onclick="eventSpaceKey()">
                <img src="../resource/moveBack.png"  alt="moveBack" />
            </span>
            <span id="moveRightButton"onclick="move('right')">
                <img src="../resource/direction.png"  alt="direction" />
            </span>
        </div>
        <div>
            <span id="moveDownButton"onclick="move('down')">
                <img src="../resource/direction.png"  alt="direction" />
            </span>
        </div>
    </div>
    
    
    <script type="text/javascript">
        window.onload = function(){
                pageInit();
        }
    </script>
</body>

 

common.css

#main
{
    margin-left:500px;
    margin-top:100px;
    width:404px;
    heignt:400px;
    border: 0px solid gray;
    border-radius: 1px;
}

#keys
{
    margin-left:1150px;
    margin-top:-430px;
    width:303px;
    heignt:300px;
    border: 3px solid green;
    border-radius: 20px;
}


#keys div
{
    display:flex;
    height:75px;
}

#keys div span
{
    height:75px;
    width:100px;
    border: 1px solid gray;
    background:blue;
}

#moveLeftButton img
{
    height:75px;
    width:100px;
    -ms-transform:rotate(180deg); /* IE 9 */
    -moz-transform:rotate(180deg); /* Firefox */
    -webkit-transform:rotate(180deg); /* Safari and Chrome */
    -o-transform:rotate(180deg); /* Opera */
}
#moveRightButton img
{
    height:75px;
    width:100px;
}

#moveUpButton
{
    margin-left:100px;
}
#moveUpButton img
{
    margin-top: -13px;
    margin-left: 12px;
    height:100px;
    width:75px;
    -ms-transform:rotate(270deg); /* IE 9 */
    -moz-transform:rotate(270deg); /* Firefox */
    -webkit-transform:rotate(270deg); /* Safari and Chrome */
    -o-transform:rotate(270deg); /* Opera */
}
#moveDownButton
{
    margin-left:100px;
}
#moveDownButton img
{
    margin-left: 12px;
    margin-top: -13px;
    height:100px;
    width:75px;
    -ms-transform:rotate(90deg); /* IE 9 */
    -moz-transform:rotate(90deg); /* Firefox */
    -webkit-transform:rotate(90deg); /* Safari and Chrome */
    -o-transform:rotate(90deg); /* Opera */
}
#moveBackButton
{
    height:100px;
    width:75px;
    background:yellow !important;
}

#refreshDiv
{
    height:40px;
    width:133px;
    margin-left:140px;
    cursor: pointer;
    background:#ba3537;
    border-radius: 2px;
}

#refreshDiv span
{
    display: contents;
    font-family: '微軟雅黑';
    margin-left:159px;
    font-size:20;
}
#refreshDiv span a
{
    margin-bottom: 10px;
}


#explation
{
    margin-top:30px;
}
#rights
{
    margin-top:100px;
}
#rights span
{
    font-size:10;
}

#explation span
{
    font-size:14;
}

#mainTable
{
    margin-top:20px;
    background:#f5f5f5;
    border: 2px solid #478dcd;
    border-radius: 3px;
}

#mainTable div
{
    display:flex;
    width:400px;
    heignt:100px;
}

#mainTable span
{
    height:100px;
    width:100px;
    border: 1px solid gray;
    font-size: 50;
    text-align: center;
    font-weight:bold;
    
}

.color0
{
    background:#f5f5f5;
}

.color2
{
    background:#f5c7ad;
}
.color4
{
    background:#ec9362;
}
.color8
{
    background:#e3631e;
}
.color16
{
    background:#c2fcb1;
    font-size: 45 !important;
}
.color32
{
    background:#76f850;
    font-size: 45 !important;
}
.color64
{
    background:#2dad07;
    font-size: 45 !important;
}
.color128
{
    background:#a8a6f9;
    font-size: 40 !important;
}
.color256
{
    background:#4b47f1;
    font-size: 40 !important;
}
.color512
{
    background:#110da4;
    font-size: 40 !important;
}
.color1024
{
    background:#f799ef;
    font-size: 35 !important;
}
.color2048
{
    background:#a30e98;
    font-size: 35 !important;
}

 

common.js

// 拼成了2048,凍結操作,不允許移動了
var flagSuccess = false;
// 剛才點擊了回退,不允許重復點擊,要移動之后再點擊
var clickedLastStep = false;

// 記錄上一步,用於回退
var lastStepArray = [
                       [0,0,0,0],
                       [0,0,0,0],
                       [0,0,0,0],
                       [0,0,0,0]
                     ];

// 數組初始化--正常初始化
var arrayInit = 
    [
     [0,0,0,0],
     [0,0,0,0],
     [0,0,0,0],
     [0,0,0,0]
   ];
//[//調試--將要success
// [0,0,0,0],
// [0,128,0,0],
// [0,0,512,1024],
// [0,0,0,1024]
//];
//[//調試--將要fail
// [1,2,3,4],
// [5,128,6,7],
// [8,9,512,1024],
// [13,22,11,11]
//];



// 頁面加載初始化
function pageInit()
{
    addHelper();
    
//    initArray();
    // 頁面元素初始化(單元格)
    initElements();
    
    // 初始數據
    initTwoPositions();
    
    // 根據初始數據給單元格填充值
    updatePageByArray();
    
    // 根據單元格的值給單元格設置樣式
    updateColor();
}

// 重新開始
function gameRestart(){
    initArray();
    pageInit();
}

function initArray(){
    flagSuccess = false;
    arrayInit = createNewArray();
    clickedLastStep = false;
    lastStepArray = createNewArray();
}


// 給兩個位置設置數字2
function initTwoPositions()
{
    initOnePosition(arrayInit);
    initOnePosition(arrayInit);
}
// 給一個位置設置數字2
function initOnePosition(array){
    // 取隨機數方式1
//    var num = getRamdom(16);
//    var line = Math.floor(num/4);
//    var col = num % 4;
//    var curNum = array[line][col];
//    if (curNum == 0)
//    {
//        // 成功找到空閑位置
//        array[line][col] = 2;
//        return true;
//    }
//    else{
//        // 遞歸調用,必須找到一個可用位置才算完
//        return initOnePosition(array);
//    }
    
    // 取隨機數方式2
    var coordinate = getOneEmptyCoordinate(array);
    array[coordinate[0]][coordinate[1]] = 2; 
}

function isEmptyCell(arrayCopy)
{
    for (var i=0;i<4;i++)
    {
        for (var j=0;j<4;j++)
        {
            if (arrayCopy[i][j] == 0)
            {
                return true;
            }
        }
    }
    return false;
}

// 生成隨機數,轉化成0-15的整數;
function getRamdom(count)
{
    // 0-1
    var r0 = Math.random();
    // 0-16
    var r1 = r0 * count;
    // 只取整數位數的數
    return Math.floor(r1);
}

// 改進:只在當前可用位置中隨機找,不用找不可用的位置 
function getOneEmptyCoordinate(array)
{
    // 1. 得到當前數組
    var countEmptyCells = 0;
    var mapIndex2Coordinate = {};
    var coordinates = null;
    for (var i=0;i<4;i++){
        for (var j=0;j<4;j++){
            if (array[i][j] == 0){
                countEmptyCells++;
                coordinates = new Array();
                coordinates.push(i);
                coordinates.push(j);
                mapIndex2Coordinate[countEmptyCells] = coordinates;
            }
        }
    }
    // 取可用位置的隨機位置
    var random = getRamdom(countEmptyCells);
    return mapIndex2Coordinate[random];
}

 

eventListener,js

/**
 *  引用工具類
 */
function addHelper(){
    var newscript = document.createElement('script');  
    newscript.setAttribute('type','text/javascript');  
    newscript.setAttribute('src','../js/arrayHelper.js');  
    document.body.appendChild(newscript);  
}

//捕捉按鍵事件
document.onkeyup = function(event) {
    event = event || window.event;
    
    if (event.keyCode == 37){//left
        move('left');
    }else if (event.keyCode == 39){//right
        move('right');
    }else if (event.keyCode == 38){//up
        move('up');
    }else if (event.keyCode == 40){//down
        move('down');
    }else if (event.keyCode == 32){//space
        eventSpaceKey();
    }
}

function eventSpaceKey(){
    // 回退上一步
    if (clickedLastStep){
        console.log('can not move back again');
        return;
    }
    moveBack();
    flagSuccess = false;
    clickedLastStep = true;
}

// 回退上一步
function moveBack(){
    // 判斷上一步全是0(剛剛初始化)
    var justStarted = true;
    for (var i=0;i<4;i++){
        for (var j=0;j<4;j++){
            if (lastStepArray[i][j] != 0){
                justStarted =  false;
            }
        }
    }
    if(justStarted){
        return;
    }
    
    // 1. 用備份的數組給當前數組設置值
    updateFrontArray(arrayInit,lastStepArray);
    
    // 3. 更新頁面
    updatePageByArray();
    updateColor();
}

// 通用方法
// 所有移動都轉換成一個方向上的移動:例如,都想象成向左移動,只需要倒轉數組即可,完成移動再倒轉回來!
function move(direction){
    if (flagSuccess){
        if (confirm("You've got your 2048! Start Another One?\n已經通關!開始新游戲?")){
            gameRestart();
        }
        return;
    }
    
    // 移動之前,記錄上一步的內容,移動失敗之后可以恢復
    var lastStepUnchange = createNewArray();
    updateFrontArray(lastStepUnchange,lastStepArray);
    // 將上一步狀態設置為當前的
    updateFrontArray(lastStepArray,arrayInit);
    
    // 將當前的去更新,更新失敗則回滾上一步的狀態
    // 1. 數組倒轉復制
    var arrayCopy = new Array();
    if (direction == 'left'){
        arrayCopy = copyArrayLeft();
    }else if (direction == 'right'){
        arrayCopy = copyArrayRight();
    }else if (direction == 'up'){
        arrayCopy = copyArrayUp();
    }else if (direction == 'down'){
        arrayCopy = copyArrayDown();
    }
    
    // 2. 都向一個方向移動
    var moveResult = moveLeft(arrayCopy);
    if ('fail' == moveResult){
        
        updateFrontArray(lastStepArray,lastStepUnchange);
        // 移動失敗,沒有任何改變
        if (confirm('Game Over! Try again?\n游戲結束,再來一次?')){
            gameRestart();
            return;
        }else{
            // 最后一步了,允許回退
            clickedLastStep = false;
            return;
        }
        return;
    }
    if ('unmoved' == moveResult){
        return;
    }
    
    // 3. 從倒轉的數組更新原數組
    if (direction == 'left'){
        restoreArrayLeft(arrayCopy);
    }else if (direction == 'right'){
        restoreArrayRight(arrayCopy);
    }else if (direction == 'up'){
        restoreArrayUp(arrayCopy);
    }else if (direction == 'down'){
        restoreArrayDown(arrayCopy);
    }
    
    // 4. 根據數字更新頁面元素
    updatePageByArray();
    updateColor();
    
    if ('success' == moveResult){
        // 因為操作DOM不是實時的,所以要等一段事件操作完成之后再彈出確認框
        setTimeout(function(){
            // 游戲通關,是否重新開始
            if (confirm('Congragulations! Start Another Game?\n恭喜通關!是否再來一把?')){
                gameRestart();
            }else{
                flagSuccess = true;
            }
        },200);
        return;
    }
    
    // 移動完成
    clickedLastStep = false;
}

// 向一個方向移動,更新數組(左),其他方向也是一樣的
function moveLeft(arrayCopy){
    var gameSuccess = false;
    
    // 是否有合並或者移動,如果沒有合並也沒有移動,就是沒有操作那就不要生成新的數字
    var anyChange = false;
    // 每一行,從【左】往【右】對比是否有一樣的數字(排除0)--並不需要挨着!中間隔了空氣也可以合並
    for (var i=0;i<4;i++){
        var firstIndex = 0;
        var secondIndex = 1;
        while (secondIndex<4){
            if (arrayCopy[i][firstIndex] == 0){
                // 第一個是0,不可能有合並,往后移動
                firstIndex++;
                secondIndex++;
                continue;
            }
            if (arrayCopy[i][secondIndex] == 0){
                // 第二個是0,第二個繼續往后找,第一個不變
                secondIndex++;
                // 1. 后面找不到數字,一直往后找,結束循環
                continue;
            }            
            // 有一次一樣的數字:計算得到和,放到第一個位置,這一行完了
            else if (arrayCopy[i][firstIndex] == arrayCopy[i][secondIndex]){
                arrayCopy[i][firstIndex] = arrayCopy[i][firstIndex] * 2;
                arrayCopy[i][secondIndex] = 0;
                anyChange = true;
                if (arrayCopy[i][firstIndex] >= 2048){
                    // 得到了2048,游戲結束
                    gameSuccess = true;
                }
                // 2. 后面找到數字,且可以合並,就合並,結束循環
                break;
            }
            else{
                // 3. 后面找到數字,但是不能合並,更新第一個數字為當前數字,第二個數字為下一個數字
                firstIndex = secondIndex;
                secondIndex += 1;
                continue;
            }
        }
    }
    
    // 將每一行數字向【左】挪動
    for (var i=0;i<4;i++){
        var newLine = [];//臨時存儲從【左】到【右】的非0數字
        var index = 0;
        for (var j=0;j<4;j++){
            if (arrayCopy[i][j] != 0){
                newLine[index] = arrayCopy[i][j];
                index++;
            }
        }
        
        // 用臨時存儲的數字給數組更新
        for (var m=0;m<index;m++){
            if (arrayCopy[i][m] != newLine[m]){
                anyChange = true;
            }
            arrayCopy[i][m] = newLine[m];
        }
        // 剩余的位置給0
        for (var n=index;n<4;n++){
            if (arrayCopy[i][n] != 0){
                anyChange = true;
            }
            arrayCopy[i][n] = 0;
        }
    }
    
    if (!anyChange){
        console.log("no change after this move!");
        if (!isEmptyCell(arrayCopy)){
            // 本步不能移動,且沒有剩余格子,且任意相鄰格子沒有相同的,就結束游戲
            if (!canMerge(arrayCopy)){
                console.log("Game Over! Try again.");
                return 'fail';
            }
        }
        if (gameSuccess){
            return 'success';
        }
        // 沒有移動
        return 'unmoved';
    }
    
    // 給空閑位置設置數字2
    if (isEmptyCell(arrayCopy))
    {
        initOnePosition(arrayCopy);
    }
    
    if (gameSuccess){
        return 'success';
    }
    return 'moved';
}

// 是否有任意相鄰的格子可以合並
function canMerge(arrayCopy){
    for (var i=0;i<4;i++){
        for (var j=0;j<4;j++){
            if (j+1 < 4&& arrayCopy[i][j] == arrayCopy[i][j+1]){
                return true;
            }
            if (i+1 < 4 && arrayCopy[i][j] == arrayCopy[i+1][j]){
                return true;
            }
        }
    }
    return false;
}

arrayHelper.js

function createNewArray(){
    var newArray = [
                           [0,0,0,0],
                           [0,0,0,0],
                           [0,0,0,0],
                           [0,0,0,0]
                         ];
    return newArray;
}


// 后面的復制給前面
function updateFrontArray(arr1,arr2)
{
    for (var i=0;i<4;i++){
        for (var j=0;j<4;j++){
            arr1[i][j] = arr2[i][j];
        }
    }
}

function copyArray(arr){
    var newArray = createNewArray();
    updateFrontArray(newArray,arr);
    return newArray;
}


//左,原方向
function copyArrayLeft(){
    var arrayCopy = copyArray(arrayInit);
    return arrayCopy;
}
function restoreArrayLeft(arrayCopy){
    updateFrontArray(arrayInit,arrayCopy);
}

//右,上下不變,左右顛倒
function copyArrayRight(){
    var arrayCopy = new Array();
    for (var i=0;i<4;i++){
        var copyOneLine = new Array();
        for (var j=0;j<4;j++){
            copyOneLine[3-j] = arrayInit[i][j];
        }
        arrayCopy[i] = copyOneLine;
    }
    return arrayCopy;
}
function restoreArrayRight(arrayCopy){
    for (var i=0;i<4;i++){
        for (var j=0;j<4;j++){
            arrayInit[i][j] = arrayCopy[i][3-j];
        }
    }
}

//
//從上往下變成從左往右
//從右往左變成從上往下
//(i,j) 對應:(3-j,i)
function copyArrayUp(){
    var arrayCopy = [
                       [0,0,0,0],
                       [0,0,0,0],
                       [0,0,0,0],
                       [0,0,0,0]
                     ];
    for (var i=0;i<4;i++){
        for (var j=0;j<4;j++){
            arrayCopy[3-j][i] = arrayInit[i][j];
        }
    }
    return arrayCopy;
}
function restoreArrayUp(arrayCopy){
    for (var i=0;i<4;i++){
        for (var j=0;j<4;j++){
            arrayInit[i][j] = arrayCopy[3-j][i];
        }
    }
}

//
//從上往下變成從下往上
//從左往右變成從左往右
//(i,j) 對應:(j,3-i)
function copyArrayDown(){
    var arrayCopy = [
                       [0,0,0,0],
                       [0,0,0,0],
                       [0,0,0,0],
                       [0,0,0,0]
                     ];
    for (var i=0;i<4;i++){
        for (var j=0;j<4;j++){
            arrayCopy[j][3-i] = arrayInit[i][j];
        }
    }
    return arrayCopy;
}
function restoreArrayDown(arrayCopy){
    for (var i=0;i<4;i++){
        for (var j=0;j<4;j++){
            arrayInit[i][j] = arrayCopy[j][3-i];
        }
    }
}

domOperation.js

// 用數組給元素賦值
function updatePageByArray()
{
    var lines = document.getElementById("mainTable").children;
    var lineIndex = 0;
    
    while (lineIndex < lines.length)
    {
        var spanIndex = 0;
        while (spanIndex < lines[lineIndex].children.length)
        {
            var oneSpan = lines[lineIndex].children[spanIndex];
            oneSpan.innerHTML = arrayInit[lineIndex][spanIndex];
            spanIndex++;
        }
        lineIndex++;
    }
}

// 初始化單元格和顏色
function initElements()
{
    var mainTable = document.getElementById("mainTable");
    var str = '';
    // 創建行
    for (var i=0;i<4;i++)
    {
        str += "<div id='" +"line"+i+"'>";
        for (var j=0;j<4;j++)
        {
            var num = arrayInit[i][j];
            str += "<span id='" +"span"+i+j+"'>"
                        + num+
                    "</span>";
        }
        str += "</div>";
        mainTable.innerHTML = str;
    }
}

// 根據ID更新顏色
function updateColor(){
    for (var i=0;i<4;i++){
        for (var j=0;j<4;j++){
            var span = document.getElementById("span"+i+j);
            var value = span.innerHTML;
            if (value == '0'){
                span.innerHTML = '';
            }
            span.className = (" color" + value);
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM