【Android 2d 游戏开发(2)】——2048

实现效果 :

开始界面
游戏界面
结束界面

代码结构:

这里写图片描述

完整代码:

MainActivity:

package com.next.next2048;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        //全屏
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(new GameView(this));
    }
}

Tile:
package com.next.next2048;

/**
* Created by Next on 2016/3/17 0017.
*/
public class Tile {
private int number;
private int x,y;
public Tile(int x,int y,int number){
this.x = x;
this.y = y;
this.number = number;
}

public int getY() {
    return y;
}

public void setY(int y) {
    this.y = y;
}

public int getX() {
    return x;
}

public void setX(int x) {
    this.x = x;
}

public int getNumber() {
    return number;
}

public void setNumber(int number) {
    this.number = number;
}

}
GameView:

package com.next.next2048;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;
import java.util.Random;

/**
 * Created by Next on 2016/3/17 0017.
 */
public class GameView extends View {
    enum GameState {
        Menu,
        Playing,
        Over
    }

    GameState gameState = GameState.Menu;
    public static final int MAX_X = 4;
    public static final int MAX_Y = 4;
    int tWidth;//tile宽度
    int scrW;//屏幕宽
    int scrH;//屏幕高
    int offsetX;//偏移x
    int offsetY;//偏移y,用于调整游戏区域在屏幕中的位置
    Paint paint;
    Tile[][] tiles;//Tile集合
    Random random;
    ArrayList<Tile> zeroList;
    float downX, downY, upX, upY;

    public GameView(Context context) {
        super(context);
        scrW = ((MainActivity) context).getWindowManager().getDefaultDisplay().getWidth();
        scrH = ((MainActivity) context).getWindowManager().getDefaultDisplay().getHeight();
        offsetX = 30;
        offsetY = (scrH - scrW) / 2;//使棋盘位于屏幕中央
        tWidth = (scrW - offsetX * 2) / MAX_X;
        paint = new Paint();
        tiles = new Tile[MAX_X][MAX_Y];
        setKeepScreenOn(true);//保持屏幕常亮
        random = new Random();
        zeroList = new ArrayList<Tile>();
    }

    private void newGame() {
        for (int x = 0; x < MAX_X; x++) {
            for (int y = 0; y < MAX_Y; y++) {
                tiles[x][y] = new Tile(x, y, 0);
            }
        }
        newTile();
        newTile();


    }

