安卓2048小游戏源码

http://git.oschina.net/scimence/sci_2048/wikis/home

package com.example.sci_2048;

import java.util.Random;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.ScaleAnimation;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class MainActivity extends Activity  implements OnTouchListener, android.view.View.OnClickListener
{
	TextView maxView, scoreView;					//当前最大数值, 累积得分值 显示文本框
	int maxInt=0, scoreInt=0;						//最大数值, 累积得分 数值形式

	TextView cell[][] = new TextView[4][4];			//以文本框的形式创建游戏的16个单元格
	int num[][] = new int[4][4];					//存储16个单元格对应的数值
	int count = 0;									//统计当前16个单元格中大于0的数值数目

	Button again;									//重新开始

	public enum Direction { LEFT, RIGHT, UP, DOWN; }//方向
	Direction direction = null;						//标记屏幕的滑动方向

	float x1=-1, y1=-1, x2=-1, y2=-1;				//标志触摸按下和触摸释放时的坐标

	int cellWidth;									//设置游戏中方格的大小

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        View main = creatMainView();					//创建游戏主视图
        setContentView(main);							//设置为游戏视图
        main.setOnTouchListener(this);					//添加触摸事件监听,用于响应触摸滑动事件

        again.setOnClickListener(this);					//重新开始按钮添加事件响应,响应按钮的点击

        RandomSite();									//随机在空位置处生成数值2
        RandomSite();

        refresh();										//刷新界面显示值
    }

    //创建游戏的主视图,包含3部分:顶部信息、中部4*4方格、底部按钮
    @SuppressWarnings("deprecation")
	public View creatMainView()
    {
    	//获取屏幕的宽度和高度
        WindowManager wm = this.getWindowManager();
        int screenWidth = wm.getDefaultDisplay().getWidth();
        int screenHeight = wm.getDefaultDisplay().getHeight();

        //根据屏幕宽度设置游戏中方格的大小,在屏幕宽度大于高度时,按宽高比重新分配比例,使得高大于宽
        cellWidth = screenWidth <= screenHeight ? (screenWidth-10)/4 : (screenHeight*screenHeight/screenWidth-10)/4;

        float rat = screenWidth <= screenHeight ? screenWidth / 480 : screenWidth / 480 * screenHeight/screenWidth;		//相对于480屏幕大小比例值
        int size1 = (int)(28*rat), size2 = (int)(42*rat), size3 = (int)(22*rat);

    	RelativeLayout main = new RelativeLayout(this);

    	//游戏信息显示部分
    	RelativeLayout  info = new RelativeLayout(this);
    	info.setBackgroundColor(0xff074747);

    	//最值和得分的显示信息,前两个为标签后两个部分用于显示数值
    	TextView label[] = new TextView[4];
    	String LText[] = new String[]{"最值", "得分", "0", "0" };

    	RelativeLayout.LayoutParams paramsL[] = new RelativeLayout.LayoutParams[4];
    	int ParamsNum[][] = new int[][]					//四个文本框的布局参数
    	{
    			{RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.ALIGN_PARENT_LEFT}, {RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.ALIGN_PARENT_RIGHT},
    			{RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.ALIGN_PARENT_LEFT}, {RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.ALIGN_PARENT_RIGHT}
    	};

    	//设置显示信息的布局
    	for(int i=0; i<4; i++)
    	{
    		label[i] = new TextView(this);

	    	label[i].setText(LText[i]);
	    	label[i].setTextSize(size1);
	    	label[i].setTextColor(Color.WHITE);
	    	label[i].setGravity(Gravity.CENTER);

	    	paramsL[i] = new RelativeLayout.LayoutParams((int)(cellWidth*1.1), (int)(cellWidth*0.4));
	    	paramsL[i].addRule(ParamsNum[i][0]);
	    	paramsL[i].addRule(ParamsNum[i][1], RelativeLayout.TRUE);

	        info.addView(label[i], paramsL[i]);
    	}
    	maxView = label[2]; 	//映射最值到全局变量,便于下次访问
    	scoreView = label[3]; 

        //游戏主体4*4方格部分
        RelativeLayout body = new RelativeLayout(this);	//创建一个相对布局的视图
        body.setBackgroundColor(Color.BLACK);			//为其设置背景色

        for(int i=0; i<4; i++)
        	for(int j=0; j<4; j++)
        	{
        		cell[i][j] = new TextView(this);		//创建
        		num[i][j] = 0;							//初始时,每个方格中的数值均为0

        		RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(cellWidth, cellWidth);
        		int left = 2 + j * (2 + cellWidth), top = 2 + i * (2 + cellWidth), right = left + cellWidth, bottom = top + cellWidth;	//top属性值由行位置i决定,left由列位置j决定
        		params.setMargins(left, top, right, bottom);						//设置各个方格的布局位置

        		body.addView(cell[i][j], params);									//将表示方格的文本框添加到窗体

        		cell[i][j].setTextSize(size2);										//设置字体大小
        		cell[i][j].setGravity(Gravity.CENTER);								//设置文本布局方式
        	}

        //添加信息显示部分到主界面
        RelativeLayout.LayoutParams paramsInfo = new RelativeLayout.LayoutParams((int)(cellWidth*2.2), (int)(cellWidth*0.8));
        int right = (int)(screenWidth/2 + (cellWidth*4+10)/2), left = right-(int)(cellWidth*2.2), top = 0, bottom = (int)(cellWidth*0.8);
        paramsInfo.setMargins(left, top, right, bottom);
//        paramsInfo.addRule(RelativeLayout.ALIGN_PARENT_TOP);
//        paramsInfo.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);

        main.addView(info, paramsInfo);

        //添加游戏主体部分到主界面
        RelativeLayout.LayoutParams paramsBody = new RelativeLayout.LayoutParams(cellWidth*4+10, cellWidth*4+10);
        paramsBody.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
        main.addView(body, paramsBody);

        //添加重新开始按钮到主界面
        RelativeLayout.LayoutParams paramsAgain = new RelativeLayout.LayoutParams((int)(cellWidth * 1.2), (int)(cellWidth * 0.6));
        paramsAgain.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        paramsAgain.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
        Button btnAgain = new Button(this);				//重新开始
        btnAgain.setText("重新开始");
        btnAgain.setTextSize(size3);					//设置字体大小
        main.addView(btnAgain, paramsAgain);

        again = btnAgain;								//映射该按钮到全局变量

    	return main;
    }

    //在游戏的空格位置处,随机生成数值2
    public void RandomSite()
    {
    	if(count<16)									//当16个方格未被数值填满时
    	{
	    	Random rnd = new Random();
	        int n = rnd.nextInt(16-count), cN=0;		//根据空位置数随机生成一个 数值

	        for(int i=0; i<4; i++)						//将随机数位置转换为在4*4方格中的对应位置
	        	for(int j=0; j<4; j++)
	        	{
	        		if(num[i][j] == 0)
	        		{
	        			if(cN == n)
	        			{
	        				num[i][j] = 2;
	        		        count++;					//4*4方格中大于0的数目统计

	        		        aniScale(cell[i][j]);	//设置动画效果
	        		        return;
	        			}
	        			else cN++;
	        		}
	        	}
    	}
    }

    //消息框
    public void messageBox(String str)
    {
    	new AlertDialog.Builder(this)
		.setMessage(str)
		.setPositiveButton("确定", null)
		.show();
    }

    //当游戏界面被数值填满时,判断是否可以朝某方向合并
  	public boolean canBeAdd()
  	{	//分别判定垂直的两个方向是否有相邻数值可以合并即可
  		if(canBeAdd(Direction.RIGHT))return true;
  		else return canBeAdd(Direction.DOWN);
  	}

	//当游戏界面被数值填满时,判断是否可以朝指定方向合并,若不可以则游戏结束
	public boolean canBeAdd(Direction direction)
	{
		if(count<16)return true;			//未被填满时,可以继续操作

		int startN=0, addX=0, addY=0;		//起始值、结束值、步增值, x、y方向增量

		if(direction == Direction.RIGHT){ startN=3; addX=0; addY=1; }
		else if(direction == Direction.LEFT){ startN=0; addX=0; addY=-1; }
		else if(direction == Direction.DOWN){ startN=3; addX=1; addY=0; }
		else if(direction == Direction.UP){ startN=0; addX=-1; addY=0; }

		for(int x=0; x<=3; x++)				//对每一行或每一列执行
		{
			int y=startN;
			int i=0, j=0;

			if(direction == Direction.RIGHT || direction == Direction.LEFT){ i=x; j=y; }
			else { i=y; j=x; }

			for(int k = 0; k<3; k++)		//4个位置,从某个方向开始对每两个连续位置进行比对,相同则合并,合并顺序为direction的逆序
			{
				int i1 = i-k*addX, j1 = j-k*addY, i2 = i1-addX, j2 = j1-addY;
				if(num[i1][j1]==num[i2][j2] && num[i1][j1]!=0)
				{
					return true;
				}
			}
		}

		return false;
	}

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

	@Override
	public boolean onTouch(View v, MotionEvent event)
	{
		//获取触摸拖动起点和终点的坐标,以便于判断触摸移动方向
		switch (event.getAction())
		{
			case MotionEvent.ACTION_DOWN:	//触摸屏幕后记录坐标
				x1 = event.getX();			//按下点坐标
				y1 = event.getY();
				break;

			case MotionEvent.ACTION_MOVE:	//触摸移动
				break;

			case MotionEvent.ACTION_UP:
				x2 = event.getX();			//移动点坐标
				y2 = event.getY();
				break;

			case MotionEvent.ACTION_CANCEL:
		}

		//进行触摸处理,要求触摸按下和释放点的坐标都存在,且不同,另外我们要求触摸移动的距离大于等于一个方格宽度
		if((x1!=-1 && x2!=-1) && (x1!=x2|| y1!=y2)&& (Math.abs(x1 - x2) >= cellWidth || Math.abs(y1 - y2) >= cellWidth))
		{
			if (x2 - x1 > Math.abs(y2 - y1)) direction = Direction.RIGHT;
			else if (x1 - x2 > Math.abs(y2 - y1)) direction = Direction.LEFT;
			else if (y2 - y1 > Math.abs(x2 - x1)) direction = Direction.DOWN;
			else if (y1 - y2 > Math.abs(x2 - x1)) direction = Direction.UP;

			gameProcess(direction);			//游戏内部数值处理
			refresh();						//根据数组中的数据,刷新显示到界面中

			x2 = x1 = -1 ; y2 = y1 = -1;	//此句保证每次触摸移动仅处理一次
		}

		return true;
	}

	//游戏内部数值处理过程实现,分为3步:朝一个方向叠加、相同数值合并、再次朝该方向叠加
	public void gameProcess(Direction direction)
	{
		boolean flag = false;				//标志是否有数值可以下落,或者可以合并

		if(Gravaty(direction))flag = true;	//控制4*4方格中的数值朝一个方向坠落,叠加
		if(add(direction))
		{
			flag = true;
			Gravaty(direction);				//数值合并后, 如果有数值合并了,逻辑上方的数值下落
		}

		if(flag)RandomSite();				//如果有数值下落了或合并了,则随机在一个空位置处生成2

		if(count==16 && !canBeAdd()) messageBox("抱歉,此次未能通关");//16个方格都被填满时,判断是否可以朝某个方向合并数值,不能则给出提示信息
	}

	//控制游戏中数值的坠落方向,该函数实现数值的坠落与叠起,相同数值不合并
	public boolean Gravaty(Direction direction)
	{
		int startN=0, endN=0, step=0, addX=0, addY=0;	//起始值、结束值、步增值, x、y方向增量
		boolean haveDroped = false;						//标志是否有数值下落			

		if(direction == Direction.RIGHT){ startN=3; endN=0; step=-1; addX=0; addY=1; }
		else if(direction == Direction.LEFT){ startN=0; endN=3; step=1; addX=0; addY=-1; }
		else if(direction == Direction.DOWN){ startN=3; endN=0; step=-1; addX=1; addY=0; }
		else if(direction == Direction.UP){ startN=0; endN=3; step=1; addX=-1; addY=0; }

		for(int x=0; x<=3; x++)							//对每一行或每一列执行
		{
			for(int y=startN; (step<0 && y>=endN) || (step>0 && y<=endN); y+=step)
			{
				int i=0, j=0, i2=-1, j2=-1;

				if(direction == Direction.RIGHT || direction == Direction.LEFT){ i=x; j=y; }
				else { i=y; j=x; }

				i2=i;
				j2=j;
				//当前方格中的数值不为0,其移动方向一侧的空位置在区域内,其数值为0
				while(num[i][j] != 0 && inArea(i2+addX, j2+addY) && num[i2+addX][j2+addY] == 0)
				{										//计算该坐标方向的最后一个可用数值为0的位置
					i2 += addX;
					j2 += addY;
				}

				if(inArea(i2, j2) && (i!=i2 || j!=j2))	//将坐标处的数值落到最后的空位置
				{

					num[i2][j2] = num[i][j];
					num[i][j] = 0;
					haveDroped = true;					//有数值下落
				}
			}
		}

		return haveDroped;
	}

	//为视图v添加动画效果,尺寸变化
	public void aniScale(View v)
	{
		v.bringToFront();				//前端显示
		AnimationSet aniSet = new AnimationSet(true);
		//设置尺寸从0.5倍变化到1.1倍
		ScaleAnimation scaleAni = new ScaleAnimation(0.89f, 1.15f, 0.89f, 1.15f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
		scaleAni.setDuration(400);		//设置动画效果时间
		aniSet.addAnimation(scaleAni);	//将动画效果添加到动画集中

		v.startAnimation(aniSet);		//视图v开始动画效果
	}

	//在Gravaty()处理的基础上,控制相同数值朝指定方向合并
	public boolean add(Direction direction)
	{
		int startN=0, addX=0, addY=0;		//起始值、结束值、步增值, x、y方向增量
		boolean combined = false;			//标记是否有数值合并了

		if(direction == Direction.RIGHT){ startN=3; addX=0; addY=1; }
		else if(direction == Direction.LEFT){ startN=0; addX=0; addY=-1; }
		else if(direction == Direction.DOWN){ startN=3; addX=1; addY=0; }
		else if(direction == Direction.UP){ startN=0; addX=-1; addY=0; }

		for(int x=0; x<=3; x++)				//对每一行或每一列执行
		{
			int y=startN;
			int i=0, j=0;

			if(direction == Direction.RIGHT || direction == Direction.LEFT){ i=x; j=y; }
			else { i=y; j=x; }

			for(int k = 0; k<3; k++)		//4个位置,从某个方向开始对每两个连续位置进行比对,相同则合并,合并顺序为direction的逆序
			{
				int i1 = i-k*addX, j1 = j-k*addY, i2 = i1-addX, j2 = j1-addY;
				if(num[i1][j1]==num[i2][j2] && num[i1][j1]!=0)
				{
					scoreInt += num[i2][j2];//累积分值

					num[i1][j1] *= 2;
					num[i2][j2] = 0;
					combined = true;

					count--;				//数值合并后,大于0的数值减1
					aniScale(cell[i1][j1]);	//设置动画效果

					if(num[i1][j1] == 2048) messageBox("恭喜,你赢了!");
//					if(num[i1][j1] == 2048) Toast.makeText(this, "恭喜,你赢了!", Toast.LENGTH_SHORT).show();
				}
			}
		}

		return combined;
	}

	//判断n1和n2是否均在0到3之间,保证坐标n1,n2在4*4方格范围
	public boolean inArea(int n1, int n2)
	{
		return 0 <= n1 && n1<=3 && 0 <= n2 && n2<=3 ;
	}

	//刷新游戏方格中的显示值,将4*4数组中的值显示到cell中
	public void refresh()
	{
		for(int i=0; i<4; i++)
        	for(int j=0; j<4; j++)
        	{
        		if( num[i][j]==0 )cell[i][j].setText("");							//数值为0时,清空显示
        		else cell[i][j].setText(String.valueOf(num[i][j]));					//大于0时在方格中显示对应的数值

        		cell[i][j].setBackgroundColor(getBacColor(num[i][j]));				//设置背景色

        		if( num[i][j]==2 || num[i][j]==4) cell[i][j].setTextColor(0xff776E65);
        		else cell[i][j].setTextColor(0xfff9f6f2);							//设置字体颜色

        		if(maxInt < num[i][j]) maxInt = num[i][j];							//记录最大数值
        	}

		maxView.setText(String.valueOf(maxInt));									//显示最大值
		scoreView.setText(String.valueOf(scoreInt));								//显示分值

	}

	//获取各数值对应的背景颜色
	public int getBacColor(int num)
	{
		int color[] = new int[]{0xff074747, 0xff999999, 0xffede0c8, 0xfff2b179, 0xfff59563, 0xfff67c5f, 0xfff65e3b, 0xffedcf72, 0xffedcc61, 0xffedc850, 0xffedc53f, 0xffedc22e};
		int i=0;			//标记颜色数组的下标位置,分别对应数值0、2、4、8、16……
		while(num>1)
		{
			i++;
			num/=2;
		}
		return color[i];	//返回对应颜色值
	}

	@Override
	public void onClick(View v) //重新开始按钮的事件响应
	{
		new AlertDialog.Builder(this)
//		.setTitle("")
		.setMessage("确定要重新开始本局吗?")
		.setPositiveButton("确定", new DialogInterface.OnClickListener()
		{
		    public void onClick(DialogInterface dialoginterface, int i)
		    {
		    	rePlay();
		    }
		})
		.setNegativeButton("取消", null)
		.show();
	}

	//重玩游戏,清空游戏数据信息
	public void rePlay()
	{
		//清空数据
		maxInt = 0;
		scoreInt = 0;
		count = 0;
		for(int i=0; i<4; i++)
        	for(int j=0; j<4; j++)
        	{
        		num[i][j] = 0;
        	}

		//生成两个随机位置
		RandomSite();
        RandomSite();

        refresh();	//刷新显示
	}
}

