简单的JavaScript实现2048游戏

实现一个网页版的2048游戏,过程参考了慕课网2048游戏的教程,

具体代码如下:

html结构:

<body>
<div class="header">
    <h2>2048</h2>
    <a href="javascript:newGame()" id="newGameBtn">New Game</a>
    <p>Score:<span id="score">0</span></p>
</div>
<div id="grid-container" class="grid-container">
    <div class="grid-cell" id="grid-cell-0-0"></div>
    <div class="grid-cell" id="grid-cell-0-1"></div>
    <div class="grid-cell" id="grid-cell-0-2"></div>
    <div class="grid-cell" id="grid-cell-0-3"></div>

    <div class="grid-cell" id="grid-cell-1-0"></div>
    <div class="grid-cell" id="grid-cell-1-1"></div>
    <div class="grid-cell" id="grid-cell-1-2"></div>
    <div class="grid-cell" id="grid-cell-1-3"></div>

    <div class="grid-cell" id="grid-cell-2-0"></div>
    <div class="grid-cell" id="grid-cell-2-1"></div>
    <div class="grid-cell" id="grid-cell-2-2"></div>
    <div class="grid-cell" id="grid-cell-2-3"></div>

    <div class="grid-cell" id="grid-cell-3-0"></div>
    <div class="grid-cell" id="grid-cell-3-1"></div>
    <div class="grid-cell" id="grid-cell-3-2"></div>
    <div class="grid-cell" id="grid-cell-3-3"></div>
</div>

一些css样式:


.header {
    margin: 0 auto;
    width: 100%;
    font-family: "Microsoft YaHei", "微软雅黑";
    position: relative;
    clear: both;
}

.header h2 {
    font-size: 55px;
    display: inline-block;
    color: #776E65;
    margin: 10px 14px 10px -100px;
    position: absolute;

}

.header a {
    text-decoration: none;
    background: #8F7A66;
    display: inline-block;
    height: 45px;
    width: 120px;
    line-height: 50px;
    font-size: 20px;
    border-radius: 5px;
    color: #ffffff;
    text-align: center;
    margin: 10px;

}

.header p {
    font-family: "Microsoft YaHei", "微软雅黑";
    font-size: 20px;
    color: #8F7A66;
    margin-left: 10px;
}

.grid-container {
    margin: 15px auto;
    background-color: #bbada0;
    position: relative;
}

.grid-cell {
    width: 100px;
    height: 100px;
    background: #ccc0b3;
    border-radius: 10px;
    position: absolute;
}

.number-cell {
    font-family: "Microsoft YaHei", "微软雅黑";
    font-weight: bold;
    text-align: center;

    position: absolute;
}

JavaScript:


var board = new Array(),
    score = 0,
    hasConflicted = new Array();//用于防止二次碰撞

var startx, starty, endx, endy;//用于移动端触控操作

screenWidth = $(window).width();
gridContainerWidth = screenWidth * 0.92;
cellWidth = screenWidth * 0.18;
cellDistance = screenWidth * 0.04;
$(function () {
    newGame();
});

function newGame() {
    adjustForMobile();
    //初始化
    init();
}
function adjustForMobile() {
    //调整grid以根据适应移动端;
    if (screenWidth >= 500) {
        //适用于网页
        gridContainerWidth = 500;
        cellWidth = 100;
        cellDistance = 20;
    }
    //调整header部分样式
    $(".header").css("width", gridContainerWidth + "px");
    $(".header").css("left", cellWidth * 3 + "px");
    $(".header h2").css("margin-left", -(gridContainerWidth / 2 - cellDistance) + "px");

    //调整grid-container
    var theGridContainer = $("#grid-container");
    theGridContainer.css({
        "width": gridContainerWidth + "px",
        "height": gridContainerWidth + "px",
        "border-radius": gridContainerWidth * 0.02 + "px"
    });

    //调整grid-cell
    $(".grid-cell").css({
        "height": cellWidth + "px",
        "width": cellWidth + "px",
        "border-radius": gridContainerWidth * 0.02 + "px"
    });
}
function init() {
    //初始化函数
    score = 0;
    updateScore();

    for (var i = 0; i < 4; i++) {
        for (var j = 0; j < 4; j++) {
            $("#grid-cell-" + i + "-" + j).css("top", getPosTop(i, j));
            $("#grid-cell-" + i + "-" + j).css("left", getPosLeft(i, j));
        }

    }
    //初始化board数据
    for (var i = 0; i < 4; i++) {
        board[i] = new Array();
        hasConflicted[i] = new Array();
        for (var j = 0; j < 4; j++) {
            board[i][j] = 0;
            hasConflicted[i][j] = false;
        }
    }
    generateOneNumber();
    generateOneNumber();

    updateBoardView();

}

