Ahri-珊

day3将分享用JS编写的2048小游戏。

在线游戏

项目源码

目录 (Table of Contents)

[TOCM]

游戏介绍

操作:

使用键盘方向键,四个方向移动(移动设备上下左右滑动)。

规则:

2048是在一个正宫格(本例为4*4)中进行的,一开始游戏会出现2个数字,在游戏中系统本身只会给出2跟4这2个数字的。

我们的目标是2048,游戏开始后,玩家要通过移动数字进行合并来达到2048。

在游戏中玩家将数字移动一个方向,正宫格中所有的数字也会同样移动,通过这样的移动我们要合成2048的,就是2跟2合成4,4跟4合成8以此类推,只有同数值的数字才能合成。

当玩家成功合成2048后,游戏就顺利通关了,而如果正宫格中的格子全部填满并且相邻的格子都不相同也就是无法移动的话,那么恭喜你,gameover。

游戏分析:

思路

使用数组存放游戏格子中的数字,移动结束后重新初始化格子。

组件:

使用了Bootstrap。

1.弹出框:提示玩家开始游戏、游戏胜利、游戏结束

2048-Ahri-s

HTML代码

    	
<div class="pop">
	<div align="right">
		<button class="btn btn-default" onclick="cant()">关闭</button>	
	</div>
	<p id="res" align="center">此处为提示内容</p>
	<div align="center">
		<button class="btn btn-success" onclick="start()">start the game</button>				
	</div> 
</div>
	 

CSS代码

.pop {
	display:block;
    	z-index:10;
    	width:600px;  
        height:350px;  
        position:absolute;  
        left:50%;  
        top:50%;  
        margin:-200px 0 0 -300px;
    	background-color:#FFF;
    	opacity:0.8;
    	border:1px solid rgb(255,95,0);
    }
.pop p {
	margin:80px 50px 60px 50px;
    	font-size:30px;
}

2.游戏盒子:大div里包含4*4的小div,由于需要将移动后数组的值展示到对应div,所以要对每个div按照坐标编号。

HTML代码

    <div class="box">
      	<div class="start" align="center">
        <button class="btn btn-success" onclick="start()">start the game</button>
    	<button class="btn btn-danger" onclick="start()">restart the game</button>
        </div>
    	<div id="box" class="container">
        	<div class="row">
            	<div id="c00" class="col-xs-3 col-sm-3 cell" align="center"></div>
                <div id="c01" class="col-xs-3 col-sm-3 cell" align="center"></div>
                <div id="c02" class="col-xs-3 col-sm-3 cell" align="center"></div>
                <div id="c03" class="col-xs-3 col-sm-3 cell" align="center"></div>
            </div>
            <div class="row">
            	<div id="c10" class="col-xs-3 col-sm-3 cell" align="center"></div>
                <div id="c11" class="col-xs-3 col-sm-3 cell" align="center"></div>
                <div id="c12" class="col-xs-3 col-sm-3 cell" align="center"></div>
                <div id="c13" class="col-xs-3 col-sm-3 cell" align="center"></div>
            </div>
            <div class="row">
            	<div id="c20" class="col-xs-3 col-sm-3 cell" align="center"></div>
                <div id="c21" class="col-xs-3 col-sm-3 cell" align="center"></div>
                <div id="c22" class="col-xs-3 col-sm-3 cell" align="center"></div>
                <div id="c23" class="col-xs-3 col-sm-3 cell" align="center"></div>
            </div>
            <div class="row">
            	<div id="c30" class="col-xs-3 col-sm-3 cell"  align="center"></div>
                <div id="c31" class="col-xs-3 col-sm-3 cell"  align="center"></div>
                <div id="c32" class="col-xs-3 col-sm-3 cell"  align="center"></div>
                <div id="c33" class="col-xs-3 col-sm-3 cell"  align="center"></div>
            </div>
        </div>
      </div>
    

CSS代码