附件下载:http://git.oschina.net/scimence/sci_2048/attach_files

时间: 2024-10-12 18:14:48

安卓2048小游戏源码的相关文章

2048小游戏源码

2048小游戏 下载地址:http://www.devstore.cn/code/info/737.html 运行截图:   

21款网页版html5小游戏源码

html5魅族创意的贪食蛇游戏源码下载 html5网页版打砖块小游戏源码下载 html5 3D立体魔方小游戏源码下载 html5网页版飞机躲避游戏源码下载 html5三国人物连连看游戏源码下载 js html5 2048数字游戏源码_2048网页版源码下载 html5盲打高手打飞字游戏下载_网页版英文打飞字游戏源码下载 jQuery flappy bird电脑版小游戏源码下载 网页版html5 3d俄罗斯方块游戏源码下载 jQuery html5迷宫游戏源码下载 html5网页游戏仿flappy

HTML5小游戏源码收藏

html5魅族创意的贪食蛇游戏源码下载 html5网页版打砖块小游戏源码下载 html5 3D立体魔方小游戏源码下载 html5网页版飞机躲避游戏源码下载 html5三国人物连连看游戏源码下载 js html5 2048数字游戏源码_2048网页版源码下载 html5盲打高手打飞字游戏下载_网页版英文打飞字游戏源码下载 jQuery flappy bird电脑版小游戏源码下载 网页版html5 3d俄罗斯方块游戏源码下载 jQuery html5迷宫游戏源码下载 html5网页游戏仿flappy