function updateBoardView() {
    //更新页面视图-即根据board生成所有 number-cell
    $(".number-cell").remove();
    for (var i = 0; i < 4; i++) {
        for (var j = 0; j < 4; j++) {
            $("#grid-container").append(‘<div class="number-cell" id="number-cell-‘ + i + ‘-‘ + j + ‘"></div>‘);
            var theNumberCell = $("#number-cell-" + i + "-" + j);//表示当前正在操作的cell

            if (board[i][j] == 0) {
                //此时不显示数字
                theNumberCell.css("width", 0);
                theNumberCell.css("height", 0);
                theNumberCell.css("top", getPosTop(i, j) + cellWidth / 2);
                theNumberCell.css("left", getPosLeft(i, j) + cellWidth / 2);

            }
            else {
                theNumberCell.css({
                    "width": cellWidth + "px",
                    "height": cellWidth + "px",
                    "line-height": cellWidth + "px",
                    "border-radius": gridContainerWidth * 0.02 + "px",
                    "top": getPosTop(i, j),
                    "left": getPosLeft(i, j),
                    "background-color": getNumberBackgroundColor(board[i][j]),
                    "color": getNumberColor(board[i][j]),
                    "font-size": cellWidth * 0.65 + "px"
                });
                theNumberCell.html(board[i][j]);
                if (board[i][j] >= 128) {
                    theNumberCell.css("font-size", cellWidth * 0.5);
                }
            }
            hasConflicted[i][j] = false;
        }
    }
}

function generateOneNumber() {
    //随机的在一个位置生成2或者4
    if (!nospace(board)) {
        //随机一个位置
        var randx = parseInt(Math.floor(Math.random() * 4));//向下取整
        var randy = parseInt(Math.floor(Math.random() * 4));
        var count = 0;
        while (count < 40) {
            //只循环40次,避免计算机一直找不到而循环
            if (board[randx][randy] == 0) {
                break;
            }
            randx = parseInt(Math.floor(Math.random() * 4));
            randy = parseInt(Math.floor(Math.random() * 4));
        }
        if (count == 39) {
            //查找一个空位置
            for (var i = 0; i < 4; i++) {
                for (var j = 0; j < 4; j++) {
                    if (board[i][j] == 0) {
                        randx = i;
                        randy = j;
                    }
                }
            }
        }
        //随机2或4
        var randNumber = Math.random() < 0.6 ? 2 : 4;

        //在随机位置显示随机数字
        board[randx][randy] = randNumber;

        showNumberWithAnimation(randx, randy, randNumber);
    }
    return true;
}

function isGameOver() {
    if (nospace(board) && noMove(board)) {
        gameOver("Just Try Again!")
    }
}

function gameOver(text) {
    generateOneNumber();
    alert(text);
}

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

//键盘操作
$(document).keydown(function (event) {
    switch (event.keyCode) {
        case 37://left
            event.preventDefault();//阻止默认的方向键,避免滚动条出现
            if (moveLeft()) {
                setTimeout(generateOneNumber(), 220);
                setTimeout(isGameOver(), 220);
            }
            break;
        case 38://up
            event.preventDefault();
            if (moveUp()) {
                setTimeout(generateOneNumber(), 210);
                setTimeout(isGameOver(), 220);
            }
            break;
        case 39://right
            event.preventDefault();
            if (moveRight()) {
                setTimeout(generateOneNumber(), 210);
                setTimeout(isGameOver(), 220);
            }
            break;
        case 40://down
            event.preventDefault();
            if (moveDown()) {
                setTimeout(generateOneNumber(), 210);
                setTimeout(isGameOver(), 220);
            }
            break;
        default :
    }
});

