JS——利用面向对象的思想实现2048

html部分代码

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>2048</title>
    <link rel="stylesheet" href="css/2048.css">
</head>

<body>
    <header>
        <div class="container">
            <h1><span>2</span><span>0</span><span>4</span><span>8</span></h1>
            <p class="inspired">2048</p>
        </div>
    </header>
    <div class="container">
        <div class="directions">
            <p><strong>如何玩:</strong> 使用你的箭头键移动瓷砖。两个瓷砖相互滑动时,它们合并成一个!</p>
        </div>
        <div class="scores">
            <div class="score-container">
                分数:
                <div class="score">
                    <div id="score">0</div>
                    <div class="add" id="add"></div>
                </div>
            </div>
        </div>
        <div class="game">
            <div class="main_box">
                <div class="min_box" id="number00"></div>
                <div class="min_box" id="number01"></div>
                <div class="min_box" id="number02"></div>
                <div class="min_box" id="number03"></div>
                <div class="min_box" id="number10"></div>
                <div class="min_box" id="number11"></div>
                <div class="min_box" id="number12"></div>
                <div class="min_box" id="number13"></div>
                <div class="min_box" id="number20"></div>
                <div class="min_box" id="number21"></div>
                <div class="min_box" id="number22"></div>
                <div class="min_box" id="number23"></div>
                <div class="min_box" id="number30"></div>
                <div class="min_box" id="number31"></div>
                <div class="min_box" id="number32"></div>
                <div class="min_box" id="number33"></div>
            </div>
            <div class="end" id="end">游戏结束
                <div class="monkey"></div>
                <button class="btn not-recommended__item js-restart-btn" id="try-again">再来一次</button>
            </div>
        </div>
        <div class="not-recommended">
            <button class="btn not-recommended__item js-restart-btn" id="restart">重新开始游戏</button>
        </div>
        <script src="js/2048.js"></script>
</body>

</html>

css部分

* {
    margin: 0px;
    padding: 0px;
}

.case {
    width: 450px;
    height: 600px;
    margin: 20px auto;
    position: relative;
}

.above_box {
    width: 450px;
    height: 150px;
    margin: 0px auto;
}

.logo {
    width: 350px;
    height: 150px;
    float: left;
}

.logo_num {
    color: #766f67;
    font-size: 60px;
    font-family: '微软雅黑';
    font-weight: bold;
}

.logo_font {
    color: #9B988F;
    float: left;
    font-size: 16px;
}

.above_box button {
    width: 100px;
    height: 50px;
    color: white;
    font-size: 15px;
    background-color: #8b7c65;
    border: none;
    margin-top: 10px;
    float: right;
}

.countScore {
    width: 100px;
    height: 70px;
    background-color: #8b7c65;
    color: white;
    float: right;
    margin-top: 10px;
}

.countScore p {
    line-height: 30px;
    text-align: center;
}

.countScore span {
    display: block;
    line-height: 30px;
    text-align: center;
    font-weight: bold;
    font-size: 20px;
}

.main_box {
    width: 450px;
    height: 450px;
    margin: 0px auto;
    background-color: #bbada0;
    border-radius: 10px;
}

.main_box2 {
    width: 450px;
    height: 450px;
    margin: 0px auto;
    border-radius: 10px;
    background-color: rgba(0, 0, 0, 0.4);
    position: absolute;
    font-size: 50px;
    color: white;
    text-align: center;
    line-height: 450px;
}

.main_box2 button {
    width: 101px;
    height: 50px;
    color: white;
    font-size: 20px;
    background-color: rgba(0, 0, 0, 0);
    border: none;
    position: absolute;
    top: 260px;
    left: 165px;
}

.game {
    z-index: 1;
}

.min_box {
    width: 100px;
    height: 100px;
    background-color: #ccc0b2;
    float: left;
    margin: 10px 0 0 10px;
    border-radius: 5px;
    font-size: 35px;
    line-height: 100px;
    text-align: center;
    color: #796f65;
}

.n2 {
    background-color: #aae3da
}

