安卓项目五子棋代码详解(五)

 

 

这一期给大家带来我自己添加的功能,最近还搞了个播放背景音乐和下棋音效,与这个一起讲了

 开笔之前,忽然响起还有一个保存游戏没讲,真是失误。

保存游戏呢,就是将当前棋子的位置都保存下来,我们可以设想一个情景,玩家玩着游戏的时候,忽然一个电话过来,就会跳转到打电话的界面,或者一条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

 

posted @ 2017-08-26 20:29  Stars-one  阅读(2505)  评论(5编辑  收藏  举报