Android developers a simple game of 2048

As an android slag slag for the first time to write a simple android games to imitate or online video written ,, hey ,,


Video Tutorial links


EDITORIAL: Here I use the IDE is eclipse, and so on, it might be a bit of Android studio that ,,,

But the main code should be no problem, ha ,,


Interface and implementation of logic:    

1,activity_main.xml

This is the main screen of the game (layout), linear layout of the entire game interface, then a nested sub-panel layout also linear meter,

The middle with two textView Score a display font and then a display score following the game interface binding with classes, class inheritance

Grid layout, and then the game's main layout is achieved in that class

2, card.java class

This is the 2048 game abstracted cards, here we come to define the nature and number of the interface card only for us, we

A lable components to a card, the size of 32 * 32 as digital display num, if 0 is empty, the color will be different according to figures

Different layouts controlled by layoutparms, margins 10, i.e. the distance between the grid and the grid 10

3, GameView.java 类

Here is a layout of the game logic and game interface control, game initGameView first be initialized by the constructor () there is provided

Interface as the layout of four, the background color is 0xffbbada0 then write a listening event, listen for touch events, setOnTouchListener,

First, we define herein startX, startY, offsetX, offsetY, when the touch startX = even.getX (), startY = even.getY () when the touch

At the end of touch, offsetX = even.getX () - startX offsetY = even.getY () - startY With these variables we can judge

Finger sliding direction, and if if abs (offsetX)> abs (offsetY) the sliding direction is defined as horizontal movement, then we define

If the offset X <-5 compared to the left, where a relative value taking the other Similarly available, then we override onSizeChanged method,

That is, if the window is a big change on the implementation of this method, when a start to open the way to change the window size, where you want to configure in the configuration file

Screen for the portrait, and then execute this method, so we can record card here longWidth = (min (w, h) -10) / 4, then

addCard (); startGame (); in addCard, we first define a two-dimensional array to hold the card on the card interface 4 * 4

Then the initial value is 0, the initial card interface 4 * 4 Here, two cards add randomly is then written here randomly generated cards

The method, we first of all sets the empty deposit into card points, which then generates a random number, and then generates a random number

Number, here 2: 4 = 9: 1, so we can determine the number of generated comparison 0-1 and 0.1, and then achieved the 1: 9, then you

The operation is moving, we were written about four methods to achieve operating up and down, for a three-cycle operation we use to traverse,

Here we assume that the right, we traverse the outer loop x, y from 1-4, and then loops through the memory 4 to the y + 1, i.e. moved to the right in each row,

We start looking for the far right, to see if it's left a card, and then have to determine whether or not identical, put the numbers together there is the far right

The edge card is not put the same card is moved to its left, then move one space to the left (if currently) appeared valid if

Will move in a random card, and finally determines the end of the card is not empty and no adjacent and same card numbers


The above is my brief three major classes of code my code, some vague hope that understanding, expression is not very clear, mainly to see the code!



MainActivity.java

package com.example.game2048;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {

	
	public MainActivity() {
		// TODO Auto-generated constructor stub
		setMainActivity(this);
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		tvScore = (TextView) findViewById(R.id.tvScore);
		
		
	}

	@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;
	}
	
	
	public void clearScore(){
		score = 0;
		showScore();
	}
	
	public void showScore(){
		tvScore.setText(score+"");
	}
	
	public void addScore(int s){
		score+=s;
		showScore();
	}
	
	public static MainActivity getMainActivity() {
		return mainActivity;
	}

	public static void setMainActivity(MainActivity mainActivity) {
		MainActivity.mainActivity = mainActivity;
	}
	private int score = 0;
	private  TextView tvScore;
	private static MainActivity mainActivity = null;
	

}



activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context=".MainActivity" >
    
    
    
    <LinearLayout 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/score"/>
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/tvScore"/>
        
        
    </LinearLayout>
    
    <com.example.game2048.GameView
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:id="@+id/gameView">
        
    </com.example.game2048.GameView>

</LinearLayout>




card.java

package com.example.game2048;

import android.R.color;
import android.content.Context;
import android.content.pm.LabeledIntent;
import android.graphics.Color;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.TextView;

public class Card extends FrameLayout {

	
	// 记录卡片的颜色
	
