2048游戏

现在我们要实现一个2048的游戏,那么开始吧~

首先我们先来把布局给实现了~2048是一个4*4的平面游戏,那么就要用到GridLayout,我们先写将其嵌入在一个LinearLayout中,请看代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:text="@string/Score" />

        <TextView
            android:id="@+id/tvScore"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textAppearance="?android:attr/textAppearanceLarge"/>
        
        <Button 
            android:id="@+id/my_button"
        	android:layout_width="wrap_content"
        	android:layout_height="wrap_content"
        	android:text="@string/newGame"
        	android:textAppearance="?android:attr/textAppearanceLarge"
            />
    </LinearLayout>
    
    
    
    <com.example.game2048.GameView
        android:id="@+id/gameView"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1" >
    </com.example.game2048.GameView>

</LinearLayout>


创建一个游戏类GameView,其继承自布局GridLayout,并这个类绑定在activity_main.xml的GridLayout上,具体操作如下

1:鼠标移至GameView处,其自动浮现类的路径,复制



2:替换关键字GridLayout



GameView的代码,要向AndroidMainfest.xml的activity添加属性 android:screenOrientation="portrait"

public class GameView extends GridLayout {
	
	private Card[][] cardsMap=new Card[4][4];
	private List<Point> emptyPoints=new ArrayList<Point>();