cell为游戏格子的默认样式,c2为格子值变为2时游戏格子的样式。

    .cell,.c2,.c4,.c8,.c16,.c32,.c64,.c128,.c256,.c512,.c1024,.c2048{
    	width:150px;
    	height:150px;
    	margin:10px;
    	background-color:rgb(255,255,170);
    	border-radius:15px;
    	}
    .c2{
    	background-color:#FF5;
    	line-height:150px;
    	font-size:100px;
    	}
    .c4{
    	background-color:#ffe543;
    	line-height:150px;
    	font-size:100px;
    	}
    .c8{
    	background-color:#fecf45;
    	line-height:150px;
    	font-size:100px;
    	}
    .c16{
    	background-color:#f3d64e;
    	line-height:150px;
    	font-size:100px;
    	}
    .c32{
    	background-color:#f9b747;
    	line-height:150px;
    	font-size:100px;
    	}
    .c64{
    	background-color:#fe9778;
    	line-height:150px;
    	font-size:100px;
    	}
    .c128{
    	background-color:#ff9b6a;
    	line-height:150px;
    	font-size:80px;
    	}
    .c256{
    	background-color:#f28860;
    	line-height:150px;
    	font-size:80px;
    	}
    .c512{
    	background-color:#fd7d36;
    	line-height:150px;
    	font-size:80px;
    	}
    .c1024{
    	background-color:#e96a25;
    	line-height:75px;
    	font-size:85px;
    	word-break: break-all;word-wrap: break-word;
    	}
    .c2048{
    	background-color:#de772c;
    	line-height:75px;
    	font-size:90px;
    	word-break: break-all;word-wrap: break-word;
    	}

事件

1.初始化

首先我们需要初始化一个二维数组存放游戏格子的值,初始化值为0。

    var nums = new Array();
    for(var i = 0;i<4;i++)
    {
    	nums[i] = new Array();
    	for(var j = 0;j<4;j++)
    	{
    		nums[i][j] = 0;
    	}
    }

然后我们需要将数组中的值展现到游戏盒子对应的格子里,让玩家能够看到。而对应的值对应的样式不同。所以我们需要两个函数:a.将一个元素的样式和值与游戏格子对应起来。b.遍历数组,将每个元素都与游戏格子对应。

    var showNum = function(num,Cx,Cy,t)
        	{
        		var id = "c"+Cx.toString()+Cy.toString();
        		var cl = "c"+num.toString();
        		var e = document.getElementById(id);
        		e.innerHTML = num;
        		e.className = "col-xs-3 col-sm-3 "+cl;
        	}
    		
    		var updateView = function()
    {
    	for(var i=0;i<4;i++)
    	{
    		for(var j=0;j<4;j++)
    		{
    			if(nums[i][i]==2048)
    				iswin = true;
    			if(nums[i][j]==0)
    				showNull(i,j);
    			else
    				showNum(nums[i][j],i,j,0);
    		}
    	}
    }
    

2.开始游戏

sss

好了,现在我们要点击开始游戏了,点击开始游戏后,我们首先需要清空存放上次游戏结果的数组,然后系统会在没有数字的游戏格子里随机出现两个数字。所以我们需要一个清空数组的函数restart(),一个在空位置随机产生数字并展示出来的函数newNumber().然后在开始游戏点击事件里调用这两个函数并隐藏弹出框。

		var start = function()
		{
			restart();
			$(".pop").hide();
			newNumber(2);
			newNumber(2);
		}
    	var restart = function()
    	{
    		for(var i = 0;i<4;i++)
    		{
    			for(var j = 0;j<4;j++)
    			{
    				nums[i][j] = 0;
    			}
    		}
    		updateView();
    	}
        var newNumber = function()
        {
        	var num;//值

        	var Cx;//横坐标

        	var Cy;//竖坐标

        	while(true)
			{
        		Cx = Math.round(Math.random()*3);
        		Cy = Math.round(Math.random()*3);
        		if (nums[Cx][Cy] == 0) 
                    break;
            }
        	num = Math.round(Math.random()*1+1)*2;
        	nums[Cx][Cy] = num;
        	showNum(num,Cx,Cy);
        }

