Android-2048

来源:互联网 发布:qq邮箱stmp服务器端口 编辑:程序博客网 时间:2024/06/05 19:39

2048是20岁的Gabriele Cirulli开发的一款数字游戏,初衷就是觉得好玩,在将其开源版本放到Github上后,意外走红。这款游戏的玩法很简单,每次可以选择上下左右滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢,系统也会在空白的地方乱数出现一个数字方块,相同数字的方块在靠拢、相撞时会相加,不断的叠加最终拼凑出2048这个数字就算成功。

最初玩这个游戏的时候,觉得逻辑简单但是很吸引人,经过几次通关之后,转而对它的实现逻辑比较感兴趣,有了想自己也写一个demo的冲动,当时用的API-19如今已经更新到API-25,时间飞快,有点小感慨,下面进入正题上代码。

一、建好布局文件
布局比较简单,显示得分,游戏操作布局通过代码动态实现

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/container"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context="com.dw.game2048.MainActivity"    tools:ignore="MergeRootFrame" >    <LinearLayout        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:orientation="horizontal" >        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="@string/score" />        <TextView            android:id="@+id/tvScore"            android:layout_width="wrap_content"            android:layout_height="wrap_content" />    </LinearLayout>    <com.dw.game2048.GameView        android:layout_width="fill_parent"        android:layout_height="0dp"        android:layout_weight="1"        android:id="@+id/gameView" >    </com.dw.game2048.GameView></LinearLayout>

二、实现功能模块

1.主界面