function moveLeft() {
    if (!canMoveLeft(board)) {
        generateOneNumber();
        return false;
    }
    for (var i = 0; i < 4; i++) {
        for (var j = 1; j < 4; j++) {
            if (board[i][j] != 0) {
                for (var k = 0; k < j; k++) {
                    if (board[i][k] == 0 && noBlockHorizontal(i, k, j, board)) {
                        //move
                        showMoveAnimation(i, j, i, k);
                        board[i][k] = board[i][j];
                        board[i][j] = 0;
                        continue;
                    }
                    if (board[i][k] == board[i][j] && noBlockHorizontal(i, k, j, board) && !hasConflicted[i][k]) {
                        //move
                        showMoveAnimation(i, j, i, k);
                        //add
                        board[i][k] += board[i][j];
                        board[i][j] = 0;
                        //add score
                        score += board[i][k];
                        updateScore();
                        if (isWinGame(board)) {
                            gameOver("You Get 2048!");
                        }
                        continue;
                    }
                }
            }
        }
    }
    setTimeout(updateBoardView(), 210);
    return true;
}

function moveUp() {
    if (!canMoveUp(board)) {
        generateOneNumber();
        return false;
    }
    for (var j = 0; j < 4; j++) {
        for (var i = 1; i < 4; i++) {
            if (board[i][j] != 0) {
                for (var k = 0; k < i; k++) {
                    if (board[k][j] == 0 && noBlockVertical(k, i, j, board)) {
                        //move
                        showMoveAnimation(i, j, k, j);
                        board[k][j] = board[i][j];
                        board[i][j] = 0;
                        continue;
                    }
                    if (board[k][j] == board[i][j] && noBlockVertical(k, i, j, board) && !hasConflicted[k][j]) {
                        //move
                        showMoveAnimation(i, j, k, j);
                        //add
                        board[k][j] += board[i][j];
                        board[i][j] = 0;
                        //add score
                        score += board[k][j];
                        updateScore();
                        if (isWinGame(board)) {
                            gameOver("You Get 2048!");
                        }
                        continue;
                    }
                }
            }
        }
    }
    setTimeout(updateBoardView(), 220);
    return true;
}
function moveRight() {
    if (!canMoveRight(board)) {
        generateOneNumber();
        return false;
    }
    for (var i = 0; i < 4; i++) {
        for (var j = 2; j >= 0; j--) {
            if (board[i][j] != 0) {
                for (var k = 3; k > j; k--) {
                    if (board[i][k] == 0 && noBlockHorizontal(i, j, k, board)) {
                        //move
                        showMoveAnimation(i, j, i, k);
                        board[i][k] = board[i][j];
                        board[i][j] = 0;
                        continue;
                    }
                    if (board[i][k] == board[i][j] && noBlockHorizontal(i, j, k, board) && !hasConflicted[i][k]) {
                        //move
                        showMoveAnimation(i, j, i, k);
                        //add
                        board[i][k] += board[i][j];
                        board[i][j] = 0;
                        //add score
                        score += board[i][k];
                        updateScore();
                        if (isWinGame(board)) {
                            gameOver("You Get 2048!");
                        }
                        continue;
                    }
                }
            }
        }
    }
    setTimeout(updateBoardView(), 500);
    return true;
}
function moveDown() {
    if (!canMoveDown(board)) {
        generateOneNumber();
        return false;
    }
    for (var j = 0; j < 4; j++) {
        for (var i = 2; i >= 0; i--) {
            if (board[i][j] != 0) {
                for (var k = 3; k > i; k--) {
                    if (board[k][j] == 0 && noBlockVertical(i, k, j, board)) {
                        //move
                        showMoveAnimation(i, j, k, j);
                        board[k][j] = board[i][j];
                        board[i][j] = 0;
                        continue;
                    }
                    if (board[k][j] == board[i][j] && noBlockVertical(i, k, j, board) && !hasConflicted[k][j]) {
                        //move
                        showMoveAnimation(i, j, k, j);
                        //add
                        board[k][j] += board[i][j];
                        board[i][j] = 0;
                        //add score
                        score += board[k][j];
                        updateScore();
                        if (isWinGame(board)) {
                            gameOver("You Get 2048!");
                        }
                        continue;
                    }
                }
            }
        }
    }
    setTimeout(updateBoardView(), 220);
    return true;
}
function updateScore() {
    //更新分数
    $("#score").html(score);
}

function getPosTop(i, j) {
    return cellDistance + (cellDistance + cellWidth) * i;
}
function getPosLeft(i, j) {
    return cellDistance + (cellDistance + cellWidth) * j;
}

