使用html+css+JavaScript实现2048

关于游戏

《2048》,是一款益智小游戏,这款游戏是由年仅19岁的意大利程序员加布里勒希鲁尼(Gabriele Cirulli)开发出来的,官方版本只能在网页上或通过其移动网站运行。
2048游戏共有16个格子,初始时会有两个格子上安放了两个数字2,每次可以选择上下左右其中一个方向去滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢外,系统也会在空白的地方随即出现一个数字方块,相同数字的方块在靠拢、相撞时会相加。系统给予的数字方块不是2就是4,玩家要想办法在这小小的16格范围中凑出“2048”这个数字方块。
(以上文字来源于搜狗百科)

关于代码

利用了html+css+JavaScript协作完成,以下是我的代码

html代码

<!doctype html>
<html lang="hahaha" >
<head>
    <meta charset="UTF-8">
    <meta name="2048"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" type="text/css" href="style.css" >
    <script src="support.js"></script>
    <script src="gamePlay.js"></script>
    <script src="control.js"></script>
    <script src="main.js"></script>

</head>
<body>
<div class="game">
    <div>
        <header>
            <p>贰 零 肆 捌</p>
        </header>
        <button class="buttons" id="newGame" onclick="newGame()">
            New Game
        </button>
    </div>
    <div id="score">
        !score!
    </div>
    <div class="gamePlatform">
        <div class="gamePlace" id="gamePlace_0_0">
        </div>
        <div class="gamePlace" id="gamePlace_0_1">2
        </div>
        <div class="gamePlace" id="gamePlace_0_2">4
        </div>
        <div class="gamePlace" id="gamePlace_0_3">8
        </div>
        <div class="gamePlace" id="gamePlace_1_0">16
        </div>
        <div class="gamePlace" id="gamePlace_1_1">32
        </div>
        <div class="gamePlace" id="gamePlace_1_2">64
        </div>
        <div class="gamePlace" id="gamePlace_1_3">128
        </div>
        <div class="gamePlace" id="gamePlace_2_0">256
        </div>
        <div class="gamePlace" id="gamePlace_2_1">512
        </div>
        <div class="gamePlace" id="gamePlace_2_2">1024
        </div>
        <div class="gamePlace" id="gamePlace_2_3">2048
        </div>
        <div class="gamePlace" id="gamePlace_3_0">4096
        </div>
        <div class="gamePlace" id="gamePlace_3_1">8192
        </div>
        <div class="gamePlace" id="gamePlace_3_2">#14
        </div>
        <div class="gamePlace" id="gamePlace_3_3">#15
        </div>
    </div>
    <script>
        changeColor()
    </script>
    <div class="gameOver" id="gameOver">
        !G!A!M!E!&nbsp; &nbsp; &nbsp;!O!V!E!R!
    </div>
    <div class="gameOver" id="toStart">
        <p>使用键盘上下左右或右下控制盘控制</p>
        <button class="buttons" id="start" onclick="start()">
            开始游戏
        </button>
    </div>
    <div class="gameOver" id="name">
        <p id="toName">为自己取名{小于8个字符)</p>
        <label>
            <input type="text" id="nameLine" placeholder="unnamed">
        </label>
        <button class="buttons" id="nameOk" onclick="nameCheck()">
            就这个名字了
        </button>
    </div>
    <div class="controlEr" id="controlEr">
        <div class="controlButton" id="up" onmousedown="upKeyDown()" onmouseup="upKeyUp()">
            ▲
        </div>
        <div class="controlButton" id="left" onmousedown="leftKeyDown()" onmouseup="leftKeyUp()">
            ◀
        </div>
        <div class="controlButton" id="down" onmousedown="downKeyDown()" onmouseup="downKeyUp()">
            ▼
        </div>
        <div class="controlButton" id="right" onmousedown="rightKeyDown()" onmouseup="rightKeyUp()">
            ▶
        </div>
    </div>

</div>
<div class="name">
    <div id="nameRightNow">
        当前使用id:unnamed
    </div>
    <div>
        <button id="reName" class="buttons" onclick="rename()">
            重新命名
        </button>
    </div>
</div>
<div class="sideWindow">
    <div class="windowTitle">
        历史分数
    </div>
    <div id="history">

    </div>