.n4 {
    background-color: #ede0c8
}

.n8 {
    background-color: #f2b179
}

.n16 {
    background-color: #f59563
}

.n32 {
    background-color: #f67c5f
}

.n64 {
    background-color: #f65e3b
}

.n128 {
    background-color: #edcf72
}

.n256 {
    background-color: #edcc61
}

.n512 {
    background-color: #9c0
}

.n1024 {
    background-color: #33b5e5
}

.n2048 {
    background-color: #09c9c0
}

.n4096 {
    background-color: #a6c
}

.n8192 {
    background-color: #93c
}

.n2,
.n4 {
    color: #776e65
}

.n1024,
.n2048,
.n4096,
.n8192 {
    font-size: 40px
}

.btn {
    font-family: inherit;
    font-size: 1rem;
    border: none;
    background: #1B9AAA;
    letter-spacing: 1px;
    color: white;
    font-weight: 300;
    padding: 0.9em 1.5em;
    border-radius: 3px;
    border: 1px solid transparent;
    cursor: pointer;
}

.btn:hover {
    background-color: #14727e;
}

.btn:active {
    background-color: #0d4a52;
}

.btn:focus {
    box-shadow: 0 0 10px #0d4a52 inset;
    outline: none;
}

.not-recommended {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    justify-content: center;
    -webkit-box-align: center;
    -ms-flex-align: center;
    align-items: center;
    margin-top: 3rem;
}

body,
html {
    position: relative;
    width: 100%;
    height: 100%;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
    -ms-flex-direction: column;
    flex-direction: column;
    font-family: "Arvo", Helvetica, sans-serif;
    font-family: 12px;
    color: #555;
    background: #F8FFE5;
}

strong {
    font-weight: bold;
}

p {
    line-height: 1.6;
}

.inspired {
    height: 20px;
    font-size: 0.9rem;
    color: #9a9a95;
}

header {
    height: 120px;
    color: #F8FFE5;
    text-align: center;
}

header span {
    display: inline-block;
    box-sizing: border-box;
    width: 4rem;
    height: 4rem;
    line-height: 4rem;
    margin: 0 0.4rem;
    background: #FFC43D;
}

header span:nth-of-type(2) {
    background: #EF476F;
}

header span:nth-of-type(3) {
    background: #1B9AAA;
}

header span:nth-of-type(4) {
    background: #06D6A0;
}

h1 {
    font-size: 2.2rem;
}

.directions {
    padding: 1rem;
    border-top: 1px solid #9a9a95;
    border-bottom: 1px solid #9a9a95;
}

.container {
    margin: 0 auto;
    padding-bottom: 3.5rem;
    -webkit-box-flex: 1;
    -ms-flex: 1;
    flex: 1;
    width: 100%;
    max-width: 550px;
    text-align: center;
}

header .container {
    padding: 0;
    padding: 2rem 4rem;
    max-width: 900px;
}

.scores {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    justify-content: center;
}

.score-container {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    justify-content: center;
    -webkit-box-align: center;
    -ms-flex-align: center;
    align-items: center;
    margin: 1.8rem;
    font-size: 1.2rem;
    line-height: 1;
    color: #555;
}

.score-container.best-score {
    color: #9a9a95;
}

.score {
    margin-left: 1rem;
    position: relative;
    font-weight: bold;
    font-size: 1.5rem;
    vertical-align: middle;
    text-align: right;
}

.game {
    position: relative;
    margin: 0 auto;
    background: #9a9a95;
    padding: 7px;
    display: inline-block;
    border-radius: 3px;
    box-sizing: border-box;
}

.tile-container {
    border-radius: 6px;
    position: relative;
    width: 400px;
    height: 400px;
}

.game {
    position: relative;
    margin: 0 auto;
    background: #9a9a95;
    padding: 7px;
    display: inline-block;
    border-radius: 3px;
    box-sizing: border-box;
}

.tile-container {
    border-radius: 6px;
    position: relative;
    width: 400px;
    height: 400px;
}