	private int [] cardColor = new int[30]; 
	
	
	//初始化卡片的颜色
	public void setColor(){
		cardColor[0] =Color.BLUE;
		cardColor[1] = Color.CYAN;
		cardColor[8] = Color.DKGRAY;
		cardColor[5] = Color.GRAY;
		cardColor[4] = Color.GREEN;
		cardColor[3] = Color.RED;
		cardColor[6] = Color.LTGRAY;
		cardColor[7] = Color.MAGENTA;
		cardColor[2]= Color.YELLOW;
		cardColor[9] = Color.WHITE;
		cardColor[10] = Color.TRANSPARENT;
	}
	
	
	//构造方法
	public Card(Context context) {
		super(context);
		
		setColor();
		lable = new TextView(getContext());
		lable.setTextSize(32);				//设置大小
		lable.setBackgroundColor(0x33ffffff);   //背景颜色
		lable.setGravity(Gravity.CENTER);		//布局为居中

		LayoutParams lp = new LayoutParams(-1,-1);
		lp.setMargins(10, 10, 0, 0);		//边距为10
		addView(lable, lp);
		setNum(0);
		
	}
	private int num = 0;
	
	
	//获取数字
	public int getNum() {
		return num;
	}

	//设置数字
	public void setNum(int num) {
		this.num = num;
		if(num<=0){
			lable.setBackgroundColor(0x33ffffff);
			lable.setText("");
		}else {
			//取log得到x设置颜色
			int x =(int) (Math.log((double)num));
			x%=11;
			lable.setBackgroundColor(cardColor[x]);
			lable.setText(num+"");
		}
		
	}

	//卡片的lable组件
	private TextView lable;
	
	
	//判断是否相等
	public boolean equals(Card o) {
		// TODO Auto-generated method stub
		return num==o.getNum();
	}
	

}



GameView.java


package com.example.game2048;

import java.util.ArrayList;
import java.util.List;

import android.R.bool;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Point;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.GridLayout;

public class GameView extends GridLayout {