</div>
<div class="sideWindow_2">
    <div class="windowTitle">
        排行榜
    </div>
    <div id="topPlayer">
        <div id="top1">

        </div>
        <div id="top2">

        </div>
        <div id="top3">

        </div>
    </div>
</div>
</body>
</html>

css代码

header{
    text-align: center;
    font-size: xx-large;
    font-family: 楷体, fantasy;
}

.game{
    float: left;
    position: relative;
    left: 50%;
    top: 25px;
    transform: translate(-50%,0);
    background: rosybrown;
    width: 480px;
    height: 650px;
}



.gamePlatform{
    float: left;
    position: absolute;
    left: 50%;
    top: 200px;
    padding: 10px;
    border-radius: 3em;
    transform: translate(-50%,0);
    background: bisque;
    width: 400px;
    height: 400px;
}

.gamePlace{
    float: left;
    position: relative;
    margin: 10px;
    width: 80px;
    height: 80px;
    border-radius: 2em;
    background: aliceblue;
    text-align: center;
    font-size: xx-large;
    font-family: 汉仪乐喵体简, serif;
    line-height: 80px;
}

.gameOver{
    float: left;
    position: absolute;
    left: 50%;
    top: 350px;
    width: 250px;
    height: 150px;
    border-radius: 0.5em;
    transform: translate(-50%,0);
    background: darkgray;
    filter:alpha(Opacity=60);
    -moz-opacity:0.6;
    opacity: 0.6;
    line-height: 150px;
    text-align: center;
}

.buttons{
    float: contour;
    position: relative;
    left: 50%;
    transform: translate(-50%,0);
    padding: 5px;
    border-radius: 1em;
}

.controlEr{
    font-size: xx-large;
    float: right;
    position: absolute;
    top: 500px;
    right: -25%;
}

.controlButton{
    float: left;
    position: absolute;
    color: #e5b49a;
    text-shadow:2px 2px #655d60;
}

.sideWindow{
    width: 400px;
    height: 300px;
    float: left;
    position: absolute;
    background: #ececec;
    filter: alpha(opacity=80);
    opacity: 0.5;
    border: 1.5px #655d60 solid;
    left: 3%;
    top: 50px;
    overflow: scroll;
}

.sideWindow_2{
    width: 400px;
    height: 90px;
    float: left;
    position: absolute;
    background: #ececec;
    filter: alpha(opacity=80);
    opacity: 0.5;
    border: 1.5px #655d60 solid;
    left: 3%;
    top: 400px;
}

.windowTitle{
    background: #655d60;
    text-align: center;
}

.name{
    float: right;
    position: absolute;
    right: 2%;
    top: 20px;
}

#score{
    text-align: center;
    font-size: x-large;
    font-family: 黑体, monospace;
}

#gameOver{
    display: none;
}

#toStart{
    display: inline;
    line-height: 30px;
}

#start{
    filter:alpha(Opacity=100);
    -moz-opacity:1;
    opacity: 1;
    left: 17%;
}

#name{
    filter:alpha(Opacity=100);
    -moz-opacity:1;
    opacity: 1;
    line-height: 20px;
}

#controlEr{
    height: 94px;
    width: 94px;
    background: #fcfcda;
    border-radius: 47px;
}

#up{
    top: -4px;
    left: 30px;
}

#down{
    top: 56px;
    left: 30px;
}

#left{
    top: 26px;
    left: 0;
}

#right{
    top: 26px;
    left: 60px;
}

#score{
    float: right;
    position: absolute;
    top: 150px;
    right: 50%;
    transform: translate(50%,0);
}

#history{
    overflow: hidden;
}

#nameOk{
    float: left;
    position: relative;
    top: 20px;
    left: 50%;
    transform: translate(-50% 0);
}


JavaScript代码

这部分代码分成了几部分来写,在实际使用中只要分开保存并且确保html中载入了每一个JavaScript文件的src就可以保证全部得到执行

main.js

let score=0;
let board=[];
let add=[];
let id="unnamed";
let top1=0;
let top2=0;
let top3=0;

/*
function check() {//检查代码,后期消除
    document.getElementById("gameOver").style.display="none";
    score=0;
    changeColor();
    inBoard();
}
*/

function start() {//起初的开始游戏按键
    document.getElementById("toStart").style.display="none";
    score=0;
    cleanBoard();
    inBoard();
    newNumber();
    newNumber();
    changeColor();
}

