android 2048的简单实现

转载请注明出处:http://blog.csdn.net/sw950729/article/details/52211315
本文出自:马云飞的博客
前天去osc原创会溜了一圈,结果因为G20找个住的地方都难- - !然后各种悲剧就发生了。昨天下午回家睡了一觉,原本晚上更新的,结果发生电脑充电器扔公司。什么鬼,fuck++,有史以来最惨的一个周末。(说好的一周最少一更的~~~~)好了话不多说,进入正题。
关于自定义view我们前面讲到了五子棋。这次讲个简单的,2048的实现。当然,如果你看懂了前面的自定义,今天的都不是问题。
首先需要自定义Gridlayout来实现自定义的几个方法,我们来看看初始化,设置每行最大数量以及颜色和手势滑动,代码如下:

private void initalgame() {
        setColumnCount(4);// 设置每行最多4个
        setBackgroundColor(0xffbbada0);
        setOnTouchListener(new View.OnTouchListener() {

            private float startX, startY, changeX, changeY;

            public boolean onTouch(View v, MotionEvent event) {

                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    startX = event.getX();// 起始的X坐标
                    startY = event.getY();// 起始的Y坐标
                    break;
                case MotionEvent.ACTION_UP:
                    changeX = event.getX() - startX;// 改变的X坐标=现在的-起始的
                    changeY = event.getY() - startY;// 改变的Y坐标=现在的-起始的

                    // 若X的绝对值>Y的绝对值,则是左右移动,否则为上下移动,左上角坐标为(0,0)
                    if (Math.abs(changeX) > Math.abs(changeY)) {
                        if (changeX < -5) {
                            Left();
                        } else if (changeX > 5) {
                            Right();
                        }
                    } else {
                        if (changeY < -5) {
                            Up();
                        } else if (changeY > 5) {
                            Down();
                        }
                    }

                    break;
                }
                return true;
            }

        });

    }

我们需要一个卡片类来给Gridlayout的item设置内容和背景色:


public class Card extends FrameLayout {

    private TextView label;
    private int num = 0;

    public Card(Context context) {
        super(context);
        label = new TextView(getContext());// 新建个textview
        label.setTextSize(32);// 设置字体大小
        label.setBackgroundColor(0x338B8B00);// 背景色
        label.setTextColor(0x330D0D0D);// 设置字体颜色
        label.setGravity(Gravity.CENTER);// 设置字体居中

        // LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
        // LayoutParams.MATCH_PARENT);// 铺满屏幕
        LayoutParams lp = new LayoutParams(-1, -1);
        lp.setMargins(10, 10, 0, 0);// 间距10像素
        addView(label, lp);

        setNum(0);
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
        label.setBackgroundColor(getBackColor(num));// 背景色
        // 如果值为0,就不设置内容
        if (num <= 0) {
            label.setText("");
        } else {
            label.setText(num + "");
        }
    }

    // 设置背景色
    private int defaultBackColor = 0x338B8B00;

    private int getBackColor(int num) {

        int bgcolor = defaultBackColor;
        switch (num) {
        case 0:
            bgcolor = 0xffCCC0B3;
            break;
        case 2:
            bgcolor = 0xffEEE4DA;
            break;
        case 4:
            bgcolor = 0xffEDE0C8;
            break;
        case 8:
            bgcolor = 0xffF2B179;// #F2B179
            break;
        case 16:
            bgcolor = 0xffF49563;
            break;
        case 32:
            bgcolor = 0xffF5794D;
            break;
        case 64:
            bgcolor = 0xffF55D37;
            break;
        case 128:
            bgcolor = 0xffEEE863;
            break;
        case 256:
            bgcolor = 0xffEDB04D;
            break;
        case 512:
            bgcolor = 0xffECB04D;
            break;
        case 1024:
            bgcolor = 0xffEB9437;
            break;
        case 2048:
            bgcolor = 0xffEA7821;
            break;
        default:
            bgcolor = 0xffEA7821;
            break;
        }
        return bgcolor;
    }

    // 判断2个数是否相等
    public boolean equals(Card c) {
        return getNum() == c.getNum();
    }

}

同时在自定义layout,我们需要计算出每个卡片的宽高:


    private Card[][] cardsMap = new Card[4][4];

    // 计算卡片的宽高
    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);
        start();// 开始游戏
    }

开始游戏时,我们随机添加2个卡片。卡片内容为2或4,比例为9:1。

// 添加卡片
    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);
                cardsMap[x][y] = c;

            }
        }
    }
// 开始游戏
    private void start() {
        MainActivity.getMainActivity().clear();
        for (int y = 0; y < 4; y++) {
            for (int x = 0; x < 4; x++) {
                cardsMap[x][y].setNum(0);
            }
        }
        // 添加随机数
        addRandomNum();
        addRandomNum();
    }

    // 添加随机数
    public void addRandomNum() {

        // 清空point
        point.clear();

        for (int y = 0; y < 4; y++) {
            for (int x = 0; x < 4; x++) {
                // 如果这个位置没有值。添加
                if (cardsMap[x][y].getNum() <= 0) {
                    point.add(new Point(x, y));
                }
            }
        }
        // 随机移除一个点
        Point p = point.remove((int) (Math.random() * point.size()));
        cardsMap[p.x][p.y].setNum(Math.random() > 0.1 ? 2 : 4);
    }

