实现2048小游戏


Welcome to [Hexo]

JS-实现2048小游戏

index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="index.js"></script>
    <link href="index.css" rel="stylesheet" />
</head>

<body>
    <div id="my2048"></div>
</body>

</html>

index.css

body, div, span, a {
    margin: 0;
    padding: 0;
}

#my2048 {
    margin-left: auto;
    margin-right: auto;
    margin-top: 300px;
    position: relative;
    background: #bbada0;
}

#my2048 div {
    position: absolute;
    display: inline-block;
    border: 0px;
}

index.js

var my2048;
var rows = 4;
var cols = 4;
var squareWidth = 100;
var spacing = 12;
var boardSet = [];
var squareSet = [];
var valueMap = [];
var colorMapping = {"0": "#ccc0b3", "2": "#eee4da", "4": "#ede0c8", "8": "#f2b179", "16": "#f59563", "32": "#f67e5f", "64": "#f65e3b", "128": "#edcf72", "256" : "#edcc61", "512": "#9c0", "1024": "#33b5e5", "2048": "#09c", "4096": "#5b67ff"};
var directionEnum = {left:{x:-1, y:0, key:"left"}, right:{x:1, y:0, key:"left"}, top:{x:0, y:-1, key:"top"}, down:{x:0, y:1, key:"top"}};
var lock = true;
var isChange = false;

function move(direction) {
    if (isOver()) {
        alert("game over ~!");
        return;
    }
    var newSquareSet = analysisActions(direction);
    //收尾(保证最终一致性)
    setTimeout(function () {
        refresh(newSquareSet);
        if (isChange) {
            randGenerateSquare();
        }
        lock = true;
        isChange = false;
    }, 300);
}

function analysisActions(direction) {
    var newSquareSet = generateNullMap();
    if (direction == directionEnum.left) {//向左
        console.log("向左");
        for (var i = 0 ; i < squareSet.length ; i ++) {
            var temp = [];
            for (var j = 0 ; j < squareSet[i].length ; j ++) {
                if (squareSet[i][j] != null) {
                    temp.push(squareSet[i][j]);
                }
            }
            temp = getNewLocation(temp);
            for (var k = 0 ; k < newSquareSet[i].length ; k ++) {
                if (temp[k]) {
                    newSquareSet[i][k] = temp[k];
                }
            }
        }
    } else if (direction == directionEnum.right) {//向右
        console.log("向右");
        for (var i = 0 ; i < squareSet.length ; i ++) {
            var temp = [];
            for (var j = squareSet[i].length - 1 ; j >= 0 ; j --) {
                if (squareSet[i][j] != null) {
                    temp.push(squareSet[i][j]);
                }
            }
            temp = getNewLocation(temp);
            for (var k = newSquareSet[i].length - 1 ; k >= 0 ; k --) {
                if (temp[newSquareSet[i].length - 1 - k]) {
                    newSquareSet[i][k] = temp[newSquareSet[i].length - 1 - k];
                }
            }
        }
    } else if (direction == directionEnum.top) {//向前
        console.log("向前");
        for (var j = 0 ; j < squareSet[0].length ; j ++) {
            var temp = [];
            for (var i = 0 ; i < squareSet.length ; i ++) {
                if (squareSet[i][j] != null) {
                    temp.push(squareSet[i][j]);
                }
            }
            temp = getNewLocation(temp);
            for (var k = 0 ; k < newSquareSet.length ; k ++) {
                if (temp[k]) {
                    newSquareSet[k][j] = temp[k];
                }
            }
        }
    } else {//向后
        console.log("向后");
        for (var j = 0 ; j < squareSet[0].length ; j ++) {
            var temp = [];
            for (var i = squareSet.length - 1 ; i >= 0 ; i --) {
                if (squareSet[i][j] != null) {
                    temp.push(squareSet[i][j]);
                }
            }
            temp = getNewLocation(temp);
            for (var k = newSquareSet.length - 1 ; k >= 0 ; k --) {
                if (temp[newSquareSet.length - 1 - k]) {
                    newSquareSet[k][j] = temp[newSquareSet.length - 1 - k];
                }
            }
        }
    }
    //动画
    for (var i = 0 ; i < newSquareSet.length ; i ++) {
        for (var j = 0 ; j < newSquareSet[i].length ; j ++) {
            if (newSquareSet[i][j] == null) {
                continue;
            }
            newSquareSet[i][j].style.transition = direction.key + " 0.3s";
            newSquareSet[i][j].style.left = (j + 1) * spacing + j * squareWidth + "px";
            newSquareSet[i][j].style.top = (i + 1) * spacing + i * squareWidth + "px";
            if(newSquareSet[i][j].nextSquare) {
                newSquareSet[i][j].nextSquare.style.transition = direction.key + " 0.3s";
                newSquareSet[i][j].nextSquare.style.left = (j + 1) * spacing + j * squareWidth + "px";
                newSquareSet[i][j].nextSquare.style.top = (i + 1) * spacing + i * squareWidth + "px";
            }
        }
    }
    return newSquareSet;
}

