天天看點

安卓項目五子棋代碼詳解(五)

這一期給大家帶來我自己添加的功能,最近還搞了個播放背景音樂和下棋音效,與這個一起講了

 開筆之前,忽然響起還有一個儲存遊戲沒講,真是失誤。

儲存遊戲呢,就是将目前棋子的位置都儲存下來,我們可以設想一個情景,玩家玩着遊戲的時候,忽然一個電話過來,就會跳轉到打電話的界面,或者一條QQ消息要處理,玩家跳轉到了QQ的界面處理消息,待他處理完之後,就會傳回遊戲,如果我們沒有設定儲存遊戲的這個方法的話,那麼玩家再次進入的時候就是跟開始的一樣,這樣的體驗非常糟糕,是以儲存遊戲這個方法是必須要有的。

首先在Panel類中聲明四個靜态變量

private static final String INSTANCE = "instance";
private static final String INSTANCE_GAME_OVER = "instance_game_over" ;//遊戲狀态
private static final String INSTANCE_WHITE_ARRAY = "instance_white_array";//白棋坐标
private static final String INSTANCE_BLACK_ARRAY = "instance_black_array";//黑棋坐标      

之後,複寫onSaveInstanceState()和onRestoreInstanceState()這兩個方法

@Override
    protected Parcelable onSaveInstanceState() {//存儲目前下棋狀态
        Bundle bundle = new Bundle();
        bundle.putParcelable(INSTANCE, super.onSaveInstanceState());
        bundle.putBoolean(INSTANCE_GAME_OVER, IsGameOver);
        bundle.putParcelableArrayList(INSTANCE_WHITE_ARRAY, Whitearray);
        bundle.putParcelableArrayList(INSTANCE_BLACK_ARRAY, Blackarray);
        return bundle;
    }
    
    @Override
    protected void onRestoreInstanceState(Parcelable state) {//恢複下棋狀态
        if(state instanceof Bundle){
            Bundle bundle = (Bundle) state;
            IsGameOver = bundle.getBoolean(INSTANCE_GAME_OVER);
            Whitearray = bundle.getParcelable(INSTANCE_WHITE_ARRAY);
            Blackarray = bundle.getParcelable(INSTANCE_BLACK_ARRAY);
            super.onRestoreInstanceState(bundle.getParcelable(INSTANCE));
            return; 
        }      

這裡簡單的解釋一下,當使用者跳轉到其他的界面的時候,onSaveInstanceState()這個方法就會執行,将目前遊戲狀态,白棋坐标與黑棋坐标儲存,傳回bundle,這個bundle我個人了解成一個鑰匙或者是令牌,使用者回到遊戲,判斷語句判斷是否有鑰匙或令牌,若有,就開門,恢複已儲存的東西

 接下來就是關于界面及相關功能的介紹詳細講解

,給大家上張圖檔

首先,我們要定義一個xml界面,如圖,可以知道有着七個控件

xml代碼如下

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    
    android:background="@drawable/bsd"
    tools:context=".MainActivity" >
     
    <com.wan.wuziqi.Panel
        android:id="@+id/wuziqi"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:visibility="gone"
         />

    <Button
        android:id="@+id/gamestart"
        android:layout_width="120dp"
        android:layout_height="60dp"
        android:background="@drawable/bgcolor"
        android:visibility="visible"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="131dp"
        android:text="@string/gamestart" />

    <Button
        android:id="@+id/changebackground"
        android:visibility="visible"
        android:layout_width="120dp"
        android:layout_height="60dp"
        android:layout_alignLeft="@+id/gamestart"
        android:layout_below="@+id/gamestart"
        android:layout_marginTop="14dp"
        android:background="@drawable/bgcolor"
        android:text="@string/changebackground" />

    <Button
        android:id="@+id/about"
        android:visibility="visible"
        android:layout_width="120dp"
        android:layout_height="60dp"
        android:layout_alignLeft="@+id/quit"
        android:layout_below="@+id/quit"
        android:layout_marginTop="14dp"
        android:background="@drawable/bgcolor"
        android:text="@string/about" />

    <Button
        android:id="@+id/quit"
        android:visibility="visible"
        android:layout_width="120dp"
        android:layout_height="60dp"
        android:layout_alignLeft="@+id/changebackground"
        android:layout_below="@+id/changebackground"
        android:layout_marginTop="16dp"
        android:background="@drawable/bgcolor"
        android:text="@string/quit" />

    <ImageView
        android:id="@+id/title"
        android:layout_width="200dp"
        android:layout_height="80dp"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:src="@drawable/title"
        android:visibility="visible" />

    <Button
        android:id="@+id/luozisound"
        android:layout_width="25dp"
        android:layout_height="25dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:background="@drawable/yx1"
         />

    <Button
        android:id="@+id/bgmsound"
        android:layout_width="25dp"
        android:layout_height="25dp"
        android:layout_alignBottom="@+id/luozisound"
        android:layout_toRightOf="@+id/luozisound"
        android:background="@drawable/bgm1"
         />

</RelativeLayout>      

标題上的污子棋是一個ImageView,其餘的都是button按鈕

背景直接在relativeLayout中設定背景就好,其餘的也是簡簡單單的設定一下圖檔,位置的話直接用拖動就好,所見即所得,這倒是很友善。

值得一提的是,button中我用的背景是圓角矩形,上面的文字都是調用string中的字元,寫在string中也是友善管理,左上角的兩個button是我用來實作控制背景音樂和音效的控制開關,點選就是關閉

接下來就是到java代碼部分了

在MainActiviity 的onCreate()方法上方聲明變量

Panel p;
    Button gamestart,changebackground,quit,about,bgmsound,luozisound;
    View imageview;
    RelativeLayout relativelayout;//更換背景需要調用此對象
    private MediaPlayer bgmsoundPlayer;//背景音樂對象
    int i=0;      

之後,在onCreate()方法之中使用findViewbyID()方法

          p = (Panel)findViewById(R.id.wuziqi);
		
		gamestart = (Button)findViewById(R.id.gamestart);
		changebackground = (Button)findViewById(R.id.changebackground);
		quit = (Button)findViewById(R.id.quit);
		about = (Button)findViewById(R.id.about);
		imageview = (View)findViewById(R.id.title);
		bgmsound = (Button)findViewById(R.id.bgmsound);
		luozisound = (Button)findViewById(R.id.luozisound);
		
		relativelayout = (RelativeLayout)findViewById(R.id.main);
      

 之後,初始化背景音樂的檔案

bgmsoundPlayer = MediaPlayer.create(this, R.raw.bgm);//加載背景音樂檔案資源,準備狀态,start()方法才可以成功播放
        
bgmsoundPlayer.setLooping(true);//設定循環播放
bgmsoundPlayer.start();      

背景音樂檔案放在res/raw的檔案夾中,若沒有可以建立一個

在之後,就是為button按鈕綁定監聽器,重寫onClick()事件方法

ButtonListener buttonlistener = new ButtonListener();
        
        
        gamestart.setOnClickListener(buttonlistener);
        changebackground.setOnClickListener(buttonlistener);
        quit.setOnClickListener(buttonlistener);
        about.setOnClickListener(buttonlistener);
        bgmsound.setOnClickListener(buttonlistener);
        luozisound.setOnClickListener(buttonlistener);      
class ButtonListener implements OnClickListener{

        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.gamestart:
                    conceal();
                    p.setVisibility(View.VISIBLE);
                    break;
                
                case R.id.changebackground:
                    
                    changebackground();
                    break;
                case R.id.quit:
                    quit();
                    
                    break;
                case R.id.about:
                    AlertDialog.Builder builder1 = new AlertDialog.Builder(MainActivity.this);//參數裡面注意!!!
                    builder1.setTitle("關于");
                    builder1.setMessage("作者:柯興新一\n說明:本軟體純屬娛樂,勿作商業用途!!");
                    builder1.setPositiveButton("确定", new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface arg0, int arg1) {
                            arg0.cancel();
                        }});
                   
                    builder1.create().show();
                    break;
                case R.id.luozisound:
                    
                    luoziButtonChange(p.luozisoundOn);
                    p.luozisoundOn = !p.luozisoundOn;
                    
                case R.id.bgmsound:
                    
                        
                        bgmButtonChange(p.bgmsoundOn);
                        p.bgmsoundOn = !p.bgmsoundOn;
                        
                        
                    
                default:
                    break;
            }
            
        }      