function getNumberBackgroundColor(number) {
    //根据数字返回背景色
    switch (number) {
        case 2:
            return "#EEE4DA";
            break;
        case 4:
            return "#EDE0C8";
            break;
        case 8:
            return "#F2B179";
            break;
        case 16 :
            return "#F59563";
            break;
        case 32:
            return "#F67C5F";
            break;
        case 64:
            return "#F65E3B";
            break;
        case 128:
            return "#EDCF72";
            break;
        case 256:
            return "#6BADF6";
            break;
        case 512:
            return "#EBC400";
            break;
        case 1024:
            return "#EBC400";
            break;
        case 2048:
            return "#EBC400";
            break;

    }
    return "#FC6";
}

function getNumberColor(number) {
    //根据数字返回前景色
    if (number <= 4) {
        return "#776E65";
    }
    return "#F9F6F2";
}
function nospace(board) {
    //判断棋盘格里是否还有空间
    for (var i = 0; i < 4; i++) {
        for (var j = 0; j < 4; j++) {
            if (board[i][j] == 0) {
                return false;
            }
        }
    }
    return true;
}
function noMove(board) {
    //判断棋盘格里是否还能移动
    if (canMoveLeft(board) ||
        canMoveUp(board) ||
        canMoveRight(board) ||
        canMoveDown(board)) {
        return false;
    }
    return true;
}
function canMoveLeft(borad) {
    for (var i = 0; i < 4; i++) {
        for (var j = 1; j < 4; j++) {
            if (board[i][j] != 0) {
                if (board[i][j - 1] == 0 || board[i][j - 1] == board[i][j]) {
                    return true;
                }
            }
        }
    }
    return false;
}
function canMoveUp(borad) {
    for (var i = 1; i < 4; i++) {
        for (var j = 0; j < 4; j++) {
            if (board[i][j] != 0) {
                if (board[i - 1][j] == 0 || board[i - 1][j] == board[i][j]) {
                    return true;
                }
            }
        }
    }
    return false;
}
function canMoveRight(borad) {
    for (var i = 0; i < 4; i++) {
        for (var j = 0; j < 3; j++) {
            if (board[i][j] != 0) {
                if (board[i][j + 1] == 0 || board[i][j + 1] == board[i][j]) {
                    return true;
                }
            }
        }
    }
    return false;
}
function canMoveDown(borad) {
    for (var i = 0; i < 3; i++) {
        for (var j = 0; j < 4; j++) {
            if (board[i][j] != 0) {
                if (board[i + 1][j] == 0 || board[i + 1][j] == board[i][j]) {
                    return true;
                }
            }
        }
    }
    return false;
}

function noBlockHorizontal(row, col1, col2, board) {
    //第row行,从col1到col2列没有障碍
    for (var i = col1 + 1; i < col2; i++) {
        if (board[row][i] != 0) {
            return false;
        }
    }
    return true;
}

function noBlockVertical(row1, row2, col, board) {
    for (var i = row1 + 1; i < row2; i++) {
        if (board[i][col] != 0) {
            return false;
        }
    }
    return true;
}

function showNumberWithAnimation(i, j, randNumber) {

    var numberCell = $("#number-cell-" + i + "-" + j);

    numberCell.css("background-color", getNumberBackgroundColor(board[i][j]));
    numberCell.css("color", getNumberColor(board[i][j]));
    numberCell.css("border-radius", gridContainerWidth * 0.02 + "px");
    numberCell.css("line-height", cellWidth + "px");
    numberCell.css("font-size", cellWidth * 0.65 + "px");
    numberCell.html(board[i][j]);
    numberCell.animate({
        width: cellWidth,
        height: cellWidth,
        top: getPosTop(i, j),
        left: getPosLeft(j, j)
    }, 150)
}

function showMoveAnimation(fromx, fromy, tox, toy) {
    var numberCell = $("#number-cell-" + fromx + "-" + fromy);
    numberCell.animate({
        top: getPosTop(tox, toy),
        left: getPosLeft(tox, toy)
    }, 100)
}

ps:

  1. 简单实现了基本的游戏功能,以及简单的响应式可能还存在一些bug,有时间再来调试吧
  2. 附上原版游戏地址: http://gabrielecirulli.github.io/2048/
  3. 附上我完整的源代码地址:My Demos
时间: 2024-10-19 02:09:53

简单的JavaScript实现2048游戏的相关文章

用javascript制作2048游戏的思路(原创若 转载请附上本链接)

