Android 之 2048 的遊戲邏輯分析,android2048

來源:互聯網
上載者:User

Android 之 2048 的遊戲邏輯分析,android2048

 

繼續學習了極客學院的實戰路徑課程,講到了2048遊戲的編寫過程,我在這裡作個總結分享給大家(結果會附原始碼和我改寫後的代碼):

這裡主要包括兩個方面:1.2048介面的繪製   2.2048演算法邏輯的實現   3.添加隨機數  4.判斷遊戲結束

先看(真機上類比圖):

 

1.介面的繪製

介面的繪製相對還是比較簡單的。先建立一個card卡片類,這個類主要是描述在中那16個小方塊

/* * 這個類主要用來初始化2048遊戲中的方塊 */public class Card extends FrameLayout{    private TextView lable;    public Card(Context context) {        super(context);        lable = new TextView(getContext());        lable.setTextSize(32);        lable.setGravity(Gravity.CENTER);        lable.setBackgroundColor(0X30FFFFFF);   //30表示透明度,透明度範圍是00-ff,後六位是顏色值                //下面設定了Layout_wight和Layout_height分別為match_parent(-1代表match_parent,-2代表wrap_content)        LayoutParams lp = new LayoutParams(-1,-1);        lp.setMargins(10, 10, 10, 10);     //設定card的間距        addView(lable,lp);        setNum(0);    }    int num = 0;    public int getNum(){        return num;    }    public void setNum(int num) {        this.num = num;        //當cardMap[][]<=0時,設為""        if (num<=0) {            lable.setText("");        }else {            lable.setText(num+"");        }    }    public boolean equals(Card o) {        return getNum()==o.getNum();    }}

 

然後建立一個GameView的主類,使它繼承GirdLayout,複寫其中的方法。再在此之前需要更改一下main_activity布局檔案,包括計分的一個textView,和在外面實現的布局。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context="com.example.game1024.MainActivity" >    <LinearLayout         android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="vertical">                <TextView             android:layout_width="wrap_content"            android:layout_height="match_parent"            android:layout_gravity="center_vertical"            android:textSize="20sp"            android:text="score:"/>        <TextView             android:id="@+id/cvScore"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:textSize="20sp"             />    </LinearLayout>        <com.example.game1024.GameView        android:background="#00ff00"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1">        </com.example.game1024.GameView></LinearLayout>

 

public class GameView extends GridLayout{    public GameView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initGame();    }    public GameView(Context context, AttributeSet attrs) {        super(context, attrs);        initGame();    }    public GameView(Context context) {        super(context);        initGame();    }        public void initGame(){        setColumnCount(4);  //設定規定行數為四行        setBackgroundColor(0XffF4A460);                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:                    //取得點擊時的初始座標                    System.out.println("00000");                    startX = event.getX();                    startY = event.getY();                    break;                case MotionEvent.ACTION_UP:                    //求得各方向的位移量                    System.out.println("0--0");                    offsetX = event.getX() - startX;                    offsetY = event.getY() - startY;                    /*                     * 比較在x軸和y軸的位移量,可以判斷為上下滑動,還是左右滑動                     * 接著判斷位移量的正負,來判斷是具體向哪個方向的滑動                     * 下面我寫移動的順序為:向左,右,上,下                     */                    if (Math.abs(offsetX)>Math.abs(offsetY)) {                        //當移動的距離大於5dp時才看作移動                        if (offsetX<-5) {                            swipeLeft();                        }else if (offsetX>5) {                            swipeRight();                        }                    }else if (Math.abs(offsetX)<Math.abs(offsetY)) {                        if (offsetY<-5) {                            swipeUp();                        }else if (offsetY>5) {                            swipeDown();                        }                    }                    break;                default:                    break;                }                return true;            }        });    }    /*     * (non-Javadoc)     * @see android.view.View#onSizeChanged(int, int, int, int)     * 當螢幕的寬高改變時,卡片所佔的寬高會隨之改變     */    @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;        addCard(cardWidth, cardWidth);                startGame();    }    //建立一個數組用於儲存各個卡片的num    private Card cardMap[][] =  new Card[4][4];    /*     * 添加card卡片的方法     */    private void addCard(int cardwidth, int cardheight){        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);                cardMap[x][y]=c;            }        }    }

2.遊戲邏輯的演算法

這個注釋比較清楚,大家看注釋吧 ,if(judge)是後面要判斷遊戲結束時用的

/*     * 移動方面的演算法     */    private void swipeLeft(){        boolean judge = false;        for (int y = 0; y < 4; y++) {            for (int x = 0; x < 4; x++) {                                for (int x1 = x+1; x1 < 4; x1++) {             //先判斷在當前點的右邊是否存在num大於零的點,如果是,進行下一步,否的話繼續迴圈
              //判斷當前點是否為空白(小於等於零相當於空,在card類中已經設定為了不顯示),為空白:將右面的點賦予當前點,同時自身置零。不為空白的話判斷當前點是否和               
              //右面的點相等,相等將當前點的num乘2,並將右面的點置零
  if (cardMap[x1][y].getNum()>0) { if (cardMap[x][y].getNum()<=0) { cardMap[x][y].setNum(cardMap[x1][y].getNum()); cardMap[x1][y].setNum(0); /* * 假如在第1個位置有一個數,它將移動到第0個位置,此時繼續迴圈,如果第2個位置也有數, * 此時因為第0個位置已經存在了數值,所以第2個位置的數不會移動到第一個空白位置,而是保持不變 * 因此需要將x減1,在比較一遍 */ x--; judge = true; }else if (cardMap[x][y].getNum()==cardMap[x1][y].getNum()) { cardMap[x][y].setNum(cardMap[x][y].getNum()*2); cardMap[x1][y].setNum(0); MainActivity.getMainActivity().addScore(cardMap[x][y].getNum()); judge = true; } break; } } } } if (judge) { checkGame(); addRandom(); } } private void swipeRight(){ boolean judge = false; for (int y = 0; y < 4; y++) { for (int x = 3; x >= 0; x--) { for (int x1 = x-1; x1 >=0; x1--) { if (cardMap[x1][y].getNum()>0) { if (cardMap[x][y].getNum()<=0) { cardMap[x][y].setNum(cardMap[x1][y].getNum()); cardMap[x1][y].setNum(0); x++; judge = true; }else if (cardMap[x][y].getNum()==cardMap[x1][y].getNum()) { cardMap[x][y].setNum(cardMap[x][y].getNum()*2); cardMap[x1][y].setNum(0); MainActivity.getMainActivity().addScore(cardMap[x][y].getNum()); judge = true; } break; } } } } if (judge) { checkGame(); addRandom(); } } private void swipeUp(){ boolean judge = false; for (int x = 0; x < 4; x++) { for (int y = 0; y <4; y++) { for (int y1 = y+1 ; y1 <4 ; y1++) { if (cardMap[x][y1].getNum()>0) { if (cardMap[x][y].getNum()<=0) { cardMap[x][y].setNum(cardMap[x][y1].getNum()); cardMap[x][y1].setNum(0); y--; judge = true; }else if (cardMap[x][y].getNum()==cardMap[x][y1].getNum()) { cardMap[x][y].setNum(cardMap[x][y].getNum()*2); cardMap[x][y1].setNum(0); MainActivity.getMainActivity().addScore(cardMap[x][y].getNum()); judge = true; } break; } } } } if (judge) { checkGame(); addRandom(); } } private void swipeDown(){ boolean judge = false; for (int x = 0; x < 4; x++) { for (int y = 3; y >=0; y--) { for (int y1 = y-1 ; y1 >=0; y1--) { if (cardMap[x][y1].getNum()>0) { if (cardMap[x][y].getNum()<=0) { cardMap[x][y].setNum(cardMap[x][y1].getNum()); cardMap[x][y1].setNum(0); y++; judge = true; }else if (cardMap[x][y].getNum()==cardMap[x][y1].getNum()) { cardMap[x][y].setNum(cardMap[x][y].getNum()*2); cardMap[x][y1].setNum(0); MainActivity.getMainActivity().addScore(cardMap[x][y].getNum()); judge = true; } break; } } } } if (judge) { checkGame(); addRandom(); } }

3.添加隨機出現的點:

同樣在GameView中添加方法,startGame()在onSizeChanged()方法中調用

/*     * 遊戲開始的初始化方法     */    private void startGame(){        MainActivity.getMainActivity().clearScore();        for (int y = 0; y < 4; y++) {            for (int x = 0; x < 4; x++) {                cardMap[x][y].setNum(0);            }        }            addRandom();        addRandom();    }        private List<Point> emptyPoint =new  ArrayList<Point>();    //添加隨機數的方法    private void addRandom(){        emptyPoint.clear();        for (int y = 0; y < 4; y++) {            for (int x = 0; x < 4; x++) {                //將cardMap中小於0的點放在emptyPoint中                if (cardMap[x][y].getNum()<=0) {                    emptyPoint.add(new Point(x, y));                }            }        }        //隨機移除emptyPoint中的一個單元        Point p = emptyPoint.remove((int)(Math.random()*emptyPoint.size()));        cardMap[p.x][p.y].setNum(Math.random()>0.1?2:4);    }

4.判斷遊戲結束

/*     * 結束遊戲方法     * 當存在點和旁邊的數相等時,遊戲就不會提示已經結束     */        private void checkGame(){            boolean check = true;            ALL:            for (int y = 0; y < 4; y++) {                for (int x = 0; x < 4; x++) {                    if (cardMap[x][y].getNum()==0||                            x>0&&cardMap[x][y].equals(cardMap[x-1][y])||                            x<3&&cardMap[x][y].equals(cardMap[x+1][y])||                            y>0&&cardMap[x][y].equals(cardMap[x][y-1])||                            y<3&&cardMap[x][y].equals(cardMap[x][y+1])) {                        check = false;                        break ALL;                    }                }            }                         // 提示遊戲失敗            if (check) {                new AlertDialog.Builder(getContext()).setTitle("提示").setMessage("遊戲失敗").setPositiveButton("再來一次", new DialogInterface.OnClickListener() {                                        @Override                    public void onClick(DialogInterface dialog, int which) {                        startGame();                    }                }).show();            }        }

 

我改進的2048:

1.增加了最高分顯示

2.增加了重新開始遊戲按鈕

3.增加了顏色變化

Game1024原版:http://pan.baidu.com/s/1sjpCdIl

Game2048改進版地址:http://pan.baidu.com/s/1o6qyfJc

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.