大货,大货,jquery练习之2048web端游戏的完成

js部分,核心

$(function () {//windows.onload方法
    //是否产生新元素
    var isNewRndItem = false;
    var gameScore = 0;
    //最高分
    var maxScore = 0;

    if (localStorage.maxScore) {
        //在HTML5中,新加入了一个localStorage特性,这个特性主要是用来作为本地存储来使用的,解决了cookie存储空间不足的问题(cookie中每条cookie的存储空间为4k),localStorage中一般浏览器支持的是5M大小,这个在不同的浏览器中localStorage会有所不同。
        maxScore = localStorage.maxScore - 0;
    } else {
        maxScore = 0;
    }//历史最高分的设置

    //游戏初始化
    gameInit();

    function refreshGame() {
        var items = $('.gameBody .row .item');//所有游戏块(.item)
        for (var i = 0; i < items.length; i++) {
            items.eq(i).html('').removeClass('nonEmptyItem').addClass('emptyItem');
            //.html->innerHTML方法
            //.classList.add("类名") 是源生的添加类方法
            //.classList.remove("类名") 是源生的删除类方法
        }
        gameScore = 0;
        //分数清零
        $('#gameScore').html(gameScore);
        //随机生成两个新元素
        newRndItem();//函数方法,之后有详细解释(封装的好处)
        newRndItem();
        //刷新颜色
        refreshColor();
        $('#gameOverModal').modal('hide');
        //BootStrap框架内方法,打开一个浮层,承载相应的操作(弹出对话框)
    }
    /*
    函数详解:功能函数,是用于每次操作后刷新,创建新块
     */


    function getSideItem(currentItem, direction) {
        //当前元素的位置
        var currentItemX = currentItem.attr('x') - 0;//改变数据格式的简单方法!(S->N)不一定用Number()
        var currentItemY = currentItem.attr('y') - 0;
        //.attr的用途1-改变html元素内属性的值(x)
        //2-获取html源生OR自定义属性的值(这里采用的是这种方法)

        //根据方向获取旁边元素的位置
        switch (direction) {
            case 'left':
                var sideItemX = currentItemX;
                var sideItemY = currentItemY - 1;
                break;
            case 'right':
                var sideItemX = currentItemX;
                var sideItemY = currentItemY + 1;
                break;
            case 'up':
                var sideItemX = currentItemX - 1;
                var sideItemY = currentItemY;
                break;
            case 'down':
                var sideItemX = currentItemX + 1;
                var sideItemY = currentItemY;
                break;
        }
        //旁边元素
        //实际意思是要去的地方的元素,通过与其进行判断来判断是否能进行移动
        var sideItem = $('.gameBody .row .x' + sideItemX + 'y' + sideItemY);
        return sideItem;
        //返回值是什么?(目前未知)
        //返回了要去的位置的元素DOM对象
    }
    /*
    函数详解:传入2个参数,请注意!一个用于获得方块的位置,other用于判断方向
 */


    function itemMove(currentItem, direction) {

        var sideItem = getSideItem(currentItem, direction);

        if (sideItem.length == 0) {//当前元素在最边上
            //不动
            //length 属性可返回下拉列表中选项的数目。HTML-DOM操作函数(这个不精确)
            //JQ中 - length 属性包含 jQuery 对象中元素的数目。
            //在此题目中,如果没有相关元素,即不存在移动后x=-1 OR y=-1的元素,就是边上元素,不动
        } else if (sideItem.html() == '') { //当前元素不在最后一个且左(右、上、下)侧元素是空元素
            //首先判断不是最边,而且要移动去的元素位置是空 ''
            sideItem.html(currentItem.html()).removeClass('emptyItem').addClass('nonEmptyItem');
            //sideItem.html(currentItem.html())这段代码是把currentItem.html()<currentItem里面的内容赋值给sideItem.html> ,之后配合迭代,使得数字移动!
            currentItem.html('').removeClass('nonEmptyItem').addClass('emptyItem');
            itemMove(sideItem, direction);//迭代,一直移动
            isNewRndItem = true;//判断是否创建新初始块

        } else if (sideItem.html() != currentItem.html()) {//左(右、上、下)侧元素和当前元素内容不同
            //不动

        } else {//左(右、上、下)侧元素和当前元素内容相同
            //向右合并
            sideItem.html((sideItem.html() - 0) * 2);//sideItem.html()为String数据类型,-0使其快速转换为Number类型
            currentItem.html('').removeClass('nonEmptyItem').addClass('emptyItem');
            gameScore += (sideItem.text() - 0) * 10;
            $('#gameScore').html(gameScore);
            // itemMove(sideItem, direction);
            maxScore = maxScore < gameScore ? gameScore : maxScore;//三元判断
            $('#maxScore').html(maxScore);
            localStorage.maxScore = maxScore;
            isNewRndItem = true;//创建新块的条件
            return;
            //只有在这里return,这是why?是因为在游戏过程中'推'一次,即'合并'一次以后就会结束这一轮迭代
            //如果return后面没有值,则返回的结果(函数返回值)为undefined
        }
    }


    function move(direction) {
        //获取所有非空元素(一个数组)
        var nonEmptyItems = $('.gameBody .row .nonEmptyItem');
        //如果按下的方向是左或上,则正向遍历非空元素
        if (direction == 'left' || direction == 'up') {
            for (var i = 0; i < nonEmptyItems.length; i++) {
                var currentItem = nonEmptyItems.eq(i);
                //:eq() 选择器选取带有指定 index 值的元素。index 值从 0 开始,所有第一个元素的 index 值是 0(不是 1)。
                //currentItem.html为啥出现的原因找到了@平安JavaScript
                //移动每一个非空数块,迭代循环《正向》
                itemMove(currentItem, direction);
            }
        } else if (direction == 'right' || direction == 'down') {//如果按下的方向是右或下,则反向遍历非空元素
            for (var i = nonEmptyItems.length - 1; i >= 0; i--) {
                var currentItem = nonEmptyItems.eq(i);
                itemMove(currentItem, direction);
            }
        }

        //是否产生新元素
        if (isNewRndItem) {
            newRndItem();
            refreshColor();
        }
    }

    function isGameOver() {
        //获取所有元素
        var items = $('.gameBody .row .item');

        //获取所有非空元素
        var nonEmptyItems = $('.gameBody .row .nonEmptyItem');
        if (items.length == nonEmptyItems.length) {//所有元素的个数 == 所有非空元素的个数  即没有空元素
            //遍历所有非空元素
            for (var i = 0; i < nonEmptyItems.length; i++) {
                var currentItem = nonEmptyItems.eq(i);
                if (getSideItem(currentItem, 'up').length != 0 && currentItem.html() == getSideItem(currentItem, 'up').html()) {
                    //上边元素存在 且 当前元素中的内容等于上边元素中的内容
                    return;
                } else if (getSideItem(currentItem, 'down').length != 0 && currentItem.html() == getSideItem(currentItem, 'down').html()) {
                    //下边元素存在 且 当前元素中的内容等于下边元素中的内容
                    return;
                } else if (getSideItem(currentItem, 'left').length != 0 && currentItem.html() == getSideItem(currentItem, 'left').html()) {
                    //左边元素存在 且 当前元素中的内容等于左边元素中的内容
                    return;
                } else if (getSideItem(currentItem, 'right').length != 0 && currentItem.html() == getSideItem(currentItem, 'right').html()) {
                    //右边元素存在 且 当前元素中的内容等于右边元素中的内容
                    return;
                }
            }
        } else {
            return;
        }
        $('#gameOverModal').modal('show');
    }

    //游戏初始化
    function gameInit() {
        //初始化分数
        $('#gameScore').html(gameScore);
        //最大分值
        $('#maxScore').html(maxScore);
        //为刷新按钮绑定事件
        $('.refreshBtn').click(refreshGame);
        //随机生成两个新元素
        newRndItem();
        newRndItem();
        //刷新颜色
        refreshColor();
    }

    //随机生成新元素
    function newRndItem() {
        //随机生成新数字
        var newRndArr = [2, 2, 4];
        var newRndNum = newRndArr[getRandom(0, 2)];
        console.log('newRndNum: ' + newRndNum);
        //随机生成新数字的位置
        var emptyItems = $('.gameBody .row .emptyItem');
        var newRndSite = getRandom(0, emptyItems.length - 1);
        emptyItems.eq(newRndSite).html(newRndNum).removeClass('emptyItem').addClass('nonEmptyItem');
    }

    //产生随机数,包括min、max
    function getRandom(min, max) {
        return min + Math.floor(Math.random() * (max - min + 1));
    }

    //刷新颜色
    function refreshColor() {
        var items = $('.gameBody .item');
        for (var i = 0; i < items.length; i++) {
            // console.log(items.eq(i).parent().index());
            switch (items.eq(i).html()) {
                case '':
                    items.eq(i).css('background', '');
                    break;
                case '2':
                    items.eq(i).css('background', 'rgb(250, 225, 188)');
                    break;
                case '4':
                    items.eq(i).css('background', 'rgb(202, 240, 240)');
                    break;
                case '8':
                    items.eq(i).css('background', 'rgb(117, 231, 193)');
                    break;
                case '16':
                    items.eq(i).css('background', 'rgb(240, 132, 132)');
                    break;
                case '32':
                    items.eq(i).css('background', 'rgb(181, 240, 181)');
                    break;
                case '64':
                    items.eq(i).css('background', 'rgb(182, 210, 246)');
                    break;
                case '128':
                    items.eq(i).css('background', 'rgb(255, 207, 126)');
                    break;
                case '256':
                    items.eq(i).css('background', 'rgb(250, 216, 216)');
                    break;
                case '512':
                    items.eq(i).css('background', 'rgb(124, 183, 231)');
                    break;
                case '1024':
                    items.eq(i).css('background', 'rgb(225, 219, 215)');
                    break;
                case '2048':
                    items.eq(i).css('background', 'rgb(221, 160, 221)');
                    break;
                case '4096':
                    items.eq(i).css('background', 'rgb(250, 139, 176)');
                    break;
            }
        }
    }

    // 电脑的方向键监听事件
    $('body').keydown(function (e) {
        switch (e.keyCode) {
            case 37:
                // left
                console.log('left');
                isNewRndItem = false;
                move('left');
                isGameOver();
                break;
            case 38:
                // up
                console.log('up');
                isNewRndItem = false;
                move('up');
                isGameOver();
                break;
            case 39:
                // right
                console.log('right');
                isNewRndItem = false;
                move('right');
                isGameOver();
                break;
            case 40:
                // down
                console.log('down');
                isNewRndItem = false;
                move('down');
                isGameOver();
                break;
        }
    });

    // 手机屏幕划动触发
    (function () {
        mobilwmtouch(document.getElementById("gameBody"))
        document.getElementById("gameBody").addEventListener('touright', function (e) {
            e.preventDefault();
            // alert("方向向右");
            console.log('right');
            isNewRndItem = false;
            move('right');
            isGameOver();
        });
        document.getElementById("gameBody").addEventListener('touleft', function (e) {
            // alert("方向向左");
            console.log('left');
            isNewRndItem = false;
            move('left');
            isGameOver();
        });
        document.getElementById("gameBody").addEventListener('toudown', function (e) {
            // alert("方向向下");
            console.log('down');
            isNewRndItem = false;
            move('down');
            isGameOver();
        });
        document.getElementById("gameBody").addEventListener('touup', function (e) {
            // alert("方向向上");
            console.log('up');
            isNewRndItem = false;
            move('up');
            isGameOver();
        });

        function mobilwmtouch(obj) {
            var stoux, stouy;
            var etoux, etouy;
            var xdire, ydire;
            obj.addEventListener("touchstart", function (e) {
                stoux = e.targetTouches[0].clientX;
                stouy = e.targetTouches[0].clientY;
                //console.log(stoux);
            }, false);
            obj.addEventListener("touchend", function (e) {
                etoux = e.changedTouches[0].clientX;
                etouy = e.changedTouches[0].clientY;
                xdire = etoux - stoux;
                ydire = etouy - stouy;
                chazhi = Math.abs(xdire) - Math.abs(ydire);
                //console.log(ydire);
                if (xdire > 0 && chazhi > 0) {
                    console.log("right");
                    //alert(evenzc('touright',alerts));
                    obj.dispatchEvent(evenzc('touright'));

                } else if (ydire > 0 && chazhi < 0) {
                    console.log("down");
                    obj.dispatchEvent(evenzc('toudown'));
                } else if (xdire < 0 && chazhi > 0) {
                    console.log("left");
                    obj.dispatchEvent(evenzc('touleft'));
                } else if (ydire < 0 && chazhi < 0) {
                    console.log("up");
                    obj.dispatchEvent(evenzc('touup'));
                }
            }, false);

            function evenzc(eve) {
                if (typeof document.CustomEvent === 'function') {

                    this.event = new document.CustomEvent(eve, {//自定义事件名称
                        bubbles: false,//是否冒泡
                        cancelable: false//是否可以停止捕获
                    });
                    if (!document["evetself" + eve]) {
                        document["evetself" + eve] = this.event;
                    }
                } else if (typeof document.createEvent === 'function') {


                    this.event = document.createEvent('HTMLEvents');
                    this.event.initEvent(eve, false, false);
                    if (!document["evetself" + eve]) {
                        document["evetself" + eve] = this.event;
                    }
                } else {
                    return false;
                }

                return document["evetself" + eve];

            }
        }
    })();
});
<!DOCTYPE html >
<html >
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>2048小游戏</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=no">
    <script src="https://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
    <link href="https://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="main.css"/>
    <script type="text/javascript" src="main.js"></script>