function gameOver() {//你死了
    document.getElementById("gameOver").style.display="inline";
}

function newGame() {//新游戏
    scoreSet();
    document.getElementById("gameOver").style.display="none";
    score=0;
    showScore();
    cleanBoard();
    inBoard();
    newNumber();
    newNumber();
    changeColor();
}

function  nameCheck(){
    let name=document.getElementById("nameLine").value;
    let nameLength=name.length;
    if(nameLength>8){
        document.getElementById("toName").innerText="to much words";
    }
    else if (nameLength===0){
        id="unnamed";
        document.getElementById("name").style.display="none";
        showName(id);
    }
    else{
        id=name;
        document.getElementById("name").style.display="none";
        showName(id);
    }
}

function rename(){
    document.getElementById("name").style.display="inline";
}

control.js

//移动指令响应
//键盘指令输入
document.onsystemevent = grabEvent;
document.onkeypress = grabEvent;
document.onirkeypress = grabEvent;
document.onkeyup = grabEvent;
function grabEvent() {
    let it = event.which||event;
    switch (it) {
        case 3:
        case 37:
        case 271://left
            moveLeft();
            showScore();
            break;
        case 1:
        case 38:
        case 269://up
            moveUp();
            showScore();
            break;
        case 4:
        case 39:
        case 272://right
            moveRight();
            showScore();
            break;
        case 2:
        case 40:
        case 270://down
            moveDown();
            showScore();
            break;
    }
}

function upKeyDown() {
    moveUp();
    showScore();
    document.getElementById("up").style.textShadow="0 0";
}

function rightKeyDown() {
    moveRight();
    showScore();
    document.getElementById("right").style.textShadow="0 0";
}

function downKeyDown() {
    moveDown();
    showScore();
    document.getElementById("down").style.textShadow="0 0";
}

function leftKeyDown() {
    moveLeft();
    showScore();
    document.getElementById("left").style.textShadow="0 0";
}

function upKeyUp() {
    document.getElementById("up").style.textShadow="2px 2px #655d60";
}

function rightKeyUp() {
    document.getElementById("right").style.textShadow="2px 2px #655d60";
}

function downKeyUp() {
    document.getElementById("down").style.textShadow="2px 2px #655d60";
}

function leftKeyUp() {
    document.getElementById("left").style.textShadow="2px 2px #655d60";
}

support.js

function scoreSet() {
    setHistory();
    setTop();
}

let date=new Date();

function setHistory() {//显示历史成绩
    let m=date.getMonth()+1;
    let d=date.getFullYear()+"年"+m+"月"+date.getDate()+"日"+date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();
    let x=document.createElement("div");
    x.innerText=d+" "+id+"  "+score;
    let firstChild=document.getElementById("history").firstChild;
    document.getElementById("history").insertBefore(x,firstChild);
}

function setTop() {
    if(score>top1){
        putTop1();
        return true;
    }
    if(score>top2){
        putTop2();
        return true;
    }
    if(score>top3){
        putTop3();
        return true;
    }
}

function putTop1() {
    document.getElementById("top3").innerText=document.getElementById("top2").innerText;
    top3=top2;
    document.getElementById("top2").innerText=document.getElementById("top1").innerText;
    top2=top1;
    let m=date.getMonth()+1;
    let d=date.getFullYear()+"年"+m+"月"+date.getDate()+"日"+date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();
    document.getElementById("top1").innerText=d+" "+id+"  "+score;
    top1=score;
}

function putTop2() {
    document.getElementById("top3").innerText=document.getElementById("top2").innerText;
    top3=top2;
    let m=date.getMonth()+1;
    let d=date.getFullYear()+"年"+m+"月"+date.getDate()+"日"+date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();
    document.getElementById("top2").innerText=d+" "+id+"  "+score;
    top2=score;
}

function putTop3() {
    let m=date.getMonth()+1;
    let d=date.getFullYear()+"年"+m+"月"+date.getDate()+"日"+date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();
    document.getElementById("top3").innerText=d+" "+id+"  "+score;
    top3=score;
}

function inBoard() {//格子初始化
    for(let i = 0;i<4;i++) {
        board[i] = [];
        for (let j = 0; j < 4; j++) {
            board[i][j] = 0;
        }
    }
}


function cleanAdd() {//清空格子合并的统计集
    for(let i = 0;i<4;i++) {
        add[i] = [];
        for (let j = 0; j < 4; j++) {
            add[i][j] = 0;
        }
    }
}

function cleanBoard() {//清理格子
    for(let i=0;i<4;i++)
        for(let j=0;j<4;j++) {
            let temp = document.getElementById("gamePlace_" + i + "_" + j);
            temp.innerText = "";
        }
}

function newNumber(){//生成随机的格子
    if (spaceCheck(board)===false) {
        return false;
    }
    let randx = Math.floor(Math.random()*4);
    let randy = Math.floor(Math.random()*4);
    while(true){
        if (board[randx][randy]===0)
            break;
        randx = Math.floor(Math.random()*4);
        randy = Math.floor(Math.random()*4);
    }
    let randNumber = Math.random()<0.5 ? 2 : 4;
    //在随机位置显示随机数字2or4
    board[randx][randy] = randNumber;
    score+=board[randx][randy];
    showNumber(randx,randy,randNumber);
    return true;
}

function showNumber(randx,randy,num) {//显示出数字
    let temp = document.getElementById("gamePlace_" + randx + "_" + randy);
    if(num===0){
        temp.innerText="";
    }
    else
        temp.innerText=num;
}

function showAllNumber(board) {
    for(let i=0;i<4;i++)
        for(let j=0;j<4;j++){
            let e=board[i][j];
            showNumber(i,j,e);
        }
}

function spaceCheck(board) {//监测是否有空余空间
    for(let i = 0;i<4;i++) {
        for (let j = 0; j < 4; j++) {
            if(board[i][j] === 0)
                return true;
        }
    }
    return false;
}

function showScore() {//更新当前分数
    document.getElementById("score").innerText="score:"+score;
}

function showName(id) {
    document.getElementById("nameRightNow").innerText="当前使用id:"+id;
}

function changeColor() {//颜色读取
    for(let i=0;i<4;i++)
        for(let j=0;j<4;j++)
        {
            let temp=document.getElementById("gamePlace_"+i+"_"+j);
            if(temp.innerText==="16384")
                temp.innerText="#14";
            if(temp.innerText==="32768")
                temp.innerText="#15";
            if(temp.innerText==="65536")
                temp.innerText="#16";
            if(temp.innerText==="")
                temp.style.background="aliceblue";
            if(temp.innerText==="2")
                temp.style.background="#fafbb0";
            if(temp.innerText==="4")
                temp.style.background="#cbd781";
            if(temp.innerText==="8")
                temp.style.background="#d0ce4a";
            if(temp.innerText==="16")
                temp.style.background="#d1a735";
            if(temp.innerText==="32")
                temp.style.background="#ffbab5";
            if(temp.innerText==="64")
                temp.style.background="#fb918a";
            if(temp.innerText==="128")
                temp.style.background="#fb4855";
            if(temp.innerText==="256")
                temp.style.background="#fb7ce6";
            if(temp.innerText==="512")
                temp.style.background="#9c82d1";
            if(temp.innerText==="1024")
                temp.style.background="#7376d0";
            if(temp.innerText==="2048")
                temp.style.background="#57aabd";
            if(temp.innerText==="4096")
                temp.style.background="#3f887c";
            if(temp.innerText==="8192")
                temp.style.background="#318853";
            if(temp.innerText==="#14")
                temp.style.background="#1c682c";
            if(temp.innerText==="#15")
                temp.style.background="#2c4816";
            if(temp.innerText==="#16")
                temp.style.background="#3a4811";
        }
}

gamePlay.js


function isGameOver() {//你死了
    if(canMoveLeft()===false&&canMoveRight()===false&&canMoveDown()===false&&canMoveUp()===false)
        gameOver();
}

function moveLeft() {//移动的过程
    if(canMoveLeft()===false)
        return false;
    cleanAdd();
    for(let i=0;i<4;i++)
        for(let j=1;j<4;j++){
            if(board[i][j]!==0)
                for(let k=j;k>0;k--){
                    if(board[i][k-1]===0){
                        board[i][k-1]=board[i][k];
                        board[i][k]=0;
                        add[i][k-1]=add[i][k];
                        add[i][k]=0;
                    }
                    if(board[i][k-1]===board[i][k]&&add[i][k-1]===0&&add[i][k]===0){
                        board[i][k-1]*=2;
                        score+=board[i][k-1];
                        board[i][k]=0;
                        add[i][k]=0;
                        add[i][k-1]+=1;
                    }
                }

        }
    showAllNumber(board);
    newNumber();
    changeColor();
    isGameOver();
}