function getNewLocation(arr) {
    if (arr.length == 0) {
        return [];
    }
    var temp = [];
    temp.push(arr[0]);
    for (var i = 1 ; i < arr.length ; i ++) {
        if (arr[i].num == temp[temp.length - 1].num && (!temp[temp.length - 1].nextSquare || temp[temp.length - 1].nextSquare == null)) {
            temp[temp.length - 1].nextSquare = arr[i];
        } else {
            temp.push(arr[i]);
        }
    }
    return temp;
}

function generateNullMap () {
    var newValueMap = [];
    for (var i = 0 ; i < rows ; i ++) {
        newValueMap[i] = [];
        for (var j = 0 ; j < cols ; j ++) {
            newValueMap[i][j] = null;
        }
    }
    return newValueMap;
}

function isOver() {
    for (var i = 0 ; i < squareSet.length ; i ++) {
        for (var j = 0 ; j < squareSet[i].length ; j ++) {
            if (squareSet[i][j] == null) {
                return false;
            }
            if (squareSet[i][j + 1] && squareSet[i][j].num == squareSet[i][j + 1].num || squareSet[i + 1] && squareSet[i + 1][j] && squareSet[i][j].num == squareSet[i + 1][j].num){
                return false;
            }
        }
    }
    return true;
}

function refresh(newSquareSet) {//纠正位图,保证最终一致性
    squareSet = generateNullMap();
    var newValueMap = generateNullMap();
    for (var i = 0 ; i < rows ; i ++) {
        for (var j = 0 ; j < cols ; j ++) {
            //新的存在则添加
            if (newSquareSet[i][j]) {
                if (newSquareSet[i][j].nextSquare) {
                    var temp = createSquare(newSquareSet[i][j].num * 2, newSquareSet[i][j].offsetLeft, newSquareSet[i][j].offsetTop, i, j);
                    squareSet[i][j] = temp;
                    my2048.append(temp);
                    my2048.removeChild(newSquareSet[i][j].nextSquare);
                    my2048.removeChild(newSquareSet[i][j]);
                } else {
                    var temp = createSquare(newSquareSet[i][j].num, newSquareSet[i][j].offsetLeft, newSquareSet[i][j].offsetTop, i, j);
                    squareSet[i][j] = temp;
                    my2048.append(temp);
                    my2048.removeChild(newSquareSet[i][j]);
                }
                if (valueMap[i][j] != squareSet[i][j].num) {
                    isChange = true;
                }
                newValueMap[i][j] = squareSet[i][j].num;
            } else {
                newValueMap[i][j] = 0;
            }
        }
    }
    valueMap = newValueMap;
}

function randSquareNum() {
    return Math.random() >= 0.5 ? 4 : 2;
}

function randGenerateSquare() {
    for (;;) {
        var randRow = Math.floor(Math.random() * rows);
        var randCol = Math.floor(Math.random() * cols);
        if (valueMap[randRow][randCol] == 0) {
            var temp = createSquare(randSquareNum(), randCol * squareWidth + (randCol + 1) * spacing, randRow * squareWidth + (randRow + 1) * spacing, randRow, randCol);
            valueMap[temp.row][temp.col] = temp.num;
            squareSet[temp.row][temp.col] = temp;
            my2048.appendChild(temp);
            return true;
        }
    }
}

function createSquare(value, left, top, row, col) {
    var temp = document.createElement("div");
    temp.style.width = squareWidth + "px";
    temp.style.height = squareWidth + "px";
    temp.style.left = left + "px";
    temp.style.top = top + "px";
    temp.style.background = colorMapping[value];
    temp.style.lineHeight = squareWidth + "px";
    temp.style.textAlign = "center";
    temp.style.fontSize = 0.4 * squareWidth + "px";
    temp.num = value;
    temp.row = row;
    temp.col = col;
    if (value > 0) {
        temp.innerHTML = "" + value;
    }
    return temp;
}

function initBoard() {
    my2048 = document.getElementById("my2048");
    my2048.style.width = cols * squareWidth + (cols + 1) * spacing + "px";
    my2048.style.height = rows * squareWidth + (rows + 1) * spacing + "px";
}

function init() {
    //初始化棋盘
    initBoard();
    for (var i = 0 ; i < rows ; i ++){
        boardSet[i] = [];
        valueMap[i] = [];
        squareSet[i] = [];
        for (var j = 0 ; j < cols ; j ++){
            valueMap[i][j] = 0;
            squareSet[i][j] = null;
            boardSet[i][j] = createSquare(0, j * squareWidth + (j + 1) * spacing, i * squareWidth + (i + 1) * spacing, i, j);
            my2048.appendChild(boardSet[i][j]);
        }
    }
    //初始化方块
    randGenerateSquare();
    randGenerateSquare();
    //添加事件
    document.addEventListener("keydown", function(e) {
        if (!lock) return;
        lock = false;
        switch (e.key) {
            case "ArrowUp": move(directionEnum.top);break;
            case "ArrowDown": move(directionEnum.down);break;
            case "ArrowLeft": move(directionEnum.left);break;
            case "ArrowRight": move(directionEnum.right);break;
            default : {
                lock = true;
            }
        }
    });
}

window.onload = function () {
    init();
}

文章作者: CYQ
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 CYQ !
评论
  目录