11款手机微信小游戏源码特效

html5微信吃苹果游戏源码下载 html5手机淘宝万能时装屋小游戏源码下载 html5 3d拳王游戏制作3D拳击游戏源码下载 html5 3d拼图游戏制作3D魔方游戏源码下载 htm5 3d游戏制作3D熊出没游戏源码下载 html5微信小游戏超级染色游戏源码下载 html5读心术小游戏源码下载_读心术微信小游戏源码下载 找你歌微信html5游戏源码下载_找你歌微信游戏源码下载 方言等级考试游戏源码下载_方言等级测试微信游戏源码下载 中秋节吃月饼游戏html5微信游戏源码下载 9款html5微信

安卓版猜拳游戏源码

安卓版猜拳游戏源码,该文件中带有安装测试包的,这个游戏源码比较简单的,现在有两个代码,一个自定义VIEW的,一个就是普通的imageView图片,游戏非常适合一些新手的使用和学习. <ignore_js_op> <ignore_js_op> <ignore_js_op>  详细说明:http://android.662p.com/thread-4914-1-1.html 安卓版猜拳游戏源码,布布扣,bubuko.com

一款真的不错的安卓飞行射击游戏源码

一款真的不错的安卓飞行射击游戏源码,喜欢的朋友可以研究一下吧.游戏一共三关.自适应屏幕 游戏有几个地方说明下:1. 如果刚进入游戏,提示错误并退出.请把LoadResource 类里面的以下代码改下: //加载爆炸图片            for(int i=1; i<=77; i++)              {                BitMap m = BitmapFactory.decodeStream(context.getAssets().open("explosi

