天天看點

手把手教你做一個2048 上0 簡介1 什麼是20482 抽象類的定義上篇總結

目錄

0 簡介

1 什麼是2048

0 簡介

閑來無事,搞了個2048玩玩,源碼放到了github上了,先上連結 https://github.com/tzx666/Android2048

現在已經實作的功能有

經典模式

自定義模式

曆史檢視、遊玩、删除自己自定義的模式

還沒有實作的功能有

遊戲的動畫、聲音

背景功能、創意上傳、圖檔合并等

效果圖

手把手教你做一個2048 上0 簡介1 什麼是20482 抽象類的定義上篇總結
手把手教你做一個2048 上0 簡介1 什麼是20482 抽象類的定義上篇總結
手把手教你做一個2048 上0 簡介1 什麼是20482 抽象類的定義上篇總結

1 什麼是2048

2048是一種遊戲,核心玩法是通過左滑右滑上滑下滑去合并相同的數字,如果到達了2048則判定為勝利,如果已經無法再滑動了則可以判斷失敗

那麼我們便可以構思出這個遊戲必然有以下功能

1 基礎背景,一個4*4的遊戲棋盤,這裡我們使用一維數組作為底層實作

2 滑動的合并與判斷

3 随機位置的生成

4 遊戲勝利和結束條件的判斷

5 引申而來的,我們同樣可以對遊戲使用mvc架構,即遊戲顯示什麼和實際邏輯是什麼并無關系,隻要定義符合合并機制,那麼無論顯示什麼都是合理的(霧)

2 抽象類的定義

根據上述的描述,我們不難定義出接口(其實應該用抽象類更合理的說)

interface Game2048 {
    fun init(context:Context);
    fun init(context:Context,size:Int);
    fun start();
    fun moveleft();
    fun moveright();
    fun moveup();
    fun movedown();
    fun addRanrom();
    fun isEnd();
    fun isFirstVisiable(position:Int):Boolean;
}
           

其中 init()負責初始化數組,isFirstVisiable()負責動畫出現的判斷,movexx函數負責遊戲過程中的合并

3 遊戲邏輯的實作

2048的遊戲邏輯比較簡單,參考代碼應該很好懂

/*
*@author tzx
*@descrption 2048的邏輯實作
*/
public class Game2048impl implements Game2048 {
    private  int score;
    private  int[] map;
    private boolean[] isfirstAppear;
    private  int MAPSIZE;
    private int GAME_OVER=101;
    private int GAME_WIN=102;
    private int GAME_CONTINUE=103;
    private int state=GAME_CONTINUE;
    private Context context;
    @Override
    public void init(Context context,int size) {
        MAPSIZE=size;
        this.context=context;
        map=new int[MAPSIZE*MAPSIZE];
        isfirstAppear=new boolean[MAPSIZE*MAPSIZE];
        addRanrom();
        addRanrom();
    }

    @Override
    public boolean isFirstVisiable(int positon) {
        return isfirstAppear[positon];
    }

    private enum state{
        GAME_OVER,GAME_CONTINUE,GAME_WIN
    };
    @Override
    public void init(Context context) {
        this.context=context;
        MAPSIZE=4;
        map=new int[MAPSIZE*MAPSIZE];
        isfirstAppear=new boolean[MAPSIZE*MAPSIZE];
        addRanrom();
        addRanrom();
    }

    @Override
    public void start() {

    }

    public int[] getMap() {
        return map;
    }

    @Override
    public void moveleft() {
        boolean merge=false;
        for(int i=0;i<4;i++){
            for(int j=0;j<4;j++){
                for(int z=j+1;z<4;z++){
                    if(map[i*MAPSIZE+z]>0){
                        if(map[i*MAPSIZE+j]==0){
                            map[i*MAPSIZE+j]=map[i*MAPSIZE+z];
                            map[i*MAPSIZE+z]=0;
                            j--;
                            merge=true;
                        }else if(map[i*MAPSIZE+j]==map[i*MAPSIZE+z]){
                            map[i*MAPSIZE+j]*=2;
                            score+=map[i*MAPSIZE+j];
                            map[i*MAPSIZE+z]=0;
                            merge=true;
                        }
                        break;
                    }
                }
            }
        }
        if(merge){
            for(int i=0;i<isfirstAppear.length;i++)isfirstAppear[i]=false;
            addRanrom();
            isEnd();
        }
    }

    @Override
    public void moveright() {
        boolean merge=false;
        for(int i=0;i<4;i++){
            for(int j=3;j>0;j--){
                for(int z=j-1;z>=0;z--){
                    if(map[i*MAPSIZE+z]>0){
                        if(map[i*MAPSIZE+j]==0){
                            map[i*MAPSIZE+j]=map[i*MAPSIZE+z];
                            map[i*MAPSIZE+z]=0;
                            j++;
                            merge=true;
                        }else if(map[i*MAPSIZE+j]==map[i*MAPSIZE+z]){
                            map[i*MAPSIZE+j]*=2;
                            map[i*MAPSIZE+z]=0;
                            score+=map[i*MAPSIZE+j];
                            merge=true;
                        }
                        break;
                    }
                }
            }
        }
        if(merge){
            for(int i=0;i<isfirstAppear.length;i++)isfirstAppear[i]=false;
            addRanrom();
            isEnd();
        }
    }

