Android開發簡單的2048遊戲

作爲一名android渣渣第一次用android寫了個簡單的小遊戲還是模仿網上的視頻寫的,,哎,,


視頻教程鏈接


寫在前面:這裏我用的IDE是eclipse,所以對與 Android studio 的來說可能會有點那個,,,

但是主要的代碼應該沒問題的哈,,


界面和實現的邏輯:    

1,activity_main.xml

這是遊戲的主界面(layout),遊戲界面 整體採用線性佈局,然後嵌套一個計分器面板也是線性佈局,

中間用了兩個textView一個顯示Score字體一個顯示分數然後下面的遊戲界面用個類綁定,類繼承

格子布局,然後遊戲的主要佈局就在那個類中實現

2,card.java 類

這是2048遊戲中的抽象出來的卡片,這裏我們來定義一些卡片的性質和一些接口供我們只用,我們用

個lable組件來表示卡片,大小爲32*32顯示的數字爲num,如果是0就是空 ,顏色會根據數字的不同而

不同,佈局用layoutparms 來控制,邊距爲10,即格子與格子之間的距離爲10

3,GameView.java 類

這裏是遊戲界面的佈局和遊戲邏輯的控制,首先通過構造函數來初始化遊戲initGameView()這裏面設置

界面佈局的列爲4列,背景顏色爲0xffbbada0然後 寫個監聽事件,監聽觸摸事件,setOnTouchListener,

首先這裏我們定義startX,startY,offsetX,offsetY,當觸摸時startX = even.getX(),startY = even.getY()當觸

摸結束時,offsetX = even.getX ()- startX offsetY = even.getY ()- startY  有了這些變量我們就可以判斷

手指滑動的方向了,如果如果abs(offsetX)>abs(offsetY)則滑動的方向定義爲水平移動,然後我們定義

如果offset X<-5則爲向左,這裏取了個相對值,其他的同理可得,然後我們重載 onSizeChanged方法,

即,如果窗口大改變是就執行這個方法,一開始打開時窗口大小方式改變,這裏要在配置文件裏配置

屏幕爲豎屏,然後就執行這個方法,所以我們可以在這裏記錄卡片的長寬 = (min(w,h)  -10)/4,然後

addCard(); startGame();在addCard中我們首先定義了個card的二維數組來保存界面上的4*4的卡片,

然後初始值爲0,這裏就初始了界面的4*4的卡片,然後就是隨機添加兩個卡片這裏寫個隨機生成卡片

的方法,首先我們用個集合把所有空的卡片的點存進去,然後從中隨機生成個,然後在隨機生成個

數,這裏2:4 = 9:1 ,所以我們就可以判斷生成0-1的數與0.1比較,然後就實現了這個1:9,接下來就

是移動的操作,我們分別寫四個方法實現上下左右的操作,對於一種操作我們用三層循環去遍歷,

這裏我們假設向右,我們外層循環遍歷x,y從1-4,然後內存循環遍歷4到y+1,即每一行向右移動,

我們先從最右邊找,看它的左邊是否有卡片,然後還要判斷是否相同,相同就把數字相加存在最右

邊這個卡片,不相同就把卡片移動到它的左邊,然後向左移動一格(如果當前有)如果出現過有效

的移動就要在隨機一個卡片,最後判斷結束就是沒有空的卡片並且沒有相鄰且數字相同的卡片


上面就是我簡單的介紹我的代碼的三個主要的代碼類,其中有些模糊希望理解,表達不是很清晰,主要還是看代碼吧!



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>();
	
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章