Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> [Android] 開心消消樂代碼(寫的比較簡單)

[Android] 開心消消樂代碼(寫的比較簡單)

編輯:關於Android編程

突然想要在android上寫一個消消樂的代碼,在此之前沒有系統地學過java的面向對象,也沒有任何android相關知識,不過還是會一點C++。8月初開始搭建環境,在這上面花了相當多的時間,然後看了一些視頻和電子書,對android有了一個大概的了解,感覺差不多了的時候就開始寫了。

瘋狂地查閱各種資料,反反復復了好幾天後,也算是寫出了個成品。原計劃有很多地方還是可以繼續寫下去的,比如UI設計,比如動畫特效,時間設計,關卡設計,以及與數據庫的連接,如果可以的話還能寫個聯網功能,當然因為寫到後期內心感到格外的疲倦,所以以上內容全部被砍掉了。

所以最後的成果就只有這樣了……因為完全沒有設計過所以非常難看,功能也只有消方塊而已,圖片還是從之前寫的連連看裡搬過來的。反正就算一個小的demo好了。

\

\

 

布局

一開始設計的布局是xml裡的,但是後來想了想有64個按鈕這樣復制下去實在是太不好了,所以就把按鈕那一部分用代碼布局了。

 

    private void initBtn(int i,int j)
    {
		btn[8*i+j].setBackgroundDrawable
		(this.getResources().getDrawable(getStyle()));
		point p = new point(i,j,btn[8*i+j],id);
		btn[8*i+j].setTag(p);
		map[i][j] = num;
    }

//……
        LinearLayout vlayout = (LinearLayout)findViewById(R.id.vlayout);
        TableLayout tlayout = new TableLayout(this);
        TableRow row[] = new TableRow[8];
        for(int i=0;i<8;i++){
        	row[i] = new TableRow(this);
        	row[i].setGravity(Gravity.CENTER);
        	for(int j=0;j<8;j++){
        		btn[8*i+j] = new ImageButton(this);
        		btn[8*i+j].setLayoutParams(new TableRow.LayoutParams(38,38));
        		initBtn(i,j);
        		btn[8*i+j].setOnClickListener(listener);
        		row[i].addView(btn[8*i+j]);
        	}
        	tlayout.addView(row[i]);
        }
//……


 


 

其中getStyle()函數返回了按鈕的樣式id,該id是隨機生成的。

point p存儲了關於按鈕的信息,它在按鈕點擊事件中會被使用。

 

android中的按鈕有三種狀態:點擊態、普通態、焦點態。最後一個的意思是用戶按方向鍵盤(或類似功能鍵)來控制哪個按鈕處於焦點,這樣就可以不通過鼠標對按鈕進行操作。當然在這裡並沒有用到這個狀態,只用到了前面兩種,但是因為已經有現成圖片了,就把三種狀態都寫入了btn?.xml(放在drawable文件夾下),使用的時候直接引用這個xml文件就可以了。

btn1.xml:

 


  
  
      
      
      
      
  


 


\

 

 

判斷是否可消去