	// 保险起见,把三个构造函数全部都添加了
	public GameView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initGameView();
	}// 构造函数1

	public GameView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initGameView();
	}// 构造函数2

	public GameView(Context context) {
		super(context);
		initGameView();
	}// 构造函数3

	private void initGameView(){//启动游戏
		setColumnCount(4);//设置为4列
		setBackgroundColor(0xffbbada0);//设置游戏背景颜色
		
		
		setOnTouchListener(new View.OnTouchListener() {
			private float startX,startY,offsetX,offsetY;//起始坐标,偏移坐标
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch(event.getAction()){
				case MotionEvent.ACTION_DOWN://手指开始触碰时
					startX=event.getX();//获得起始的x坐标
					startY=event.getY();//获得起始的y坐标
					break;
					
				case MotionEvent.ACTION_UP://手指触碰后
					offsetX=event.getX()-startX;//获得偏移的x坐标
					offsetY=event.getY()-startY;//获得偏移的y坐标
					
					if(Math.abs(offsetX)>Math.abs(offsetY)){//水平位移大于竖直位移,说明是在水平方向上动的
						if(offsetX<-5){
							swipeLeft();
						}else if(offsetX>5){
							swipeRight();
						}
					}
					else{
						if(offsetY<-5){
							swipeUp();
						}else if(offsetY>5){
							swipeDown();
						}
					}
					break;
				}
				return true;//返回true事件发生
			}
			
		});
	}
				
	
	
	private void checkComplete(){//检查游戏结束否
		
		boolean complete=true;
		ALL://标签
		for(int y=0;y<4;y++){
			for(int x=0;x<4;x++){
				if(cardsMap[x][y].getNum()==0||//如果一个格子不为0并且它上下左右有跟它相等的数,则游戏不结束
						(x>1&&cardsMap[x][y].equals(cardsMap[x-1][y]))||
						(x<3&&cardsMap[x][y].equals(cardsMap[x+1][y]))||
						(y>0&&cardsMap[x][y].equals(cardsMap[x][y-1]))||
						(y<3&&cardsMap[x][y].equals(cardsMap[x][y+1]))){
					complete=false;
					break ALL;
				}
			}
				
		}
		if(complete){
			new AlertDialog.Builder(getContext()).setTitle("Hello").setMessage("游戏结束 ").setPositiveButton("重来 ", new DialogInterface.OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					startGame();
					
				}
			}).show();
		}
	}
								
					
							
					
					

	
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {//处理窗口大小变化,只在布局被创建时执行一次
		super.onSizeChanged(w, h, oldw, oldh);
		
		int cardWidth=(Math.min(w, h)-10)/4;//获取卡片宽高,正方形只知宽就可以了
		addCards(cardWidth,cardWidth);
		
		startGame();
	}
	
	private void addCards(int cardHeight,int cardWidth){
		
		Card c;
		for(int y=0;y<4;y++){
			for(int x=0;x<4;x++){
				c=new Card(getContext());
				c.setNum(0);
				addView(c, cardWidth, cardHeight);
				cardsMap[x][y]=c;
			}
		}
		
	}
	
	public void startGame(){
		
		MainActivity.getMainActivity().clearScore();//分数清零
		for(int y=0;y<4;y++){//原先可能不为0,所以要先清0
			for(int x=0;x<4;x++){
				cardsMap[x][y].setNum(0);
			}
		}
		
		addRandomNum();//添加两个随机数
		addRandomNum();
		
	}
	
	private void addRandomNum(){
		
		emptyPoints.clear();//添加随机数之前把列表清空
		
		for(int y=0;y<4;y++){
			for(int x=0;x<4;x++){
				if(cardsMap[x][y].getNum()<=0){//如果是空点的话才添加随机数
					emptyPoints.add(new Point(x,y));
				}
			}
		}
		
		Point p=emptyPoints.remove((int)(Math.random()*emptyPoints.size()));//取出列表中的一个点
		cardsMap[p.x][p.y].setNum(Math.random()>0.1?2:4);//2生成的概率是4的9倍
	}
	
	
	private void swipeLeft() {
		
		boolean merge=false;
		for(int y=0;y<4;y++){
			for(int x=0;x<4;x++){
				
				for(int x1=x+1;x1<4;x1++){//从当前位置往右遍历,只遍历3列
					
					if(cardsMap[x1][y].getNum()>0){//找到一个当前格子大于0的
						
						if(cardsMap[x][y].getNum()<=0){//与当前格同一行的,且在其前面的(列方向),是空白的
							cardsMap[x][y].setNum(cardsMap[x1][y].getNum());//将当前格子的数字移到空白格处
							cardsMap[x1][y].setNum(0);//当前格清零
							x--;
							merge=true;
						}else if(cardsMap[x][y].equals(cardsMap[x1][y])){//如果当前格和同行某一格数值相等,则合并
							cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
							cardsMap[x1][y].setNum(0);
							MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());//计分
							merge=true;
						}
						break;	
					}
					
				}
			}
		}
		if(merge){
			addRandomNum();
			checkComplete();
		}
	}

	private void swipeRight() {
		
		boolean merge=false;
		for(int y=0;y<4;y++){
			for(int x=3;x>=0;x--){
				
				for(int x1=x-1;x1>=0;x1--){//从当前位置往右遍历,只遍历3列
					
					if(cardsMap[x1][y].getNum()>0){//找到一个当前格子大于0的
						
						if(cardsMap[x][y].getNum()<=0){//与当前格同一行的,且在其前面的(列方向),是空白的
							cardsMap[x][y].setNum(cardsMap[x1][y].getNum());//将当前格子的数字移到空白格处
							cardsMap[x1][y].setNum(0);//当前格清零
							x++;
							merge=true;
						}else if(cardsMap[x][y].equals(cardsMap[x1][y])){//如果当前格和同行某一格数值相等,则合并
							cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
							cardsMap[x1][y].setNum(0);
							MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());//计分
							merge=true;
						}
						break;	
					}
					
				}
			}
		}
		if(merge){
			addRandomNum();
			checkComplete();
		}
	}

	private void swipeUp() {
		
		boolean merge=false;
		for(int x=0;x<4;x++){
			for(int y=0;y<4;y++){
				
				for(int y1=y+1;y1<4;y1++){//从当前位置往右遍历,只遍历3列
					
					if(cardsMap[x][y1].getNum()>0){//找到一个当前格子大于0的
						
						if(cardsMap[x][y].getNum()<=0){//与当前格同一行的,且在其前面的(列方向),是空白的
							cardsMap[x][y].setNum(cardsMap[x][y1].getNum());//将当前格子的数字移到空白格处
							cardsMap[x][y1].setNum(0);//当前格清零
							y--;
							merge=true;
						}else if(cardsMap[x][y].equals(cardsMap[x][y1])){//如果当前格和同行某一格数值相等,则合并
							cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
							cardsMap[x][y1].setNum(0);
							MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());//计分
							merge=true;
						}
						break;		
					}
					
				}
			}
		}
		if(merge){
			addRandomNum();
			checkComplete();
		}
	}

	private void swipeDown() {
		
		boolean merge=false;
		for(int x=0;x<4;x++){
			for(int y=3;y>=0;y--){
				
				for(int y1=y-1;y1>=0;y1--){//从当前位置往右遍历,只遍历3列
					
					if(cardsMap[x][y1].getNum()>0){//找到一个当前格子大于0的
						
						if(cardsMap[x][y].getNum()<=0){//与当前格同一行的,且在其前面的(列方向),是空白的
							cardsMap[x][y].setNum(cardsMap[x][y1].getNum());//将当前格子的数字移到空白格处
							cardsMap[x][y1].setNum(0);//当前格清零
							y++;
							
						}else if(cardsMap[x][y].equals(cardsMap[x][y1])){//如果当前格和同行某一格数值相等,则合并
							cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
							cardsMap[x][y1].setNum(0);
							MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());//计分
							
						}
						break;		
					}
					
				}
			}
		}
		if(merge){
			addRandomNum();
			checkComplete();
		}
	}

}