這裡使用了switch語句,調用View裡的getId()方法獲得目前觸摸控件的ID,之後由case語句為不同ID配置設定不同的方法

這裡首先要說明的是,除了左上角的那兩個button按鈕不用隐藏,其餘的都應該是點選一下之後便是隐藏起來,由于代碼相同,為了使代碼簡潔,我就把設定button按鈕隐藏的代碼寫進了conceal()方法之中

private void conceal(){
            imageview.setVisibility(View.INVISIBLE);
            gamestart.setVisibility(View.INVISIBLE);
            changebackground.setVisibility(View.INVISIBLE);
            quit.setVisibility(View.INVISIBLE);
            about.setVisibility(View.INVISIBLE);
        }      

改變背景的方法

private void changebackground(){
            
            switch (i){
            case 0:
                relativelayout.setBackgroundResource(R.drawable.bsd2);
                i++;
                break;
            case 1:
                relativelayout.setBackgroundResource(R.drawable.bsd3);
                i++;
                break;
            case 2:
                relativelayout.setBackgroundResource(R.drawable.bsd4);
                i++;
                break;
            case 3:
                relativelayout.setBackgroundResource(R.drawable.bsd5);
                i++;
                break;
            case 4:
                relativelayout.setBackgroundResource(R.drawable.bsd6);
                i++;
                break;
            case 5:
                relativelayout.setBackgroundResource(R.drawable.bsd7);
                i++;
                break;
            case 6:
                relativelayout.setBackgroundResource(R.drawable.bsd8);
                i++;
                break;
            case 7:
                relativelayout.setBackgroundResource(R.drawable.bsd);
                i=0;
                break;
            }
        }
        
    }      