在點擊事件中,用兩個變量記錄先後點擊的按鈕信息,這兩個變量是滾動使用的,也就是說,第一次點擊存入變量1,第二次點擊存入變量2,第三次點擊存入變量1,第四次點擊存入變量2……額外有一個布爾變來控制信息存入哪個變量。 每次點擊後,都計算先後兩次點擊的按鈕是否相鄰。如果相鄰,那麼交換它們的位置。 我們用二維數組mark來記錄每個方塊是否可以消去,初始化為0。交換後,先一行行地掃描一遍,檢查是否有相連的三個以上圖案相同的按鈕,如果有的話,把它們都做上標記。然後再一列列掃描一遍,同樣檢查是否有相連的三個以上圖案相同的按鈕。總體復雜度為O(2*n^2) 當然可以有更快的算法,但是在這個代碼裡,我們對計算的速度沒有要求,甚至希望它慢一些(因為動畫效果需要在這裡停頓一下),所以就沒有必要進行優化了。 那麼mark裡存儲些什麼呢?一開始我把mark設計為布爾量,可消去的設為true。後來寫到消去後更新按鈕後,我突然想到mark裡不僅僅可以記錄是否可消去,還可以記錄消去後應該更新為什麼。 我們知道,消去一行按鈕後,上面的按鈕會掉下來補充空位,也就是說消去的這一行會被上面一行取代。所以我們把這些按鈕的mark賦值為1。 同樣,消去一列n個按鈕後,每個按鈕會被它上面第n個按鈕取代,所以我們把這些按鈕的mark賦值為n。 這樣,在更新的時候,我們只需要遍歷二維數組mark,根據它對應的值,來采取相應的操作就可以了。 在這裡,要注意順序性的問題,首先,在賦值mark的時候,應該先掃描橫行,再掃描豎列,因為可能會出現十字架或T字型的消去,這裡橫縱有重疊,而更新的時候以縱為准,所以後掃描縱列來覆蓋橫行的值。 另外一個要注意的順序,就是在更新的時候,一定要從上往下掃描。如果從下往上掃描的話,下面圖案的更新可能會破壞到上面的圖,那麼,上面原來存在的可以被消去的方塊就已經被破壞了,但是mark還記錄著消去方塊的索引,這樣就會引起錯的消去。反之,上面圖案的消去是不會破壞下面的圖案的。

判斷地圖是否還存在解

每一輪消去後,我們都需要判斷地圖上是否還存在解,如果不存在,就要進行更新。 因為僅僅是判斷存在性,算法略有變化。 我們需要考慮到所有的交換情況,以及它們能否產生可行解,一旦找到一個,我們就可以返回true。所以外循環包含兩個,一個掃描橫向相鄰的所有方塊,一個掃描縱向相鄰的所有方塊。 對於特定的兩個方塊,我們先交換它們,然後對於兩個方塊,都計算它們的十字架區域是否存在可行解,之後再把它們交換回來: \(十字架區域) 總體的最壞時間復雜度是2*(n^2)*2*8。

多線程

在主線程裡,按理來說應該有消去 — 更新這樣的畫面,但是我發現android是直接把所有東西都計算了出來,然後再去顯示UI的,而不是邊計算邊顯示,所以我之前設置的那些一步步更新畫面的代碼一點兒用也沒有,然後我想了想估計是要用多線程來寫,在此之前我沒有寫過多線程的代碼,所以花了一天時間看了多線程並把這部分修正了。 大概的想法是這樣的:每次點擊了兩個相鄰按鈕後,先交換兩個按鈕,然後調用線程的start()方法。 在線程重寫的run()方法裡,先計算是否存在解(find函數),如果可以消去,每隔0.03s發送一個消息,通知主線程,主線程設置按鈕的alpha值減小(增加透明度),反復10次,這樣就做出了按鈕慢慢消失的效果。 之後,再停頓0.1s,向主線程發送一個消息,主線程開始進行更新按鈕操作。更新之後,因為掉落下來的按鈕還可能組成新的可消去的部分,所以繼續調用線程的start方法,直到不存在可消去的按鈕。 如果不存在解,那麼,先判斷這是因為用戶點擊的兩個按鈕無法產生解,還是之前消去後掉落下來的按鈕不會產生解。我們用flag來記錄這一狀態。如果是前者,先停頓0.3s,再把兩個按鈕的位置交換回來;如果是後者,說明已經消去所有按鈕,這時我們檢查是否還存在可行解,如果不存在,向主線程發送一個消息,通知它更新地圖。 總之就是重寫run,以及消息機制的使用。特別注意的就是run中絕對不能寫UI的操作,UI的事情只能交給主線程做,所以才需要不斷通知。 還有一個要注意線程之間的執行順序,調試了很久的一個地方,後來發現是因為主線程那邊還沒計算出結果,但是次線程已經開始新的計算了,所以此線程用到的是主線程沒有更新過的舊數據。後來想到的方法就是等主線程算完了,再回來調用次線程的函數。
    @Override  
    public void run()  
    {  
		if(find()){
			flag = false;
			int n = 10;
			alpha = 255;
			while(n--!=0){
    		    wait(30);
    		    mHandler.sendEmptyMessage(0);
			}
    		wait(100);
    		mHandler.sendEmptyMessage(1);
    	
	    }
		else if(flag==true){
			swapMap(p1.x,p1.y,p2.x,p2.y);
    		wait(300);
    		mHandler.sendEmptyMessage(2);
	   	}
		else if(flag==false){
	    	p1 = new point(-2,-2);
    	    p2 = new point(-2,-2);
			if(check()==false){
				mHandler.sendEmptyMessage(3);
			}
		}
    }