剩下的就是判断滑动方向来进行数的位移和相加了:


    private void Left() {

        boolean flag = 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--;
                            flag = 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().add(
                                    cardsMap[x][y].getNum());
                            flag = true;
                        }
                        break;
                    }
                }
            }
        }
        if (flag) {
            addRandomNum();
            IsFinish();
        }
    }

    private void Right() {

        Boolean flag = 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++;
                            flag = 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().add(
                                    cardsMap[x][y].getNum());
                            flag = true;
                        }
                        break;
                    }
                }
            }
        }
        if (flag) {
            addRandomNum();
            IsFinish();
        }
    }

    private void Up() {
        boolean flag = 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--;
                            flag = 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().add(
                                    cardsMap[x][y].getNum());
                            flag = true;
                        }
                        break;
                    }
                }
            }
        }
        if (flag) {
            addRandomNum();
            IsFinish();
        }
    }

    private void Down() {
        boolean flag = 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++;
                            flag = 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().add(
                                    cardsMap[x][y].getNum());
                            flag = true;
                        }
                        break;
                    }
                }
            }
        }

        if (flag) {
            addRandomNum();
            IsFinish();
        }
    }

最后我们每次滑动结束都是需要判断游戏是否结束,判断条件则是列表被铺满而且无法进行相加:

private void IsFinish() {

        boolean finish = 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]))) {

                    finish = false;
                    break ALL;
                }
            }
        }

        if (finish) {
            new AlertDialog.Builder(getContext())
                    .setTitle("游戏结束!")
                    .setMessage("您的得分为:" + MainActivity.score)
                    .setPositiveButton("重来",
                            new DialogInterface.OnClickListener() {

                                public void onClick(DialogInterface dialog,
                                        int which) {
                                    start();
                                }
                            })
                    .setNegativeButton("退出",
                            new DialogInterface.OnClickListener() {

                                public void onClick(DialogInterface dialog,
                                        int which) {
                                    MainActivity.getMainActivity().finish();
                                }
                            }).show();
        }

    }

而我们需要一个类来保存我们的最高分,这里用了一个最简单的数据存储,Shareperference。代码很简单:


public class BestScode {

    private SharedPreferences sp;
    public BestScode(Context context){
        sp = context.getSharedPreferences("bestscode", context.MODE_PRIVATE);
    }
    public int getBestScode(){
        int bestscode = sp.getInt("bestscode", 0);
        return bestscode;
    }
    public void setBestScode(int bestScode){
        Editor editor = sp.edit();
        editor.putInt("bestscode", bestScode);
        editor.commit();
    }
}

剩下的就是主activity了:


    private TextView text;
    public static int score;
    private static MainActivity mainactivity = null;
    private TextView tv_bestScore;
    private int current_score = 0;
    private int currentBestScore;

    public MainActivity() {
        mainactivity = this;
    }

    public static MainActivity getMainActivity() {
        return mainactivity;
    }

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        inital();
    }

    public void inital() {
        text = (TextView) findViewById(R.id.text);
        tv_bestScore = (TextView) findViewById(R.id.tv_bestScore);
        BestScode bs = new BestScode(this);
        currentBestScore = bs.getBestScode();
        tv_bestScore.setText("" + currentBestScore);
        // WindowManager wm = (WindowManager) this
        // .getSystemService(Context.WINDOW_SERVICE);

        // int width = wm.getDefaultDisplay().getWidth();
        // int height = wm.getDefaultDisplay().getHeight();
        // iv=(ImageView) findViewById(R.id.image);
        // 生成图片
        // iv.setImageResource(R.drawable.myname);
        // iv.setScaleType(ImageView.ScaleType.FIT_XY);
        // iv.setAdjustViewBounds(true);
        // iv.setMaxHeight(height);// 屏幕高度
        // iv.setMaxWidth(width);// 屏幕宽度
    }

    // 清空分数
    public void clear() {
        score = 0;
        show();
    }

    // 显示分数
    public void show() {
        text.setText("" + score);

    }

    // 添加分数
    public void add(int s) {
        score += s;
        show();
        if (score > currentBestScore) {
            currentBestScore = score;
            BestScode bs = new BestScode(this);
            bs.setBestScode(currentBestScore);
            tv_bestScore.setText("" + currentBestScore);
        }

    }

    /**
     * 菜单、返回键响应
     */
    private long exitTime = 0;

    public boolean onKeyDown(int keyCode, KeyEvent event) {

        if (keyCode == KeyEvent.KEYCODE_BACK
                && event.getAction() == KeyEvent.ACTION_DOWN) {
            if ((System.currentTimeMillis() - exitTime) > 2000) {
                Toast.makeText(this, "再按一次退出程序", 1000).show();
                exitTime = System.currentTimeMillis();
            } else {
                finish();
                System.exit(0);
            }
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

最后附上我的layout:

<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:background="#bbada0"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/ll_best"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_marginRight="10dp"
        android:orientation="vertical" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="最高纪录:"
            android:textColor="#FF0000"
            android:textSize="18sp" />

        <TextView
            android:id="@+id/tv_bestScore"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="0"
            android:textColor="#FF0000"
            android:textSize="20sp" />
    </LinearLayout>

    <com.example.game2048.GameView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="4" >
    </com.example.game2048.GameView>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="得分:"
            android:textColor="#98F5FF"
            android:textSize="50sp" />

        <TextView
            android:id="@+id/text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:textColor="#98F5FF"
            android:textSize="50sp" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="作者:\n我就是马云飞"
            android:textColor="#90EE90"
            android:textSize="38sp" />


    </LinearLayout>

</LinearLayout>

好了。有兴趣可以把这个demo进行延伸,写了等级划分啊,自定义背景啊~~~。
我的android交流群:232748032

发布了89 篇原创文章 · 获赞 155 · 访问量 29万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览