    @Override
    public void moveup() {
        boolean merge=false;
        for(int j=0;j<4;j++){
            for(int i=0;i<4;i++){
                for(int z=i+1;z<4;z++){
                    if(map[z*MAPSIZE+j]>0){
                        if(map[i*MAPSIZE+j]==0){
                            map[i*MAPSIZE+j]=map[z*MAPSIZE+j];
                            map[z*MAPSIZE+j]=0;
                            i--;
                            merge=true;
                        }else if(map[i*MAPSIZE+j]==map[z*MAPSIZE+j]){
                            map[i*MAPSIZE+j]*=2;
                            score+=map[i*MAPSIZE+j];
                            map[z*MAPSIZE+j]=0;
                            merge=true;
                        }
                        break;
                    }
                }
            }
        }
        if(merge){
            for(int i=0;i<isfirstAppear.length;i++)isfirstAppear[i]=false;
            addRanrom();
            isEnd();
        }
    }

    @Override
    public void movedown() {
        boolean merge=false;
        for(int j=0;j<4;j++){
            for(int i=3;i>0;i--){
                for(int z=i-1;z>=0;z--){
                    if(map[z*MAPSIZE+j]>0){
                        if(map[i*MAPSIZE+j]==0){
                            map[i*MAPSIZE+j]=map[z*MAPSIZE+j];
                            map[z*MAPSIZE+j]=0;
                            i++;
                            merge=true;
                        }else if(map[i*MAPSIZE+j]==map[z*MAPSIZE+j]){
                            map[i*MAPSIZE+j]*=2;
                            score+=map[i*MAPSIZE+j];
                            map[z*MAPSIZE+j]=0;
                            merge=true;
                        }
                        break;
                    }
                }
            }
        }
        if(merge){
            for(int i=0;i<isfirstAppear.length;i++)isfirstAppear[i]=false;
            addRanrom();
            isEnd();
        }
    }

    @Override
    public void addRanrom() {
        Random rand=new Random();
        int x=rand.nextInt(4);
        int y=rand.nextInt(4);
        do{
            x=rand.nextInt(4);
            y=rand.nextInt(4);
        }while(map[x*MAPSIZE+y]!=0);
        isfirstAppear[x*MAPSIZE+y]=true;
        map[x*MAPSIZE+y]=Math.random()>0.1?2:4;
    }

    @Override
    public void isEnd() {
        int state=this.GAME_OVER;
        for(int i=0;i<4;i++){
            for(int j=0;j<4;j++){
                if(map[i*MAPSIZE+j]==2048){
                    state=GAME_WIN;
                    return;
                }else if(map[i*MAPSIZE+j]==0||(i>0&&map[i*MAPSIZE+j]==map[(i-1)*MAPSIZE+j])||(i<3&&map[i*MAPSIZE+j]==map[(i+1)*MAPSIZE+j])||(j>0&&map[i*MAPSIZE+j]==map[i*MAPSIZE+(j-1)])||(j<3&&map[i*MAPSIZE+j]==map[i*MAPSIZE+(j+1)])){
                    state=this.GAME_CONTINUE;
                    return;
                }
            }
        }
        if(state==GAME_OVER){
            UtilsKt.showDialog(context, "遊戲結束", "", new Callback() {
                @Override
                public void onConfirm(@NotNull DialogInterface dialog) {
                    ((Activity)context).finish();
                }

                @Override
                public void onCancel(@NotNull DialogInterface dialog) {

                }
            });
        }else if(state==GAME_WIN){
            UtilsKt.showDialog(context, "遊戲勝利", "", new Callback() {
                @Override
                public void onConfirm(@NotNull DialogInterface dialog) {
                    ((Activity)context).finish();
                }

                @Override
                public void onCancel(@NotNull DialogInterface dialog) {

                }
            });
        }
    }
    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }
    void Gesture(int c){
        if(c==1) moveleft();		//getKeyCode()是表示按鍵按下的序号,KeyEvent.VK_UP表示up(下)鍵的序号
        if(c==2) moveright();
        if(c==3) moveup();
        if(c==4) movedown();
    }
}
           

事實上,上面的類完全可以通過scanner以控制台的形式跑起來

上篇總結

在本篇,我們主要關注遊戲的邏輯實作,但是麼有界面的遊戲一定是假遊戲,下一篇将結合用到的安卓開發知識介紹如何優雅的畫界面(霧)