.tile,
.background {
    display: block;
    color: #F8FFE5;
    position: absolute;
    width: 100px;
    height: 100px;
    box-sizing: border-box;
    text-align: center;
}

.background {
    z-index: 1;
    text-align: center;
    border: 7px solid #9a9a95;
    background-color: #F8FFE5;
}

.tile {
    opacity: 0;
    z-index: 2;
    background: #FFC43D;
    color: #F8FFE5;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-align: center;
    -ms-flex-align: center;
    align-items: center;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    justify-content: center;
    font-size: 1.8rem;
    align-items: center;
    -webkit-transition: 110ms ease-in-out;
    transition: 110ms ease-in-out;
    border-radius: 3px;
    border: 7px solid #9a9a95;
    box-sizing: border-box;
}

.end {
    opacity: 0;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: -1;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
    -ms-flex-direction: column;
    flex-direction: column;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    justify-content: center;
    -webkit-box-align: center;
    -ms-flex-align: center;
    align-items: center;
    background: rgba(85, 85, 85, 0.4);
    color: white;
    font-size: 2rem;
    -webkit-transition: opacity 0.3s ease-in-out;
    transition: opacity 0.3s ease-in-out;
}

.end .btn {
    margin-top: 1rem;
}

.end.active {
    opacity: 1;
    z-index: 1000;
}

JS部分