接下来要创建一个纸牌类,来创建卡片,类名为Card

public class Card extends FrameLayout {
	
	private int num=0;
	private TextView label;
	private View background;
	public Card(Context context) {
		super(context);

		LayoutParams lp = null;
		lp = new LayoutParams(-1, -1);//填满父容器
		lp.setMargins(10, 10, 0, 0);//设置每个文本之间的距离

		background = new View(getContext());
		background.setBackgroundColor(0x33ffffff);//设置第二层的背景颜色
		addView(background, lp);//加入布局中

		label = new TextView(getContext());
		label.setTextSize(28);
		label.setGravity(Gravity.CENTER);//使数字居中

		lp = new LayoutParams(-1, -1);//第三层背景
		lp.setMargins(10, 10, 0, 0);
		addView(label, lp);

		setNum(0);
	}
	
	
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
		
		if(num<=0){
			label.setText("");//如果数小于等于0,设置空字符
		}else{
			String s=Integer.toString(num);
			label.setText(s);
		}
		
		switch (num) {//设置相应数字对应的颜色
		case 0:
			label.setBackgroundColor(0x00000000);
			break;
		case 2:
			label.setBackgroundColor(0xffeee4da);
			break;
		case 4:
			label.setBackgroundColor(0xffede0c8);
			break;
		case 8:
			label.setBackgroundColor(0xfff2b179);
			break;
		case 16:
			label.setBackgroundColor(0xfff59563);
			break;
		case 32:
			label.setBackgroundColor(0xfff67c5f);
			break;
		case 64:
			label.setBackgroundColor(0xfff65e3b);
			break;
		case 128:
			label.setBackgroundColor(0xffedcf72);
			break;
		case 256:
			label.setBackgroundColor(0xffedcc61);
			break;
		case 512:
			label.setBackgroundColor(0xffedc850);
			break;
		case 1024:
			label.setBackgroundColor(0xffedc53f);
			break;
		case 2048:
			label.setBackgroundColor(0xffedc22e);
			break;
		default:
			label.setBackgroundColor(0xff3c3a32);
			break;
		}
	}
	
	public boolean equals(Card o){
		return getNum()==o.getNum();//判断卡片的内容是否相等
	}
	

}

最后是MainActivity的实现

public class MainActivity extends Activity {

	private TextView tvScore;
	private static MainActivity mainActivity=null;//构造一个MainActivity实例变量,可以方便获取
	private int score=0;
	private Button my_button;
	private GameView gameView;
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_game);
        tvScore=(TextView) findViewById(R.id.tvScore);
        gameView=(GameView) findViewById(R.id.gameView);
        my_button=(Button) findViewById(R.id.my_button);
        my_button.setOnClickListener(new OnClickListener() {//重新开始
			
			@Override
			public void onClick(View v) {
				gameView.startGame();
				
			}
		});
       
    }
    
    
    
    public MainActivity(){
    	mainActivity=this;
    }
    
    public static MainActivity getMainActivity() {
		return mainActivity;
	}
    
    public void clearScore(){//清零
    	score=0;
    	showScore();
    }
    
    public void showScore(){//显示分数
    	tvScore.setText(score+"");
    }
    
    public void addScore(int s){//加分
    	score+=s;
    	showScore();
    }



    
}

最后来一些游戏截图吧~







----------------------------晴天_1993----------------------------


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值