    private void newTile() {
        zeroList.removeAll(zeroList);
        for (int x = 0; x < MAX_X; x++) {
            for (int y = 0; y < MAX_Y; y++) {
                if (tiles[x][y].getNumber() == 0) {
                    zeroList.add(tiles[x][y]);
                }
            }
        }
        int size = zeroList.size();
        if (size > 0) {
            //出现4的概率是20%,出现2的概率是80%
            if (random.nextInt(5) == 0) {
                zeroList.get(random.nextInt(size)).setNumber(4);
            } else {
                zeroList.get(random.nextInt(size)).setNumber(2);
            }
        } else {
            return;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        switch (gameState) {
            case Menu:
                menuDraw(canvas);
                break;
            case Playing:
                playingDraw(canvas);
                break;
            case Over:
                overDraw(canvas);
                break;
            default:
                break;
        }
    }

    private void menuDraw(Canvas canvas) {
        canvas.drawColor(Color.WHITE);
        paint.setColor(Color.BLACK);
        paint.setTextAlign(Paint.Align.CENTER);
        paint.setTextSize(tWidth / 2);
        canvas.drawText("2048", scrW / 2, scrH / 4, paint);
        canvas.drawText("Touch me", scrW / 2, scrH / 2, paint);
    }

    private void playingDraw(Canvas canvas) {
        canvas.drawColor(Color.WHITE);
        //画主游戏区域
        paint.setColor(Color.BLACK);
        paint.setStrokeWidth(10);
        for (int x = 0; x < MAX_X + 1; x++) {
            canvas.drawLine(offsetX + x * tWidth, offsetY, offsetX + x * tWidth, offsetY + tWidth * MAX_Y, paint);
        }
        for (int y = 0; y < MAX_Y + 1; y++) {
            canvas.drawLine(offsetX, offsetY + y * tWidth, offsetX + MAX_X * tWidth, offsetY + y * tWidth, paint);
        }
        for (int x = 0; x < MAX_X; x++) {
            for (int y = 0; y < MAX_Y; y++) {
                if (tiles[x][y].getNumber() != 0) {
                    switch (tiles[x][y].getNumber()){
                        case 2:
                            paint.setColor(0xffff6666);
                            break;
                        case 4:
                            paint.setColor(0xffff9900);
                            break;
                        case 8:
                            paint.setColor(0xff99CC33);
                            break;
                        case 16:
                            paint.setColor(0xff33CC99);
                            break;
                        case 32:
                            paint.setColor(0xff666699);
                            break;
                        case 64:
                            paint.setColor(0xff339933);
                            break;
                        case 128:
                            paint.setColor(0xff0099CC);
                            break;
                        case 256:
                            paint.setColor(0xff660033);
                            break;
                        case 512:
                            paint.setColor(0xff006633);
                            break;
                        case 1024:
                            paint.setColor(0xff660099);
                            break;
                        case 2048:
                            paint.setColor(0xffff0033);
                            break;
                        case 4096:
                            paint.setColor(0xff333333);
                            break;
                        case 8192:
                            paint.setColor(0xff000000);
                            break;
                        default:
                            paint.setColor(0xff000000);
                            break;
                    }
                    canvas.drawText(tiles[x][y].getNumber() + "", offsetX + x * tWidth + tWidth / 2, offsetY + y * tWidth + tWidth * 3 / 4, paint);
                }
            }
        }
    }

    private void overDraw(Canvas canvas) {
        int max = 0;
        for (int x = 0; x < MAX_X; x++) {
            for (int y = 0; y < MAX_Y; y++) {
                if (tiles[x][y].getNumber() > max) {
                    max = tiles[x][y].getNumber();
                }
            }
        }
        canvas.drawColor(Color.WHITE);
        paint.setColor(Color.BLACK);
        paint.setTextAlign(Paint.Align.CENTER);
        paint.setTextSize(tWidth / 2);
        canvas.drawText("Top:" + max, scrW / 2, scrH / 4, paint);
        canvas.drawText("Try again", scrW / 2, scrH / 2, paint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (gameState) {
            case Menu:
                menuLogic(event);
                break;
            case Playing:
                playingLoic(event);
                break;
            case Over:
                overLogic(event);
                break;
        }
        return true;
    }

    private void menuLogic(MotionEvent event) {
        if (event.getX() > 0) {
            gameState = GameState.Playing;
            newGame();
            invalidate();
        }
    }

    private void playingLoic(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            downX = event.getX();
            downY = event.getY();
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            upX = event.getX();
            upY = event.getY();
            float moveX = upX - downX;
            float moveY = upY - downY;
            if (Math.abs(moveX) > Math.abs(moveY)) {
                if (moveX > 50) {
                    //右滑
                    //合并
                    boolean isMove = false;//判断是否有tile移动
                    for (int y = 0; y < MAX_Y; y++) {
                        for (int x = MAX_X - 1; x >= 0; x--) {
                            if (tiles[x][y].getNumber() == 0) {
                                continue;
                            }
                            for (int x0 = x - 1; x0 >= 0; x0--) {
                                if (tiles[x0][y].getNumber() == 0) {
                                    continue;
                                } else if (tiles[x][y].getNumber() == tiles[x0][y].getNumber()) {
                                    tiles[x][y].setNumber(tiles[x][y].getNumber() * 2);
                                    tiles[x0][y].setNumber(0);
                                    isMove = true;
                                    break;
                                } else {
                                    break;
                                }
                            }
                        }
                    }
                    //移动
                    for (int y = 0; y < MAX_Y; y++) {
                        for (int x = MAX_X - 1; x >= 0; x--) {
                            if (tiles[x][y].getNumber() != 0) {
                                continue;
                            }
                            for (int x0 = x - 1; x0 >= 0; x0--) {
                                if (tiles[x0][y].getNumber() == 0) {
                                    continue;
                                } else {
                                    tiles[x][y].setNumber(tiles[x0][y].getNumber());
                                    tiles[x0][y].setNumber(0);
                                    isMove = true;
                                    break;
                                }
                            }
                        }
                    }
                    //有tile移动才添加新的tile
                    if (isMove) {
                        newTile();
                        invalidate();
                        judgeOver();
                    }
                } else if (moveX < -50) {
                    //左滑
                    //合并
                    boolean isMove = false;
                    for (int y = 0; y < MAX_Y; y++) {
                        for (int x = 0; x < MAX_X; x++) {
                            if (tiles[x][y].getNumber() == 0) {
                                continue;
                            }
                            for (int x0 = x + 1; x0 < MAX_X; x0++) {
                                if (tiles[x0][y].getNumber() == 0) {
                                    continue;
                                } else if (tiles[x][y].getNumber() == tiles[x0][y].getNumber()) {
                                    tiles[x][y].setNumber(tiles[x][y].getNumber() * 2);
                                    tiles[x0][y].setNumber(0);
                                    isMove = true;
                                    break;
                                } else {
                                    break;
                                }
                            }
                        }
                    }
                    //移动
                    for (int y = 0; y < MAX_Y; y++) {
                        for (int x = 0; x < MAX_X; x++) {
                            if (tiles[x][y].getNumber() != 0) {
                                continue;
                            }
                            for (int x0 = x + 1; x0 < MAX_X; x0++) {
                                if (tiles[x0][y].getNumber() == 0) {
                                    continue;
                                } else {
                                    tiles[x][y].setNumber(tiles[x0][y].getNumber());
                                    tiles[x0][y].setNumber(0);
                                    isMove = true;
                                    break;
                                }
                            }
                        }
                    }
                    if (isMove) {
                        newTile();
                        invalidate();
                        judgeOver();
                    }
                }
            } else {
                if (moveY > 50) {
                    //下滑
                    //合并
                    boolean isMove = false;
                    for (int x = 0; x < MAX_X; x++) {
                        for (int y = MAX_Y - 1; y >= 0; y--) {
                            if (tiles[x][y].getNumber() == 0) {
                                continue;
                            }
                            for (int y0 = y - 1; y0 >= 0; y0--) {
                                if (tiles[x][y0].getNumber() == 0) {
                                    continue;
                                } else if (tiles[x][y].getNumber() == tiles[x][y0].getNumber()) {
                                    tiles[x][y].setNumber(tiles[x][y].getNumber() * 2);
                                    tiles[x][y0].setNumber(0);
                                    isMove = true;
                                    break;
                                } else {
                                    break;
                                }
                            }
                        }
                    }
                    //移动
                    for (int x = 0; x < MAX_X; x++) {
                        for (int y = MAX_Y - 1; y >= 0; y--) {
                            if (tiles[x][y].getNumber() != 0) {
                                continue;
                            }
                            for (int y0 = y - 1; y0 >= 0; y0--) {
                                if (tiles[x][y0].getNumber() == 0) {
                                    continue;
                                } else {
                                    tiles[x][y].setNumber(tiles[x][y0].getNumber());
                                    tiles[x][y0].setNumber(0);
                                    isMove = true;
                                    break;
                                }
                            }
                        }
                    }
                    if (isMove) {
                        newTile();
                        invalidate();
                        judgeOver();
                    }
                } else if (moveY < -50) {
                    //上滑
                    //合并
                    boolean isMove = false;
                    for (int x = 0; x < MAX_X; x++) {
                        for (int y = 0; y < MAX_Y; y++) {
                            if (tiles[x][y].getNumber() == 0) {
                                continue;
                            }
                            for (int y0 = y + 1; y0 < MAX_Y; y0++) {
                                if (tiles[x][y0].getNumber() == 0) {
                                    continue;
                                } else if (tiles[x][y].getNumber() == tiles[x][y0].getNumber()) {
                                    tiles[x][y].setNumber(tiles[x][y].getNumber() * 2);
                                    tiles[x][y0].setNumber(0);
                                    isMove = true;
                                    break;
                                } else {
                                    break;
                                }
                            }
                        }
                    }
                    //移动
                    for (int x = 0; x < MAX_X; x++) {
                        for (int y = 0; y < MAX_Y; y++) {
                            if (tiles[x][y].getNumber() != 0) {
                                continue;
                            }
                            for (int y0 = y + 1; y0 < MAX_Y; y0++) {
                                if (tiles[x][y0].getNumber() == 0) {
                                    continue;
                                } else {
                                    tiles[x][y].setNumber(tiles[x][y0].getNumber());
                                    tiles[x][y0].setNumber(0);
                                    isMove = true;
                                    break;
                                }
                            }
                        }
                    }
                    if (isMove) {
                        newTile();
                        invalidate();
                        judgeOver();
                    }
                }
            }
        }
    }

    private void overLogic(MotionEvent event) {
        if (event.getX() > 0) {
            newGame();
            gameState = GameState.Playing;
        }
    }

    private void judgeOver() {
        //右滑
        //合并
        for (int y = 0; y < MAX_Y; y++) {
            for (int x = MAX_X - 1; x >= 0; x--) {
                if (tiles[x][y].getNumber() == 0) {
                    continue;
                }
                for (int x0 = x - 1; x0 >= 0; x0--) {
                    if (tiles[x0][y].getNumber() == 0) {
                        continue;
                    } else if (tiles[x][y].getNumber() == tiles[x0][y].getNumber()) {
                        return;
                    } else {
                        break;
                    }
                }
            }
        }
        //移动
        for (int y = 0; y < MAX_Y; y++) {
            for (int x = MAX_X - 1; x >= 0; x--) {
                if (tiles[x][y].getNumber() != 0) {
                    continue;
                }
                for (int x0 = x - 1; x0 >= 0; x0--) {
                    if (tiles[x0][y].getNumber() == 0) {
                        continue;
                    } else {
                        return;
                    }
                }
            }
        }
        //左滑
        //合并
        for (int y = 0; y < MAX_Y; y++) {
            for (int x = 0; x < MAX_X; x++) {
                if (tiles[x][y].getNumber() == 0) {
                    continue;
                }
                for (int x0 = x + 1; x0 < MAX_X; x0++) {
                    if (tiles[x0][y].getNumber() == 0) {
                        continue;
                    } else if (tiles[x][y].getNumber() == tiles[x0][y].getNumber()) {
                        return;
                    } else {
                        break;
                    }
                }
            }
        }
        //移动
        for (int y = 0; y < MAX_Y; y++) {
            for (int x = 0; x < MAX_X; x++) {
                if (tiles[x][y].getNumber() != 0) {
                    continue;
                }
                for (int x0 = x + 1; x0 < MAX_X; x0++) {
                    if (tiles[x0][y].getNumber() == 0) {
                        continue;
                    } else {
                        return;
                    }
                }
            }
        }
        //下滑
        //合并
        for (int x = 0; x < MAX_X; x++) {
            for (int y = MAX_Y - 1; y >= 0; y--) {
                if (tiles[x][y].getNumber() == 0) {
                    continue;
                }
                for (int y0 = y - 1; y0 >= 0; y0--) {
                    if (tiles[x][y0].getNumber() == 0) {
                        continue;
                    } else if (tiles[x][y].getNumber() == tiles[x][y0].getNumber()) {
                        return;
                    } else {
                        break;
                    }
                }
            }
        }
        //移动
        for (int x = 0; x < MAX_X; x++) {
            for (int y = MAX_Y - 1; y >= 0; y--) {
                if (tiles[x][y].getNumber() != 0) {
                    continue;
                }
                for (int y0 = y - 1; y0 >= 0; y0--) {
                    if (tiles[x][y0].getNumber() == 0) {
                        continue;
                    } else {
                        return;
                    }
                }
            }
        }
        //上滑
        //合并
        for (int x = 0; x < MAX_X; x++) {
            for (int y = 0; y < MAX_Y; y++) {
                if (tiles[x][y].getNumber() == 0) {
                    continue;
                }
                for (int y0 = y + 1; y0 < MAX_Y; y0++) {
                    if (tiles[x][y0].getNumber() == 0) {
                        continue;
                    } else if (tiles[x][y].getNumber() == tiles[x][y0].getNumber()) {
                        return;
                    } else {
                        break;
                    }
                }
            }
        }
        //移动
        for (int x = 0; x < MAX_X; x++) {
            for (int y = 0; y < MAX_Y; y++) {
                if (tiles[x][y].getNumber() != 0) {
                    continue;
                }
                for (int y0 = y + 1; y0 < MAX_Y; y0++) {
                    if (tiles[x][y0].getNumber() == 0) {
                        continue;
                    } else {
                        return;
                    }
                }
            }
        }
        gameState = GameState.Over;
        invalidate();
    }
}

说两句:

这次跟上次的五子棋用的一样的游戏框架,应该很容易理解游戏的主题逻辑,当然最重要的是游戏算法,我实现的算法可能有些麻烦,但还算达到了效果,欢迎提意见。

关于主体算法:

我分了两个步骤:1.合并。2.移动
哎呀,不写了,有兴趣的人自己看代码吧,好像也没多少人看我写这个东西。。。囧

下次写个能动的游戏,就贪吃蛇吧,感觉自己帅的人请加我的公众微信号:xinshouit 更新会在里面通知

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值