</head>
<body>

<div class="container">
    <div class="main">
        <div class="gameName">2048小游戏</div>
        <div class="maxScore">最高分:
            <span id="maxScore">1345612</span>
        </div>
        <div class="col-sm-3 col-md-4"></div>
        <div class="gameBody col-sm-6 col-md-4" id="gameBody">
            <div class="row">
                <div class="item emptyItem x0y0" x="0" y="0"></div>
                <div class="item emptyItem x0y1" x="0" y="1"></div>
                <div class="item emptyItem x0y2" x="0" y="2"></div>
                <div class="item emptyItem x0y3" x="0" y="3"></div>
            </div>
            <div class="row">
                <div class="item emptyItem x1y0" x="1" y="0"></div>
                <div class="item emptyItem x1y1" x="1" y="1"></div>
                <div class="item emptyItem x1y2" x="1" y="2"></div>
                <div class="item emptyItem x1y3" x="1" y="3"></div>
            </div>
            <div class="row">
                <div class="item emptyItem x2y0" x="2" y="0"></div>
                <div class="item emptyItem x2y1" x="2" y="1"></div>
                <div class="item emptyItem x2y2" x="2" y="2"></div>
                <div class="item emptyItem x2y3" x="2" y="3"></div>
            </div>
            <div class="row">
                <div class="item emptyItem x3y0" x="3" y="0"></div>
                <div class="item emptyItem x3y1" x="3" y="1"></div>
                <div class="item emptyItem x3y2" x="3" y="2"></div>
                <div class="item emptyItem x3y3" x="3" y="3"></div>
            </div>
        </div>
        <div class="gameRule col-sm-12 col-md-12">电脑:请用键盘的方向键进行操作</div>
        <div class="gameRule col-sm-12 col-md-12">手机:请划动屏幕进行操作</div>
        <div class="col-sm-4 col-md-4"></div>
        <div class="scoreAndRefresh col-sm-6 col-md-6">
            <div class="gameScore ">得分:<span id="gameScore">0</span></div>
            <button type="button" class="btn btn-danger refreshBtn">
                <span class="">刷新</span>
            </button>
        </div>


        <div class="modal fade" id="gameOverModal" aria-labelledby="myModalLabel" aria-hidden="true"
             data-backdrop="static">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
                            ×
                        </button>
                        <h4 class="modal-tittle" id="myModalLabel">2048小游戏</h4>
                    </div>
                    <div class="modal-body">
                        Game Over!
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-info" data-dismiss="modal">关闭</button>
                        <button type="button" class="btn btn-danger refreshBtn" onclick="refreshGame()">再玩一次</button>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>


</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值