	//构造方法
	
	
	public GameView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
		initGameView();
	}

	public GameView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		initGameView();
	}

	public GameView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		initGameView();
	}

	
	//初始化游戏
	private void initGameView(){
		
		setColumnCount(4);   //设置列为4
		setBackgroundColor(0xffbbada0);  //设置背景色
		
		//监听触摸事件
		setOnTouchListener(new OnTouchListener() {
			
			private float startX,startY,offsetX,offsetY;   //四个变量记录初始位置和偏移量
			
			@Override
			public boolean onTouch(View arg0, MotionEvent even) {
				// TODO Auto-generated method stub
				switch(even.getAction()){
				case MotionEvent.ACTION_DOWN:    //记录初始位置
					startX = even.getX();
					startY = even.getY();
					break;
				case MotionEvent.ACTION_UP:      //记录偏移量
					offsetX = even.getX()-startX;
					offsetY = even.getY() -startY;
					
					
					if(Math.abs(offsetX)>Math.abs(offsetY)){   //X的偏移量大于Y的偏移量
						if(offsetX<-5){
							swipeLeft();		//向左的操作
						}else {
							swipeRight();		//向右的操作
						}
					}else {
						if(offsetY<-5){
							swipeUp();			//向上的操作
						}else{
							swipeDown();		//向下的操作
						}
					}
					
					break;
				
				}
				
				return true;
			}
		});
	}
	
	
	//重载方法,窗口大小改变使执行
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		// TODO Auto-generated method stub
		super.onSizeChanged(w, h, oldw, oldh);
		//记录卡片的大小
		int cardWidth = (Math.min(w, h)-10)/4;
		//添加卡片
		addCards(cardWidth, cardWidth);
		//开始游戏
		startGame();
		
	}
	
	
	//添加卡片
	private void addCards(int cardWidth,int cardHeight){
		Card card;
		//4*4
		for(int i=0;i<4;i++){
			for(int j=0;j<4;j++){
				card = new Card(getContext());   //初始化卡片对象
				card.setNum(0);					//初始值为0
				addView(card,cardWidth,cardHeight);//添加
				cardsMap[i][j] = card;				//将卡片与cardMap绑定
			}
		}
	}
	
	//添加随机卡片
	private void addRandomNum(){
		
		//记录空卡片的点的集合
		emptyPoints.clear();
		for(int i=0;i<4;i++){
			for(int j=0;j<4;j++){
				if(cardsMap[j][i].getNum()<=0){
					emptyPoints.add(new Point(j,i));  //添加所有空卡片
				}
			}
		}
		Point point = emptyPoints.remove((int)(Math.random()*emptyPoints.size()));  //从空卡片中随机一个卡片
		cardsMap[point.x][point.y].setNum(Math.random()>0.1?2:4);				//随机生成一个数 2:4 = 1:9
	}
	
	//开始游戏方法
	private void startGame(){
		//分数清零
		MainActivity.getMainActivity().clearScore();
		for(int i=0;i<4;i++){
			for(int j=0;j<4;j++){
				cardsMap[j][i].setNum(0);  //初始化为0
			}
		}
		//随机生成两个卡片
		addRandomNum();
		addRandomNum();
	}
	
	
	//向左移动的方法
	private void swipeLeft(){
		boolean flag = false;
		for(int x = 0;x<4;x++){
			for(int y = 0;y<4;y++){
				for(int y1 = y+1;y1<4;y1++){
					if(cardsMap[x][y1].getNum()>0){	//如果枚举位置有卡片
						if(cardsMap[x][y].getNum()<=0){		//如果当前位置没有卡片
							cardsMap[x][y].setNum(cardsMap[x][y1].getNum());	//直接移动到当前位置
							cardsMap[x][y1].setNum(0);
							y--;	//向前移动
							flag = 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());  //分数增加
							flag = true;
						}
						
						break;
					}
				}
			}
		}
		if(flag){
			//如果有有效移动则随机一张卡片并且判断是否结束
			addRandomNum();
			checkComplete();
		}
	}
	
	//同上 向右移动的操作
	private void swipeRight(){
		boolean flag = false;
		for(int x = 0;x<4;x++){
			for(int y = 3;y>=0;y--){
				for(int y1 = y-1;y1>=0;y1--){
					if(cardsMap[x][y1].getNum()>0){
						if(cardsMap[x][y].getNum()<=0){
							cardsMap[x][y].setNum(cardsMap[x][y1].getNum());
							cardsMap[x][y1].setNum(0);
							y++;
							flag = 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());
							flag = true;
						}
						
						break;
					}
				}
			}
		}
		if(flag){
			addRandomNum();
			checkComplete();
		}
	}
	//同上,向上移动的操作
	private void swipeUp(){
		boolean flag = false;
		for(int y = 0;y<4;y++){
			for(int x = 0;x<4;x++){
				for(int x1 = x+1;x1<4;x1++){
					if(cardsMap[x1][y].getNum()>0){
						if(cardsMap[x][y].getNum()<=0){
							cardsMap[x][y].setNum(cardsMap[x1][y].getNum());
							cardsMap[x1][y].setNum(0);
							x--;
							flag = 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());
							flag = true;
						}
						
						break;
					}
				}
			}
		}
		if(flag){
			addRandomNum();
			checkComplete();
		}
		
	}
	//同上,向下移动的操作
	private void swipeDown(){
		
		boolean flag = false;
		
		for(int y = 0;y<4;y++){
			for(int x = 3;x>=0;x--){
				for(int x1 = x-1;x1>=0;x1--){
					if(cardsMap[x1][y].getNum()>0){
						if(cardsMap[x][y].getNum()<=0){
							cardsMap[x][y].setNum(cardsMap[x1][y].getNum());
							cardsMap[x1][y].setNum(0);
							x++;
							 flag = 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());
							flag = true;
						}
						break;
					}
				}
			}
		}
		
		if(flag){
			addRandomNum();
			checkComplete();
		}
	}
	
	
	//判断是否结束游戏
	private void checkComplete(){
		boolean complete = true;
		All:
		for(int x = 0;x<4;x++){
			for(int y=0;y<4;y++){
				//判断有空或上下左右有相同的卡片则没结束
				if(cardsMap[x][y].getNum()==0||
				  (x-1>=0&&cardsMap[x][y].equals(cardsMap[x-1][y]))||
				  (x+1<4&&cardsMap[x][y].equals(cardsMap[x+1][y]))||
				  (y-1>=0&&cardsMap[x][y].equals(cardsMap[x][y-1]))||
				  (y+1<4&&cardsMap[x][y].equals(cardsMap[x][y+1]))){
					complete = false;
					break All;
				}
			}
		}
		//游戏结束
		if(complete){
			new AlertDialog.Builder(getContext()).setTitle("你好").setMessage("游戏结束!").setPositiveButton("重来", new DialogInterface.OnClickListener() {

				
				//重新开始游戏
				@Override
				public void onClick(DialogInterface arg0, int arg1) {
					// TODO Auto-generated method stub
					startGame();
				}
			}).show();
		}
		
	}
	
	//记录4*4卡片的数组
	private Card [][] cardsMap = new Card[4][4];
	//记录空卡片的集合
	private List<Point> emptyPoints = new ArrayList<Point>();
	
}



Published 110 original articles · won praise 76 · views 110 000 +

Guess you like

Origin blog.csdn.net/qq_34731703/article/details/73380156