package com.dw.game2048;import android.app.Activity;import android.os.Bundle;import android.view.Menu;import android.widget.TextView;public class MainActivity extends Activity {    private int score = 0;    private TextView tvScore;    private static MainActivity mainActivity = null;    public static MainActivity getMainActivity() {        return mainActivity;    }    public MainActivity() {        mainActivity = this;    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        tvScore = (TextView) findViewById(R.id.tvScore);    }    @Override    public boolean onCreateOptionsMenu(Menu menu) {        // Inflate the menu; this adds items to the action bar if it is present.        getMenuInflater().inflate(R.menu.main, menu);        return true;    }    public void clearScore(){        score = 0;        showScore();    }    public void showScore(){        tvScore.setText(score+"");    }    public void addScore(int s){        score+=s;        showScore();    }   }

2.卡片类的实现

package com.dw.game2048;import android.content.Context;import android.view.Gravity;import android.widget.FrameLayout;import android.widget.TextView;public class Card extends FrameLayout {    private int num = 0;    private TextView label;    public Card(Context context) {        super(context);         label = new TextView(getContext());        label.setTextSize(32);        label.setBackgroundColor(0x33ffffff);        label.setGravity(Gravity.CENTER);        LayoutParams lp = new LayoutParams(-1, -1);        lp.setMargins(10, 10, 0, 0);        addView(label, lp);        setNum(0);    }    public int getNum() {        return num;    }    public void setNum(int num) {        this.num = num;         if (num<=0) {            label.setText("");        }else{            label.setText(num+"");        }    }    public boolean equals(Card o) {        return getNum()==o.getNum();    }}

3.游戏逻辑的实现

package com.dw.game2048;import java.util.ArrayList;import java.util.List;import android.app.AlertDialog;import android.content.Context;import android.content.DialogInterface;import android.graphics.Point;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.widget.GridLayout;public class GameView extends GridLayout {    private Card[][] cardsMap = new Card[4][4];    private List<Point> emptyPoints = new ArrayList<Point>();    public GameView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        initGameView();    }    public GameView(Context context) {        super(context);        initGameView();    }    public GameView(Context context, AttributeSet attrs) {        super(context, attrs);        initGameView();    }    private void initGameView(){        setColumnCount(4);        setBackgroundColor(0xffbbada0);         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:                    startX = event.getX();                    startY = event.getY();                    break;                case MotionEvent.ACTION_UP:                    offsetX = event.getX()-startX;                    offsetY = event.getY()-startY;                    if (Math.abs(offsetX)>Math.abs(offsetY)) {                        if (offsetX<-5) {                            swipeLeft();                        }else if (offsetX>5) {                            swipeRight();                        }                    }else{                        if (offsetY<-5) {                            swipeUp();                        }else if (offsetY>5) {                            swipeDown();                        }                    }                    break;                }                return true;            }        });    }    @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;        addCards(cardWidth,cardWidth);        startGame();    }    private void addCards(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);                cardsMap[x][y] = c;            }        }    }    private void startGame(){        MainActivity.getMainActivity().clearScore();        for (int y = 0; y < 4; y++) {            for (int x = 0; x < 4; x++) {                cardsMap[x][y].setNum(0);            }        }        addRandomNum();        addRandomNum();    }    private void addRandomNum(){        emptyPoints.clear();        for (int y = 0; y < 4; y++) {            for (int x = 0; x < 4; x++) {                if (cardsMap[x][y].getNum()<=0) {                    emptyPoints.add(new Point(x, y));                }            }        }        Point p = emptyPoints.remove((int)(Math.random()*emptyPoints.size()));        cardsMap[p.x][p.y].setNum(Math.random()>0.1?2:4);    }    private void swipeLeft(){        boolean merge = false;        for (int y = 0; y < 4; y++) {            for (int x = 0; x < 4; x++) {                for (int x1 = x+1; x1 < 4; x1++) {                    if (cardsMap[x1][y].getNum()>0) {                        if (cardsMap[x][y].getNum()<=0) {                            cardsMap[x][y].setNum(cardsMap[x1][y].getNum());                            cardsMap[x1][y].setNum(0);                            x--;                            merge = true;                        }else if (cardsMap[x][y].equals(cardsMap[x1][y])) {                            cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);                            cardsMap[x1][y].setNum(0);                            MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());                            merge = true;                        }                        break;                    }                }            }        }        if (merge) {            addRandomNum();            checkComplete();        }    }    private void swipeRight(){        boolean merge = false;        for (int y = 0; y < 4; y++) {            for (int x = 3; x >=0; x--) {                for (int x1 = x-1; x1 >=0; x1--) {                    if (cardsMap[x1][y].getNum()>0) {                        if (cardsMap[x][y].getNum()<=0) {                            cardsMap[x][y].setNum(cardsMap[x1][y].getNum());                            cardsMap[x1][y].setNum(0);                            x++;                            merge = true;                        }else if (cardsMap[x][y].equals(cardsMap[x1][y])) {                            cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);                            cardsMap[x1][y].setNum(0);                            MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());                            merge = true;                        }                        break;                    }                }            }        }        if (merge) {            addRandomNum();            checkComplete();        }    }    private void swipeUp(){        boolean merge = false;        for (int x = 0; x < 4; x++) {            for (int y = 0; y < 4; y++) {                for (int y1 = y+1; y1 < 4; y1++) {                    if (cardsMap[x][y1].getNum()>0) {                        if (cardsMap[x][y].getNum()<=0) {                            cardsMap[x][y].setNum(cardsMap[x][y1].getNum());                            cardsMap[x][y1].setNum(0);                            y--;                            merge = true;                        }else if (cardsMap[x][y].equals(cardsMap[x][y1])) {                            cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);                            cardsMap[x][y1].setNum(0);                            MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());                            merge = true;                        }                        break;                    }                }            }        }        if (merge) {            addRandomNum();            checkComplete();        }    }    private void swipeDown(){        boolean merge = false;        for (int x = 0; x < 4; x++) {            for (int y = 3; y >=0; y--) {                for (int y1 = y-1; y1 >=0; y1--) {                    if (cardsMap[x][y1].getNum()>0) {                        if (cardsMap[x][y].getNum()<=0) {                            cardsMap[x][y].setNum(cardsMap[x][y1].getNum());                            cardsMap[x][y1].setNum(0);                            y++;                            merge = true;                        }else if (cardsMap[x][y].equals(cardsMap[x][y1])) {                            cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);                            cardsMap[x][y1].setNum(0);                            MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());                            merge = true;                        }                        break;                    }                }            }        }        if (merge) {            addRandomNum();            checkComplete();        }    }    private void checkComplete(){        boolean complete = true;        ALL:        for (int y = 0; y < 4; y++) {            for (int x = 0; x < 4; x++) {                if (cardsMap[x][y].getNum()==0||                        (x>0&&cardsMap[x][y].equals(cardsMap[x-1][y]))||                        (x<3&&cardsMap[x][y].equals(cardsMap[x+1][y]))||                        (y>0&&cardsMap[x][y].equals(cardsMap[x][y-1]))||                        (y<3&&cardsMap[x][y].equals(cardsMap[x][y+1]))) {                    complete = false;                    break ALL;                }            }        }        if (complete) {            new AlertDialog.Builder(getContext()).setTitle("提示").setMessage("Game Over").            setPositiveButton("再来一次", new DialogInterface.OnClickListener() {                @Override                public void onClick(DialogInterface dialog, int which) {                    startGame();                }            }).show();        }    }}

今天先到这,睡个午觉。

0 0