function moveRight() {
    if(canMoveRight()===false)
        return false;

    cleanAdd();
    for(let i=0;i<4;i++)
        for(let j=2;j>=0;j--){
            if(board[i][j]!==0)
                for(let k=j;k<3;k++){
                    if(board[i][k+1]===0){
                        board[i][k+1]=board[i][k];
                        board[i][k]=0;
                        add[i][k+1]=add[i][k];
                        add[i][k]=0;
                    }
                    if(board[i][k+1]===board[i][k]&&add[i][k+1]===0&&add[i][k]===0){
                        board[i][k+1]*=2;
                        score+=board[i][k+1];
                        board[i][k]=0;
                        add[i][k]=0;
                        add[i][k+1]+=1;
                    }
                }
        }
    showAllNumber(board);
    newNumber();
    changeColor();
    isGameOver();
}

function moveUp() {
    if(canMoveUp()===false)
        return false;

    cleanAdd();
    for(let j=0;j<4;j++)
        for(let i=1;i<4;i++){
            if(board[i][j]!==0)
                for(let k=i;k>0;k--){
                    if(board[k-1][j]===0){
                        board[k-1][j]=board[k][j];
                        board[k][j]=0;
                        add[k-1][j]=add[k][j];
                        add[k][j]=0;
                    }
                    if(board[k-1][j]===board[k][j]&&add[k-1][j]===0&&add[k][j]===0){
                        board[k-1][j]*=2;
                        score+=board[k-1][j];
                        board[k][j]=0;
                        add[k][j]=0;
                        add[k-1][j]+=1;
                    }
                }

        }
    showAllNumber(board);
    newNumber();
    changeColor();
    isGameOver();
}

function moveDown() {
    if(canMoveDown()===false)
        return false;

    cleanAdd();
    for(let j=0;j<4;j++)
        for(let i=2;i>=0;i--){
            if(board[i][j]!==0)
                for(let k=i;k<3;k++){
                    if(board[k+1][j]===0){
                        board[k+1][j]=board[k][j];
                        board[k][j]=0;
                        add[k+1][j]=add[k][j];
                        add[k][j]=0;
                    }
                    if(board[k+1][j]===board[k][j]&&add[k+1][j]===0&&add[k][j]===0){
                        board[k+1][j]*=2;
                        score+=board[k+1][j];
                        board[k][j]=0;
                        add[k][j]=0;
                        add[k+1][j]+=1;
                    }
                }

        }
    showAllNumber(board);
    newNumber();
    changeColor();
    isGameOver();
}


function canMoveLeft(){//可以移动的判定
    for (let i=0;i<4;i++)
        for (let j=0;j<4;j++){
            if(board[i][j]!==0&&j!==0)
                if(board[i][j-1]===0||board[i][j-1]===board[i][j])
                    return true;
        }
    return false;
}

function canMoveRight(){
    for (let i=0;i<4;i++)
        for (let j=0;j<4;j++){
            if(board[i][j]!==0&&j!==3)
                if(board[i][j+1]===0||board[i][j+1]===board[i][j])
                    return true;
        }
    return false;
}

function canMoveUp(){
    for (let i=0;i<4;i++)
        for (let j=0;j<4;j++){
            if(board[i][j]!==0&&i!==0)
                if(board[i-1][j]===0||board[i-1][j]===board[i][j])
                    return true;
        }
    return false;
}

function canMoveDown(){
    for (let i=0;i<4;i++)
        for (let j=0;j<4;j++){
            if(board[i][j]!==0&&i!==3)
                if(board[i+1][j]===0||board[i+1][j]===board[i][j])
                    return true;
        }
    return false;
}

写的原因

寒假作业嘛。。。写就是了

仍然有的缺陷

在编码到“排行榜”部分时数组的使用出现了一些问题,在代码中_数组_的使用出现了一些问题,这很大程度上影响到了代码的简洁和效果,希望之后可以找到办法改吧。。

最后,github

git@github.com:guixv/2048.git

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值