這裡說明一下,在之前的聲明有聲明了一個int型的變量i,它的目的就是用在改變背景的這裡,就相當于一個定時器,還是由switch()語句,由i的值改變進而換成不同的背景,當然,若果你想的話,這裡還可以弄成一個随機更換背景圖檔的,在case 末尾給i 随機指派就可以達到随機的更換背景圖檔的效果了,具體的請各位自己去嘗試。

quit()方法

private void quit(){
            AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);//參數裡面注意!!!
            builder.setMessage("是否退出?");
            builder.setPositiveButton("是", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.cancel();
                    onDestroy();
                }
            }).setNegativeButton("否", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.cancel();
                }
            });
            builder.create().show();

}
      

點選退出遊戲按鈕時,會彈出一個對話框,由使用者選擇是否退出

第一行代碼一直搞了半天,發現是裡面參數的問題,是以一定要注意參數

builder.setPositiveButton("是",建立監聽器).setNegativeButton("否", 建立監聽器);

positive是消極的,negative是積極的,不過這兩個按鈕監聽器裡的onClick事件不分消極還是積極的

quit()裡的onDestroy()方法

@Override
protected void onDestroy() {
    super.onDestroy();
    System.exit(0);
}
}      

System.exit(0)為完全退出

關于背景音樂和音效,我還設定了點選變色的功能

我定義了兩個方法,luoziButtonChange()和bgmButtonChange()方法,參數裡面傳入一個boolean值

PS:bgmsoundOn和luozisoundOn這兩個是在Panel類中定義的boolean值,預設是true

點選之後就會進行邏輯計算,由!邏輯運算符轉換數值

private void luoziButtonChange(boolean a){
            if(a){
                luozisound.setBackgroundResource(R.drawable.yx2);
                
            }else{
                luozisound.setBackgroundResource(R.drawable.yx1);
                
            }
        }
        private void bgmButtonChange(boolean a){
            if(a){
                bgmsound.setBackgroundResource(R.drawable.bgm2);
                bgmsoundPlayer.stop();
            }else{
                bgmsound.setBackgroundResource(R.drawable.bgm1);
                try {
                    bgmsoundPlayer.prepare();//停止之後需要進入準備狀态,下一次start()方法才可以成功播放
                } catch (IllegalStateException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                bgmsoundPlayer.start();
            }
        }      

改變圖檔調用setBackgroundResource()方法,音效使用的是soundpool,還有個play()方法用來播放聲音,每畫一個棋子,就播放一次聲音,是以我将play()方法放在了Panel類中的畫棋子方法中了

luozisoundCheck()方法

public void luozisoundCheck(){
        if(luozisoundOn){
            luozisound.play(1,1, 1, 0, 0, 1);
        }else{
            luozisound.stop(1);
        }
        
    }      

if語句判斷luozisoundOn的值是否為true,為true執行播放,為fasle停止播放

關于soundpool相關,我整理了一下,請點選

Android開發之SoundPool使用詳解

講完音效,到背景音樂了。

這背景音樂我其實找了好久的資料,但是總是實作不了,最後發現了問題,網上找的都是用對象new的一個對象,不知道為什麼用不了,我的是直接聲明才可以使用的,不太懂前面為什麼不能用,找到了答案再補上吧

 寫在尾聲:

五子棋作為android開發的簡單項目,特别适合新手入門,還可以在五子棋中添加自己能夠想象到功能,既可以學習,又可以從中得到樂趣。

我的五子棋還沒有實作藍牙對戰,自創熱點對戰,AI對戰,還有悔棋的功能,是以,我這系列還是沒有結束的~~O(∩_∩)O哈哈~

最近因為學習側滑菜單,eclipse上搞個Android5.0的SDK搞了半天都是不行的,是以轉到了Android Studio平台,這環境也是搞了兩天,真是累,不過可以用了,慢慢習慣Android Studio

感覺我的方法都是寫在了Panel類中,有些影響可讀性,之後有時間得優化一些項目,當然,用的是Android Studio

提問之前,請先看提問須知

點選右側圖示發起提問

安卓項目五子棋代碼詳解(五)

或者加入QQ群一起學習

安卓項目五子棋代碼詳解(五)

TornadoFx學習交流群:1071184701

安卓項目五子棋代碼詳解(五)
安卓項目五子棋代碼詳解(五)

繼續閱讀