九宫格小游戏源码分享

九宫格小游戏,可从本地图库载入一张图片,填充到9个ImageView,另涉及Timer计时.图库控件.每个格子都是相同的控件,动态添加到首页中的,在初始化后,响应touch事件,之后通过多次消息传递,来完成整个拼图过程.里面有个随机发牌的经典算法,也可参考. 初始化时,激发每个格子的init事件和initCheckOk来完成布局=>单个控件响应 touch事件,发出广播,要求机动单元格给予回应,是否允许交换位置 =>机动单元格响应广播. 广播是通过承载页sm("do_Page&quo

微信游戏圈小游戏源码共享下载

源码数量不少于300套!持续更新中! 皇家VIP群入会费请咨询QQ   截止于2014-10-18,更新的一些游戏截图   截止于2014-10-13,微信小游戏VIP交流群已经共享的源码截图 列举一下部分游戏的名称: 随意门(屌丝版) 植物大战僵尸 逼死强迫症2 胸口碎大石 粉绿男女 打击者 黄金矿工 反腐小王子 转你妹 纸飞机 狂射iphone6 小兔子快快跑 跳跳狗 扫雷 奇葩连连看 看你有多花 开心消消乐 进化 拯救精子 打老虎 色域迷惑人 厕纸挑战 气球砰砰砰 横冲直闯 疯狂飙车 粑粑

flappy pig小游戏源码分析(4)——核心pig模块(未完待续)

热身之后,我们要动点真格的了,游戏叫flappy pig,我们的pig终于要出场了. 老规矩,看看目录结构,读者对着目录结构好好回想我们已经讲解的几个模块: 其中game.js是游戏主程序,option.js是游戏配置文件,util是我们的通用工具库函数. 那么pig是什么呢,我们先上源码: var flappy = (function (self) { 'use strict';//开启严格模式 var option = self.option,//把前面添加好的option拿出来 $ = s