一.项目已上传至github,地址:https://github.com/forjuan/2048game 二.学习了javascript基础后,想要捣鼓点东西做,做了一个自己以前很爱玩的2048游戏.经过初期的思路设计手工画了设计思路图.手工图有空在用图画出来. 实现2048的功能:1.核心:上下左右移动. 2.游戏开始,游戏结束. 3.外观实现. 4.积分(暂时没实现) 把问题分解:1.首要难点移动,将移动进行分解,分为上下左右移动: 2.用什么记录位置,怎样记录每个方块的值,边界,相同值相

用javascript实现2048的小游戏

前段时间,看了一个视频,用javascript实现的2048小游戏,发现不难,都是一些基出的语法和简单逻辑. 整个2048游戏没有很多的数据,所有,实现起来还是很有成就感的. 先上图,简直就和原版游戏一样一样的. 下面分享一下整个2048游戏的代码逻辑: 首先,搭建游戏框架 其次,开始我们的代码编写 index.html <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type"

分享一下自己写的2048游戏(3*3,4*4,5*5,6*6多种玩法,可反悔)

2048是一款非常常见的小游戏,所以我也想自己尝试着写一款,给自己练练手.说道练手,这里需要交代一下:我从事Android的工作刚刚一年,平时的工作主要是客制化UI和修改Bug,也就是这里改改,那里改改,因此,完整的开发项目的机会比较少,所以,对我而言,想要提高自己的编程水平,抽出时间自己做一些小项目是有意义的.虽然平时的工作主要是客制化UI和修改bug,但并不意味这我的工作是简单枯燥的,我时常会遇到系统中的一些bug,这样我有机会阅读android系统的源码,并从中分析问题出现的原因,这份工作

用javascript实现一个2048游戏

早就想自己写一个2048游戏了,昨晚闲着没事,终于写了一个如下图,按方向键开始玩吧.如果觉得操作不方便,请直接打开链接玩吧:http://gujianbo.1kapp.com/2048/2048.html 附上源代码链接:https://github.com/gujianbo/js2048 个人博客地址:http://gujianbo.1kapp.com/ 新浪微博:http://weibo.com/gujianbobo 欢迎读者交流讨论并提出宝贵意见. 用javascript实现一个2048游

280行代码:Javascript 写的2048游戏

2048 原作者就是用Js写的,一直想尝试,但久久未动手. 昨天教学生学习JS代码.不妨就做个有趣的游戏好了.2048这么火,是一个不错的选择. 思路: 1. 数组 ,2维数组4x4 2. 移动算法,移动后有数字的对齐,无数字(我用的0,但不显示)补齐. 移动前 移动后(注意程序合并了第一行2个2,并产生了新的2) 移动算法分2步: 第一步骤:移动 第二步骤:合并 移动代码参考: [html] view plaincopy function left(t,i) { var j; var len 

最少javascript代码完成一个2048游戏

原生javascript代码写的2048游戏.建议在谷歌浏览器下跑.'WASD'控制方向.演示地址请移步:http://runjs.cn/detail/bp8baf8b 直接贴代码~ html: <!DOCTYPE> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/htm

js+css 写出 简单2048游戏

新手写的,可能不是很完善,欢迎修改及探讨 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>2048游戏</title> 6 <style> 7 .container{ 8 width: 600px; 9 height: 600px; 10 border: 2px solid

Web版2048游戏制作

写在前面 工作之余参与了<慕课网2048游戏制作>的学习视频,视频断断续续看完了,游戏也制作成功了.因为其他的事情也没来的及总结,一拖时间也就过去了,整理磁盘的时候发现了2048源码,思考一下还是将之push到github上了(后面贴出),也顺便写篇总结,回顾一下,同时也谢谢liuyubobobo老师的授课. 不过源码在手,不运行下玩玩,怎么说的过去呢,哈哈!下面是游戏截图. 大图是PC端运行的效果,小图则是在iphone5s上的运行效果(Chrome浏览器debug,具体如何做参考文章:ht

2048游戏详解

由于最近在百度IFE看到有2048任务,所以昨天兴趣一来自己也做了一个.大概花了五个小时完成,不过不足之处是操作时没有滑动效果.昨晚新增了手机版本,流畅度还可以,不过由于没有滑动,游戏过程显得很突兀啊,且容我下次再加上吧.下面先讲讲这个游戏怎么实现,这是个人想的方法.不足之处,多多指教啊. 首先我在做这个小游戏的时候我想到了两种方法:第一种方法就是本例用到的方法,利用方向键操作,只改变相应DIV块的背景以及更改文字,其特点是16个DIV的位置是固定不变的;第二种方法就是通过定位来实现,操作方向键