var game = {
    // 定义二维数组
    data: [],
    // 定义行数
    RN: 4,
    // 定义列数
    CN: 4,
    //记录分数
    score: 0,
    // 游戏结束
    gameover: 0,

    // 游戏开始
    start() {
        // 初始化数组
        this.data = [
            [0, 0, 0, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ];
        this.score = 0;
        var that = this;
        // 生成开始的二个随机位置的随机2或4
        this.randomNum();
        this.randomNum();
        // 渲染函数
        this.updataeView();
        // 定义4个键盘事件    
        document.onkeydown = function(e) {
            switch (e.keyCode) {
                case 37: //左移
                    that.moveLeft();
                    break;
                case 38: // 上移
                    that.moveUp();
                    break;
                case 39: // 右移
                    that.moveRight();
                    break;
                case 40: // 下移
                    that.moveDown();
                    break;
            }
        };
    },

    // 定义随机函数
    randomNum() {
        var r, c;
        // 判断数组中但前位置是否为空
        while (true) {
            r = parseInt(Math.random() * this.RN);
            c = parseInt(Math.random() * this.CN);
            if (this.data[r][c] == 0) {
                this.data[r][c] = Math.random() < 0.6 ? 2 : 4;
                break;
            } else if (this.isFull()) {
                break;
            }
        }
    },

    // 定义渲染函数
    updataeView() {
        for (var r = 0; r < this.RN; r++) {
            for (var c = 0; c < this.CN; c++) {
                if (this.data[r][c]) {
                    // 不为0 将值赋给div
                    document.getElementById("number" + r + c).innerHTML = this.data[r][c];
                    // 上色
                    document.getElementById("number" + r + c).className = "min_box n" + this.data[r][c];
                } else {
                    document.getElementById("number" + r + c).innerHTML = "";
                    document.getElementById("number" + r + c).className = "min_box n";
                }
            }
        }
        //更新分数
        document.getElementById("score").innerHTML = this.score;
    },

    // 左移前拍照
    moveLeft() {
        for (var r = 0; r < this.RN; r++) { //遍历data中的每一列
            this.moveLeftdown(r); //上移当前行
        }
        // 先判断是否是满格 
        //      不是满格 生成随机数
        // 是满格 判断游戏是否结束
        if (!this.isFull()) {
            this.randomNum();
            this.updataeView();
        } else if (this.gameOver()) {
            this.start = this.gameOver;
        }
    },
    // 左移事件
    moveLeftdown(r) {
        //c从0开始,遍历当前列中的元素,到<CN-1结束,每次+1
        for (var c = 0; c < this.CN; c++) {
            //找到r之后下一个不为0的值的位置,存在nextc中
            var nextc = this.moveLeftinrow(r, c);
            //找到c之后下一个不为0的值的位置,存在nextc中
            if (nextc == -1) {
                break; //如果nextr等于-1,退出循环
            } else {
                if (this.data[r][c] == 0) { //如果当前位置等于0
                    this.data[r][c] = this.data[r][nextc]; //将当前位置设为下一个位置的值
                    this.data[r][nextc] = 0; //将下一位置设为0
                    c--; //保证下次依然检查当前元素
                } else if (this.data[r][c] == this.data[r][nextc]) {
                    this.data[r][c] *= 2; //当前位置 = 当前位置值*2
                    this.data[r][nextc] = 0; // 将下一位置设为0
                    this.score += this.data[r][c]; // 增加分数
                }
            }
        }
    },
    // 找r行c列位置之后,不为0的下一个位置
    moveLeftinrow(r, c) {
        for (var i = c + 1; i < this.CN; i++) { //i+1开始,遍历r行剩余元素
            if (this.data[r][i] != 0) { //如果i不等于0
                return i;
            }
        }
        return -1; //循环结束,返回-1
    },

    // 上移前拍照
    moveUp() {
        // 判断是否移动
        for (var c = 0; c < this.CN; c++) { //遍历data中的每一列
            this.moveUpdown(c); //右移当前行
        }
        // 先判断是否是满格 
        //      不是满格 生成随机数
        // 是满格 判断游戏是否结束
        if (!this.isFull()) {
            this.randomNum();
            this.updataeView();
        } else if (this.gameOver()) {
            this.start = this.gameOver;
        }
    },
    //上移事件
    moveUpdown(c) {
        //r从0开始,遍历当前列中的元素,到<RN-1结束,每次+1
        for (var r = 0; r < this.RN - 1; r++) {
            //找到c之后下一个不为0的值的位置,存在next中
            var nextr = this.moveUpinrow(r, c);
            if (nextr == -1) {
                break; //如果nextr等于-1,退出循环
            } else {
                if (this.data[r][c] == 0) { //如果当前位置等于0
                    this.data[r][c] = this.data[nextr][c]; //将当前位置设为下一个位置的值
                    this.data[nextr][c] = 0; //将下一位置设为0
                    r--; //保证下次依然检查当前元素
                } else if (this.data[r][c] == this.data[nextr][c]) { //否则,如果当前位置等于下一位置
                    this.data[r][c] *= 2; //当前位置 = 当前位置值*2
                    this.score += this.data[r][c]; //增加分数
                    this.data[nextr][c] = 0; //将下一位置设为0
                }
            }
        }
    },
    //找r行c列位置之后,不为0的下一个位置
    moveUpinrow(r, c) {
        for (var i = r + 1; i < this.RN; i++) { //i+1开始,遍历c列剩余元素
            if (this.data[i][c] != 0) { //如果i不等于0
                return i;
            }
        }
        return -1; //循环结束,返回-1
    },

    //右移前拍照
    moveRight() {
        for (var r = 0; r < this.RN; r++) { //遍历data中的每一行
            this.moveRightdown(r); //右移当前行
        }
        // 先判断是否是满格 
        //      不是满格 生成随机数
        // 是满格 判断游戏是否结束
        if (!this.isFull()) {
            this.randomNum();
            this.updataeView();
        } else if (this.gameOver()) {
            this.start = this.gameOver;
        }
    },
    //右移事件
    moveRightdown(r) {
        //c从CN-1开始,到>0结束,每次-1
        for (var c = this.CN - 1; c > 0; c--) {
            //找到c之后下一个不为0的值的位置,存在nextc中
            var nextc = this.moveRightinrow(r, c);
            if (nextc == -1) {
                break; //如果nextc等于-1,退出循环
            } else {
                if (this.data[r][c] == 0) { //如果当前位置等于0
                    this.data[r][c] = this.data[r][nextc]; //将当前位置设为下一个位置的值
                    this.data[r][nextc] = 0; //将下一位置设为0
                    c++; //保证下次依然检查当前元素
                } else if (this.data[r][c] == this.data[r][nextc]) { //否则,如果当前位置等于下一位置
                    this.data[r][c] *= 2; //当前位置 = 当前位置值*2
                    this.score += this.data[r][c]; //增加分数
                    this.data[r][nextc] = 0; //将下一位置设为0
                }
            }
        }
    },
    //找r行c列位置之后,不为0的下一个位置
    moveRightinrow(r, c) {
        for (var i = c - 1; i >= 0; i--) { //i从c+1开始,遍历r行剩余元素
            if (this.data[r][i] != 0) { //如果i不等于0
                return i;
            }
        }
        return -1; //循环结束,返回-1
    },

    // 下移前拍照
    moveDown() {
        for (var c = 0; c < this.CN; c++) { //遍历data中的每一列
            this.moveDowndown(c); //下移当前行
        }
        // 先判断是否是满格 
        //      不是满格 生成随机数
        // 是满格 判断游戏是否结束
        if (!this.isFull()) {
            this.randomNum();
            this.updataeView();
        } else if (this.gameOver()) {
            this.start = this.gameOver;
        }
    },
    //下移事件
    moveDowndown(c) {
        //r从RN-1开始,遍历当前列中的元素,到>0结束,每次-1
        for (var r = this.RN - 1; r > 0; r--) {
            //找到c之后下一个不为0的值的位置,存在nextr中
            var nextr = this.moveDowninrow(r, c);
            if (nextr == -1) {
                break; //如果nextr等于-1,退出循环
            } else { //否则
                if (this.data[r][c] == 0) { //如果当前位置等于0
                    this.data[r][c] = this.data[nextr][c]; //将当前位置设为下一个位置的值
                    this.data[nextr][c] = 0; //将下一位置设为0
                    r++; //保证下次依然检查当前元素
                } else if (this.data[r][c] == this.data[nextr][c]) { //否则,如果当前位置等于下一位置
                    this.data[r][c] *= 2; //当前位置 = 当前位置值*2
                    this.score += this.data[r][c]; //增加分数
                    this.data[nextr][c] = 0; //将下一位置设为0
                }
            }
        }
    },
    //找r行c列位置之后,不为0的下一个位置
    moveDowninrow(r, c) {
        for (var i = r - 1; i >= 0; i--) { //i从r-1开始,遍历c列剩余元素
            if (this.data[i][c] != 0) { //如果i不等于0
                return i;
            }
        }
        return -1; //循环结束,返回-1
    },
    //判断游戏状态为结束
    gameOver() {
        //如果没有满,则返回false
        if (!this.isFull()) {
            return false;
        } else {
            //从左上角第一个元素开始,遍历二维数组
            for (var r = 0; r < this.RN; r++) {
                for (var c = 0; c < this.CN; c++) {
                    //如果当前元素不是最右侧元素
                    if (c < this.CN - 1) {
                        // 如果当前元素==右侧元素
                        if (this.data[r][c] == this.data[r][c + 1]) {
                            return false;
                        }
                    }
                    //如果当前元素不是最下方元素
                    if (r < this.RN - 1) {
                        // 如果当前元素==下方元素
                        if (this.data[r][c] == this.data[r + 1][c]) {
                            return false;
                        }
                    }
                }
            }
            return this.gameoverupdate();
        }
    },
    //判断是否满格
    isFull() {
        for (var r = 0; r < this.RN; r++) {
            for (var c = 0; c < this.CN; c++) {
                if (this.data[r][c] == 0) { //如果当前元素等于0
                    return false; //返回false
                }
            }
        }
        return true; //遍历结束,返回true
    },
    gameoverupdate() {
        var end = document.getElementById("end");
        end.classList.add("active")
    },

}

game.start();

var btn = document.getElementsByClassName("btn")[0];
var btn2 = document.getElementsByClassName("btn")[1];
btn.onclick = function() {
    game.start();
    end.classList.remove("active");
    game.score = 0;
}
btn2.onclick = function() {
    game.start();
    game.score = 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值