3.上下左右事件

left-right-up-down

游戏开始了,玩家让这些游戏格子往哪边走,游戏格子就得往那边走,并且两个相同的数撞在一起就合并!duang~我们以向左滑动为例分析。 首先我们判断当前能不能进行左滑操作,这里用一个canMoveLeft函数判断,如果游戏格子里存在一个格子左边有空位或者左划可以合并那么玩家就可以向左滑滑动。

    var canMoveLeft = function()
    {
        for(var i=0;i<4;i++)
            for(var j=1;j<4;j++)
                if(nums[i][j]!=0)
                    if(nums[i][j-1]==0||nums[i][j-1]==nums[i][j])
                        return true;              
        return false;
    }

然后我么需要对存放数值的数组进行遍历寻找值不为空的元素(需要判断要不要滑动的元素),然后在这样的元素左边寻找它的落地位置。落地位置需要满足两个条件:a.这个位置是空的或者这个位置跟我值一样。b.我要移到这个位置中间没有元素挡着我。(注意,左滑应从最左边的元素开始遍历,右滑应从最右边的元素开始遍历)。如果找到的落地位置是空的,交换两个元素值就可以了,如果不是空的则需要合并元素。到这步,我们还需要一个函数noBlockHorizontal判断条件b。

    function noBlockHorizontal(row,col1,col2){
        for(var i=col1+1;i<col2;i++)
            if(nums[row][i]!=0)
                return false;
        return true;
    }

遍历结束后,所有的元素都待在了左滑后该呆的位置了,更新游戏格子就行啦。

    var moveLeft = function()
    {
    	if( !canMoveLeft())
            return false;
    	for(var i=0;i<4;i++)
            for(var j=1;j<4;j++)
    		{//第一列的数字不可能向左移动

                if(nums[i][j]!=0)
    			{
                    //(i,j)左侧的元素

                    for(var k=0;k<j;k++)
    				{
                        //落脚位置的是否为空 && 中间没有障碍物

                        if(nums[i][k]==0&&noBlockHorizontal(i,k,j))
    					{
                            nums[i][k] = nums[i][j];
                            nums[i][j] = 0;
                            continue;
                        }
                        //落脚位置的数字和本来的数字相等 && 中间没有障碍物

                        else if(nums[i][k]==nums[i][j]&&noBlockHorizontal(i,k,j))
    					{
                            nums[i][k] += nums[i][j];
                            nums[i][j] = 0;
                            continue;
                        }
                    }
                }
            }
    	updateView();
    	return true;
    }

4.结束游戏

2048-Ahri

a.当游戏格子位置满了并且不能再滑动时,游戏失败。因此我们需要两个函数nospace()与nomove()来判断游戏格子满没满,还能不能移动。

    var nomove = function()
    {
        if(canMoveLeft()|| canMoveRight()||canMoveUp()||canMoveDown())
            return false;
        return true;
    }
    var nospace = function() //判断是否还有空间

    	{
    		for (var i=0;i<4;i++) 
    			for (var j=0; j<4; j++) 
    				if (nums[i][j] == 0)
    					return false;
    		return true;
    	}
    var isgameover = function()
    {
        if(nospace()&&nomove())
    		{
            	gameover();
    		}
    }
    var gameover = function()
    {
        document.getElementById("res").innerHTML = "你又死了呀,好菜哦,再玩一次证明你自己吧";
    	$(".pop").show();
    }

5.添加移动端滑动事件

我使用的这种方法。

6.添加自己喜欢的动画

我采用的jQuery的animate方法。

查看完整代码与示例

看代码点这里~

玩游戏点这里~

End