1. 程式人生 > >mcrwayfun,歡迎你

mcrwayfun,歡迎你

現在我們要實現一個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----------------------------