代碼

\ main.xml


        

MainActivity.java
package com.example.android.market.licensing;  
  
import android.annotation.SuppressLint;  
import android.app.Activity;  
import android.os.Bundle;  
import android.os.Handler;  
import android.os.Message;  
import android.widget.ImageButton;  
import android.widget.LinearLayout;  
import android.widget.TableLayout;  
import android.widget.TableRow;  
import android.widget.TextView;  
import android.widget.Toast;  
import android.view.Gravity;  
import android.view.View;  
  
  
@SuppressLint("NewApi")  
public class MainActivity extends Activity implements Runnable {  
    private static final String TAG = "App";  
    private point p1 = new point(-2,-2);  
    private point p2 = new point(-2,-2);;  
    private boolean isPoint1 = true;  
    private int map[][] = new int[8][8];  
    private int id;  
    private int mark[][] = new int[8][8];  
    private Thread thread;  
    private int num;  
    private int alpha = 255;  
    boolean flag = false;  
    private int score = 0;  
    private TextView text;  
    ImageButton[] btn = new ImageButton[64];  
      
    private int getStyle(){  
        num = (int)(1+Math.random()*(7-1+1));  
        switch(num){  
        case 1:return id = R.drawable.btn1;  
        case 2:return id = R.drawable.btn2;  
        case 3:return id = R.drawable.btn3;  
        case 4:return id = R.drawable.btn4;  
        case 5:return id = R.drawable.btn5;  
        case 6:return id = R.drawable.btn6;  
        case 7:return id = R.drawable.btn7;  
        default:return id = 0;  
        }  
    }  
  
  
    public MainActivity() { }  
  
