2048小遊戲

 

1、遊戲簡介: javascript

2048是一款休閒益智類的數字疊加小遊戲
css

 

2、 遊戲玩法:html

在4*4的16宮格中,您能夠選擇上、下、左、右四個方向進行操做,數字會按方向移動,相鄰的兩個數字相同就會合並,組成更大的數字,每次移動或合併後會增長一個數字。java

當16宮格中沒有空格子,且四個方向都沒法操做時,遊戲結束。 jquery

 

3、 遊戲目的:bootstrap

目的是合併出2048這個數字,得到更高的分數。dom

 

4、 遊戲截圖:ide

 

 

 

 

6、遊戲實現原理:post

使用js、jQuery實現了PC版及手機版,實現原理是同樣的,只是移動端的一些樣式和上、下、左、右滑動的事件與PC端不同flex

1. 首先,把16宮格當作是矩陣的形式

2. 在html中給每一個格子添加類名及屬性,來記錄每一個格子的位置

類名item是每一個格子的類名,emptyItem是空格子的類名,nonEmptyItem是非空格式的類名

 

3. 遊戲開始時,隨機生成兩個數字,2或者4,出如今矩陣中任意位置

這部分是經過類名emptyItem及nonEmptyItem來實現的。

①. 隨機生成一個數字2或者4

②. 獲取全部空元素(類名emptyItem)

③. 隨機選擇一個空元素    將這個數字填充到空元素中,並將類名emptyItem移除,添加類名nonEmptyItem,即非空元素

④. 重複①、②、③步,再隨機生成一個數字填充一到隨機的位置

 

4. 遊戲的核心在於移動

移動有四個方向:上、下、左、右,實現思路以下:

向左移動

  移動或合併

  遍歷全部非空元素

    若是當前元素在第一個位置     則不動

    若是當前元素不在每個位置

      當前元素左側是空元素    向左移動

      當前元素左側是非空元素    

        左側元素和當前元素的內容不一樣    不動

        左側元素和當前元素的內容相同    向左合併

 

  是否產生新元素

  全部非空元素中,有移動的    產生新元素

  全部非空元素中,有合併的    產生新元素

 

 

向右移動

  移動或合併

  遍歷全部非空元素

    若是當前元素在最後一個位置     則不動

    若是當前元素不在最後一個位置

      當前元素右側是空元素    向右移動

      當前元素右側是非空元素    

        右側元素和當前元素的內容不一樣    不動

        右側元素和當前元素的內容相同    向右合併

 

  是否產生新元素

  全部非空元素中,有移動的    產生新元素

  全部非空元素中,有合併的    產生新元素

 

向上移動、向下移動 。。。。思路同上

 

5. 判斷遊戲是否結束:

獲取全部元素

獲取全部非空元素

若是全部元素的個數 == 全部非空元素的個數

  循環遍歷全部非空元素

    上面元素存在 && 當前元素的內容 == 上面元素的內容   return

    下面元素存在 && 當前元素的內容 == 下面元素的內容   return

    左邊元素存在 && 當前元素的內容 == 左邊元素的內容   return

    右邊元素存在 && 當前元素的內容 == 右邊元素的內容   return

   全部元素,以上條件都不知足   gameover 

 

代碼實現_Pc端

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>2048小遊戲</title>
    <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css">
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script>
    <script src="http://libs.baidu.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>

<style type="text/css">
        * {
            margin: 0;
            padding: 0;
            font-family: "YouYuan";
        }
        body {
            background: lavenderblush;
        }
        .container {
            margin-top: 30px;
        }
        .main {
            width: 1000px;
            height: 100%;
            margin: 0 auto;
            overflow: hidden;
            text-align: center;
        }
        .main .gameName {
            font-size: 35px;
            font-weight: bold;
        }
        .main .maxScore {
            font-size: 20px;
        }
        .main .maxScore span {
            color: red;
            font-weight: bold;
        }
        .main .gameBody {
            width: 400px;
            height: 400px;
            margin: 0 auto;
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            padding: 15px;
            background: #999;
            border-radius: 8px;
        }
        .main .gameBody .row {
            display: flex;
            justify-content: space-between;
        }
        .main .gameBody .row .item {
            width: 80px;
            height: 80px;
            border-radius: 10px;
            background: #fff;
            text-align: center;
            line-height: 80px;
            font-size: 30px;
            font-weight: bold;
            color: #666;
            font-family: "microsoft yahei";
        }
        .main .gameRule {
            font-size: 20px;
            font-weight: bold;
            margin-top: 15px;
        }
        .main .gameScore {
            font-size: 20px;
            font-weight: bold;
            margin-top: 15px;
        }
        .main .gameScore span {
            color: red;
            font-size: 30px;
        }
        .main .scoreAndRefresh {
            display: flex; 
            justify-content: space-around; 
            width: 280px; 
            margin: 0 auto;
        }
        .main .scoreAndRefresh .refreshBtn {
            height: 30px; margin-top: 22px;
        }
        .modal {
            margin-top: 7%;

        }
        .modal .modal-header h4 {
            text-align: left;
            font-weight: bold;
        }
        .modal .modal-dialog {
            width: 300px;
            margin: 0 auto;

        }
        .modal .modal-body {
            font-size: 18px;
            font-weight: bold;
            color: red;
        }
        #resetMaxScore {
            color: #fff;
            height: 30px;

        }
    </style>
</head>

<body>

<div class="container">
    <div class="main">
        <!--《2048》一款益智休閒小遊戲,據說能拼出2048的全世界不超過3%!-->
        <div class="gameName">2048小遊戲</div>
        <div class="maxScore">最高分:
            <span id="maxScore">134567</span>
        </div>
        <div class="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">請按上、下、左、右鍵進行操做</div>
        <div class="scoreAndRefresh">
            <div class="gameScore">得分:<span id="gameScore">0</span></div>
            <button type="button" class="btn btn-danger refreshBtn">
                <span class="glyphicon glyphicon-repeat"></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">
                            &times;
                        </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">再玩一次</button>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

</body>
<script type="text/javascript">
$(function(){
        //是否產生新元素
        var isNewRndItme = false;
        var gameScore = 0;
        //最高分
        var maxScore = 0;

        if(localStorage.maxScore) {
            maxScore = localStorage.maxScore - 0;
        }else {
            maxScore = 0;
        }


        //遊戲初始化
        gameInit();

        //上、下、左、右監聽事件
        $('body').keydown(function(e) {
            switch (e.keyCode) {
                case 37:
                    // left
                    console.log('left');
                    isNewRndItme = false;
                    move('left');
                    isGameOver();
                    break;
                case 38:
                    // up
                    console.log('up');
                    isNewRndItme = false;
                    move('up');
                    isGameOver();
                    break;
                case 39:
                    // right
                    console.log('right');
                    isNewRndItme = false;
                    move('right');
                    isGameOver();
                    break;
                case 40:
                    // down
                    console.log('down');
                    isNewRndItme = false;
                    move('down');
                    isGameOver();
                    break;
            }
        });


        function refreshGame(){
            var items = $('.gameBody .row .item');
            for(var i = 0; i < items.length; i++) {
                items.eq(i).html('').removeClass('nonEmptyItem').addClass('emptyItem');
            }
            gameScore = 0;
            //分數清零
            $('#gameScore').html(gameScore);
            //隨機生成兩個新元素
            newRndItem();
            newRndItem();
            //刷新顏色
            refreshColor();
            $('#gameOverModal').modal('hide');
        }


        function getSideItem(currentItem, direction) {
            //當前元素的位置
            var currentItemX = currentItem.attr('x') - 0;
            var currentItemY = currentItem.attr('y') - 0;

            //根據方向獲取旁邊元素的位置
            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;
        }


        function itemMove(currentItem, direction) {
            
            var sideItem = getSideItem(currentItem, direction);

            if(sideItem.length == 0) {//當前元素在最邊上
                //不動
                
            }else if(sideItem.html() == '') { //當前元素不在最後一個且左(右、上、下)側元素是空元素
                sideItem.html(currentItem.html()).removeClass('emptyItem').addClass('nonEmptyItem');
                currentItem.html('').removeClass('nonEmptyItem').addClass('emptyItem');
                itemMove(sideItem, direction);
                isNewRndItme = true;
                
            }else if(sideItem.html() != currentItem.html()) {//左(右、上、下)側元素和當前元素內容不一樣
                //不動
                
            }else {//左(右、上、下)側元素和當前元素內容相同
                //向右合併
                sideItem.html((sideItem.html() - 0) * 2);
                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;
                isNewRndItme = true;            
                return;
            }
        }


        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);
                    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(isNewRndItme) {
                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;
                }
            }
        }
    });
</script>
</html>

 

移動端滑動事件

PC端2048和手機端2048的不一樣之處就是一些樣式和上、下、左、右滑動事件

移動端的滑動事件以下:

(function (){
    mobilwmtouch(document.getElementById("gameBody"))
    document.getElementById("gameBody").addEventListener('touright',function (e){
        e.preventDefault();
        alert("方向向右");                        
    });
    document.getElementById("gameBody").addEventListener('touleft',function (e){
        alert("方向向左");
    });
    document.getElementById("gameBody").addEventListener('toudown',function (e){
        alert("方向向下");
    });
    document.getElementById("gameBody").addEventListener('touup',function (e){
        alert("方向向上");
    });
    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];
            
        }
    }
})()
相關文章
相關標籤/搜索