    private void initBtn(int i,int j)  
    {  
        btn[8*i+j].setBackgroundDrawable  
        (this.getResources().getDrawable(getStyle()));  
        point p = new point(i,j,btn[8*i+j],id);  
        btn[8*i+j].setTag(p);  
        map[i][j] = num;  
    }  
      
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
        LinearLayout vlayout = (LinearLayout)findViewById(R.id.vlayout);  
        TableLayout tlayout = new TableLayout(this);  
        TableRow row[] = new TableRow[8];  
        for(int i=0;i<8;i++){  
            row[i] = new TableRow(this);  
            row[i].setGravity(Gravity.CENTER);  
            for(int j=0;j<8;j++){  
                btn[8*i+j] = new ImageButton(this);  
                btn[8*i+j].setLayoutParams(new TableRow.LayoutParams(38,38));  
                initBtn(i,j);  
                btn[8*i+j].setOnClickListener(listener);  
                row[i].addView(btn[8*i+j]);  
            }  
            tlayout.addView(row[i]);  
        }  
        text = new TextView(this);       
        text.setText("分數 : 0");  
        vlayout.addView(tlayout);  
        vlayout.addView(text);  
        while(find()){  
            updateState();  
        }  
        thread = new Thread(this);    
    }  
      
    private void wait(int time)  
    {  
        try {  
            Thread.sleep(time);  
        } catch (InterruptedException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
    }  
      
    @Override    
    public void run()    
    {    
        if(find()){  
            flag = false;  
            int n = 10;  
            alpha = 255;  
            while(n--!=0){  
                wait(30);  
                mHandler.sendEmptyMessage(0);  
            }  
            wait(100);  
            mHandler.sendEmptyMessage(1);  
          
        }  
        else if(flag==true){  
            swapMap(p1.x,p1.y,p2.x,p2.y);  
            wait(300);  
            mHandler.sendEmptyMessage(2);  
        }  
        else if(flag==false){  
            p1 = new point(-2,-2);  
            p2 = new point(-2,-2);  
            if(check()==false){  
                mHandler.sendEmptyMessage(3);  
            }  
        }  
    }    
  
     void swapImage()  
    {  
        p1.v.setBackgroundDrawable  
        (MainActivity.this.getResources().getDrawable(p2.id));  
        p2.v.setBackgroundDrawable  
        (MainActivity.this.getResources().getDrawable(p1.id));  
        int tmp =p1.id;  
        p1.id = p2.id;  
        p2.id = tmp;  
        p1.v.setTag(p1);  
        p2.v.setTag(p2);  
    }  
      
    private void updateBtn(int x1,int y1,int x2,int y2)  
    {  
        map[x1][y1] = map[x2][y2];  
        point p = (point)(btn[8*x1+y1].getTag());  
        p.id = ((point)(btn[8*x2+y2].getTag())).id;  
        btn[8*x1+y1].setTag(p);  
        btn[8*x1+y1].setBackgroundDrawable  
        (MainActivity.this.getResources().getDrawable(p.id));  
    }  
      
    private void updateBtn(int i,int j)  
    {  
        btn[8*i+j].setBackgroundDrawable  
        (MainActivity.this.getResources().getDrawable(getStyle()));  
        map[i][j] = num;  
        point p = (point)(btn[8*i+j].getTag());  
        p.id = id;  
        btn[8*i+j].setTag(p);  
    }  
  
    private void hideBtn(){  
        alpha -= 25;  
        for(int i=0;i<8;i++){  
            for(int j=0;j<8;j++){  
                if(mark[i][j]!=0&&mark[i][j]!=2){  
                    btn[8*i+j].getBackground().setAlpha(alpha);           
                }  
            }  
        }  
    }  
  
      
    private void updateState()  
    {  
          
        for(int i=0;i<8;i++){  
            for(int j=0;j<8;j++){  
                btn[8*i+j].getBackground().setAlpha(255);             
            }  
        }  
        for(int i=0;i<8;i++){  
            for(int j=0;j<8;j++){  
                if(mark[i][j]==1){  
                    for(int k=i;k>0;k--){  
                        updateBtn(k,j,k-1,j);  
                    }  
                     updateBtn(0,j);  
                }  
                else if(mark[i][j]>=3){  
                    if(i-mark[i][j]>=0) {  
                        updateBtn(i,j,i-mark[i][j],j);  
                        updateBtn(i-mark[i][j],j);  
                    }  
                    else{  
                        updateBtn(i,j);  
                    }  
                }  
                else if(mark[i][j]==2){
                	updateBtn(i,j);
                }
            }  
        }  
    }  
      
    public Handler mHandler=new Handler()    
    {    
        public void handleMessage(Message msg)    
        {    
            switch(msg.what){  
                case 0:{  
                    hideBtn();  
                    break;  
                }     
                case 1:{  
                    updateState();  
                    text.setText("分數 " + ((Integer)score).toString());  
                    thread.start();  
                    break;  
                }  
                case 2:{  
                    swapImage();  
                    p1 = new point(-2,-2);  
                    p2 = new point(-2,-2);  
                    break;  
                }  
                case 3:{  
                    Toast.makeText(MainActivity.this, "已自動生成新地圖", Toast.LENGTH_SHORT).show();   
                    for(int i=0;i<8;i++){  
                        for(int j=0;j<8;j++){  
                            initBtn(i,j);  
                        }  
                    }  
                    while(find()){  
                        updateState();  
                    }  
                    break;  
                }  
            }  
            super.handleMessage(msg);    
        }    
    };        
      
    private boolean find()  
    {  
        for(int i=0;i<8;i++){  
            for(int j=0;j<8;j++){  
                mark[i][j] = 0;  
            }  
        }  
        boolean flag = false;  
        // heng  
        for(int i=0;i<8;i++){  
            int count = 1;  
            for(int j=0;j<7;j++){  
                if(map[i][j]==map[i][j+1]){  
                    count++;  
                    if(count==3){  
                        flag = true;  
                        mark[i][j-1] = 1;  
                        mark[i][j] = 1;  
                        mark[i][j+1] = 1;  
                        score += 15;  
                    }  
                    else if(count>3){  
                        mark[i][j+1] = 1;  
                        score += 5;  
                    }  
                }  
                else count = 1;  
            }  
        }  
        //shu  
        for(int j=0;j<8;j++){  
            int count = 1;  
            for(int i=0;i<7;i++){  
                if(map[i][j]==map[i+1][j]){  
                    count++;  
                    if(count==3){  
                        flag = true;  
                        if(mark[i][j]==1)score+=10;  
                        else score +=15;  
                        mark[i-1][j] = 3;  
                        mark[i][j] = 3;  
                        mark[i+1][j] = 3;  
                        for(int k=i-1;k>=0;k--){
                        	mark[k][j] = 2;  
                        }
                    }  
                    else if(count>3){  
                        mark[i+1][j] = count;  
                        for(int k=1;k=1&&map[i-1][j]==map[i][j]){  
            count++;  
            if(i>=2&&map[i-2][j]==map[i][j]){  
                count++;  
            }  
        }  
        if(count>=3)return true;  
        if(i+1<8&&map[i+1][j]==map[i][j]){  
            count++;  
            if(i+2<8&&map[i+2][j]==map[i][j]){  
                count++;  
            }  
        }  
        if(count>=3)return true;  
          
        //heng  
        count = 1;  
        if(j>=1&&map[i][j-1]==map[i][j]){  
            count++;  
            if(j>=2&&map[i][j-2]==map[i][j]){  
                count++;  
            }  
        }  
        if(count>=3)return true;  
          
        if(j+1<8&&map[i][j+1]==map[i][j]){  
            count++;  
            if(j+2<8&&map[i][j+2]==map[i][j]){  
                count++;  
            }  
        }  
        if(count>=3)return true;  
          
        return false;  
    }  
      
    private void swapMap(int x1,int y1,int x2,int y2)  
    {  
        int tmp = map[x1][y1];  
        map[x1][y1] = map[x2][y2];  
        map[x2][y2] = tmp;  
    }  
      
    private boolean check()  
    {  
          
        //heng  
        for(int i=0;i<8;i++){  
            for(int j=0;j<7;j++){  
                swapMap(i,j,i,j+1);  
                if(check(i,j)){  
                    swapMap(i,j,i,j+1);  
                    return true;  
                }  
                if(check(i,j+1)){  
                    swapMap(i,j,i,j+1);  
                    return true;  
                }  
                swapMap(i,j,i,j+1);  
            }  
        }  
        //shu  
        for(int j=0;j<8;j++){  
            for(int i=0;i<7;i++){  
                swapMap(i,j,i+1,j);  
                if(check(i,j)){  
                    swapMap(i,j,i+1,j);  
                    return true;  
                }  
                if(check(i+1,j)){  
                    swapMap(i,j,i+1,j);  
                    return true;  
                }  
                swapMap(i,j,i+1,j);  
            }  
        }  
        return false;  
    }  
      
    ImageButton.OnClickListener listener = new ImageButton.OnClickListener(){//創建監聽對象      
        @SuppressLint("NewApi")  
  
        public void onClick(View v) {  
            if(isPoint1){  
                p1 = (point)v.getTag();  
                isPoint1 = false;  
            }  
            else {  
                p2 = (point)v.getTag();  
                isPoint1 = true;  
            }  
          
            if(((p1.x-p2.x==1||p1.x-p2.x==-1)&&p1.y==p2.y)||  
               (p1.y-p2.y==1||p1.y-p2.y==-1)&&p1.x==p2.x){  
                flag = true;  
                swapMap(p1.x,p1.y,p2.x,p2.y);  
                swapImage();  
                thread.start();  
            }  
        }  
  
    };  
}  

  point.java
package com.example.android.market.licensing;
import android.view.View;
public class point {
	public int x;
	public int y;
	View v;
	int id;
	point(int _x,int _y,View _v,int _id){
		x = _x;
		y = _y;
		v = _v;
		id = _id;
	}
	point(int _x,int _y){
		x = _x;
		y = _y;
	}
}

  AndroidManifest.xml



    
        
            
                
                
            
        
    
    
    
    
    


 
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved