小游戏2048

这是在自定义控件中练习中出现的产物。通过游戏界面,很明显主要就是一个表格布局,主要的自定义控件主要是两个GamePanel 和Card。

MainActivity代码如下:

public class AndroidGameActivity extends Activity implements GamePanel.OnChangeListener {
    private TextView mTvScore;
    private TextView mTvBestScore;
    private Button mBtnNewGame;
    private GamePanel mGamePanel;
    private ResultDialog mDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_android_game);
        initViews();
        initData();
    }

    private void initViews() {
        mTvScore = (TextView) findViewById(R.id.tv_current_score);
        mTvBestScore = (TextView) findViewById(R.id.tv_best_score);
        mBtnNewGame = (Button) findViewById(R.id.btn_new_game);
        mBtnNewGame.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startNewGame();
            }
        });
        mGamePanel = (GamePanel) findViewById(R.id.game_panel);
        mGamePanel.setOnChangeListener(this);
    }

    private void initData() {
        startNewGame();
    }

    @Override
    public void onBackPressed() {
        if (mDialog != null && mDialog.isShowing()) {
            mDialog.dismiss();
            return;
        }

        super.onBackPressed();
    }

    private void setCurrentScore(int score) {
        mTvScore.setText("SCORE\n" + score);
    }

    private void setBestScore(int score) {
        mTvBestScore.setText("BEST\n" + score);
    }


    private void startNewGame() {
        setCurrentScore(0);
        setBestScore(Config.getBestScore(this));
        mGamePanel.restartGame();
    }


    @Override
    public void onChange() {
        setCurrentScore(mGamePanel.getScore());
    }

    @Override
    public void onGameOver(boolean isSuccess) {
        if (mDialog == null) {
            mDialog = new ResultDialog(AndroidGameActivity.this, new ResultDialog.OnOkListener() {
                @Override
                public void onOk() {
                    startNewGame();
                }

                @Override
                public void onCancel() {
                    finish();
                }
            });
        }
        if (isSuccess) {
            mDialog.setMsg("游戏闯关成功", "是否再来一局?");
        } else {
            mDialog.setMsg("游戏闯关失败", "是否再来一局?");
        }
        mDialog.show();
    }
}

Card代码如下:

public class Card extends View {
    private Paint mBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private int bgColor;
    private int bgCorner = 4;
    private static final int smallTextSize = 30;
    private int textSize = 50;
    private int textColor;
    private int widthSize;
    private int number = 0;

    public Card(Context context) {
        super(context);
        init();
    }

    public Card(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        widthSize = AppUtils.getCardSize(getContext());
        bgColor = GameColor.getCardBgColor(number);
        textColor = GameColor.getCardFontColor(number);
    }

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

    public int getNumber() {
        return number;
    }

    public void setDoubleNumber() {
        number = number * 2;
        if (number >= 1024) {
            mTextPaint.setTextSize(smallTextSize);
        }
        invalidate();
    }

    @Override
    public void invalidate() {
        bgColor = GameColor.getCardBgColor(number);
        textColor = GameColor.getCardFontColor(number);
        super.invalidate();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(widthSize, widthSize);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 设置圆角背景
        mBgPaint.setColor(bgColor);
        RectF bgRect = new RectF(0, 0, widthSize, widthSize);
        canvas.drawRoundRect(bgRect, bgCorner, bgCorner, mBgPaint);
        // 绘制分数
        if (number > 0) {
            String num = String.valueOf(number);
            mTextPaint.setColor(textColor);
            mTextPaint.setTextSize(textSize);
            Paint.FontMetrics metrics = mTextPaint.getFontMetrics();
            int textWidth = (int) mTextPaint.measureText(num);
            int x = widthSize / 2 - textWidth / 2;
            int y = (int) (widthSize - Math.abs(metrics.descent) + Math.abs(metrics.ascent)) / 2;
            canvas.drawText(String.valueOf(number), x, y, mTextPaint);
        }
    }
}

GamePanel代码如下:

public class GamePanel extends ViewGroup {
    //列数
    public static final int DEFAULT_COLUMN = 4;
    // 行数
    public static final int DEFAULT_ROW = 4;

    private Card[][] mGroup;
    private int score = 0;
    private int viewSize;
    private float lastX;
    private float lastY;
    private int touchSlop;
    private ArrayList<Integer> indexs = new ArrayList<Integer>();
    private ArrayList<Point> positions = new ArrayList<Point>();
    private OnChangeListener mListener;


    public GamePanel(Context context) {
        super(context);
        init();
    }

    public GamePanel(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        touchSlop = (int) (ViewConfiguration.get(getContext()).getScaledTouchSlop() * 1.2f);
        viewSize = AppUtils.getPanelSize(getContext());
        mGroup = new Card[DEFAULT_ROW][DEFAULT_COLUMN];
        for (int i = 0; i < DEFAULT_ROW; i++) {
            for (int j = 0; j < DEFAULT_COLUMN; j++) {
                mGroup[i][j] = new Card(getContext());
                positions.add(new Point(i, j));
                addView(mGroup[i][j]);
            }
        }
        score = 0;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        for (int i = 0; i < DEFAULT_ROW; i++) {
            for (int j = 0; j < DEFAULT_COLUMN; j++) {
                mGroup[i][j].measure(widthMeasureSpec, heightMeasureSpec);
            }
        }
        setMeasuredDimension(viewSize, viewSize);
    }

    @Override
    protected void onLayout(boolean changed,
                            int l, int t, int r, int b) {
        if (changed) {
            int padding = AppUtils.dip2px(getContext(), 10);
            int size = AppUtils.getCardSize(getContext());
            for (int i = 0; i < DEFAULT_ROW; i++) {
                for (int j = 0; j < DEFAULT_COLUMN; j++) {
                    int left = padding + j * (padding + size);
                    int top = padding + i * (padding + size);
                    mGroup[i][j].layout(left, top, left + size, top + size);
                }
            }
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (indexs != null && indexs.size() > 0) {
                    indexs.clear();
                }
                lastX = x;
                lastY = y;
                break;
            case MotionEvent.ACTION_UP:
                float tempX = x - lastX;
                float tempY = y - lastY;
                if (Math.abs(tempX) >= touchSlop && Math.abs(tempX) > Math.abs(tempY)) {
                    if (tempX > 0) {
                        goRight();
                    } else {
                        goLeft();
                    }
                } else if (Math.abs(tempY) >= touchSlop && Math.abs(tempY) > Math.abs(tempX)) {
                    if (tempY > 0) {
                        goBottom();
                    } else {
                        goTop();
                    }
                }
                lastX = 0;
                lastY = 0;
                break;
            case MotionEvent.ACTION_CANCEL:
                lastX = 0;
                lastY = 0;
                break;
        }
        return true;
    }

    public void restartGame() {
        score = 0;
        if (mGroup != null) {
            for (int i = 0; i < DEFAULT_ROW; i++) {
                for (int j = 0; j < DEFAULT_COLUMN; j++) {
                    mGroup[i][j].setNumber(0);
                }
            }
        }
        getRandomItem();
        getRandomItem();
    }

    // 随机生成一个item
    public void getRandomItem() {
        if (GameScore.isGameSuccess(mGroup)) {
            Config.saveBestScore(getContext(), score + Config.GAME_SUCCESS_EXTRA);
            if (mListener != null) {
                mListener.onGameOver(true);
            }
            return;
        } else if (positions.size() == 0 && !GameScore.isGameMerge(mGroup)) {
            Config.saveBestScore(getContext(), score);
            if (mListener != null) {
                mListener.onGameOver(false);
            }
            return;
        }
        Point p = getRandomPos();
        if (p != null) {
            LogUtils.e("随机生成的pos,x:" + p.x + "y:" + p.y);
            if (mGroup[p.x][p.y].getNumber() == 0) {
                mGroup[p.x][p.y].setNumber(2);
            } else {
                getRandomItem();
            }
        }
    }

    private void buildPositions() {
        positions.clear();
        for (int i = 0; i < DEFAULT_ROW; i++) {
            for (int j = 0; j < DEFAULT_COLUMN; j++) {
                if (mGroup[i][j].getNumber() == 0) {
                    positions.add(new Point(i, j));
                }
            }
        }
    }

    private Point getRandomPos() {
        if (positions.size() == 0) {
            return null;
        }
        Random random = new Random();
        int pos = random.nextInt(positions.size());
        Point p = positions.remove(pos);
        return p;
    }

    /**
     * 继续生成下一个随机位置
     */
    private void getNextRandom() {
        if (mListener != null) {
            mListener.onChange();
        }
        buildPositions();
        getRandomItem();
    }

    private void addScore(int newNumber) {
        score += GameScore.addGameScore(newNumber);
    }

    /**
     * 向左滑动
     */
    private void goLeft() {
        for (int i = 0; i < DEFAULT_ROW; i++) {
            for (int j = 0; j < DEFAULT_COLUMN; j++) {
                Card cur = mGroup[i][j];
                if (cur.getNumber() > 0) {
                    mergeLeft(i, j);
                    if (indexs != null && indexs.size() > 0) {
                        mGroup[i][indexs.get(0)].setNumber(cur.getNumber());
                        if (!mergeLeft(i, indexs.get(0) - 1)) {
                            mergeLeft(i, indexs.get(0));
                        }
                        cur.setNumber(0);
                        indexs.remove(0);
                    }
                } else {
                    indexs.add(j);
                }
            }
            if (indexs != null && indexs.size() > 0) {
                indexs.clear();
            }
        }
        getNextRandom();
    }

    private boolean mergeLeft(int i, int j) {
        if (i >= 0 && i < DEFAULT_ROW && j >= 0 && j < DEFAULT_COLUMN) {
            Card cur = mGroup[i][j];
            if (j < DEFAULT_COLUMN - 1) {
                Card next = mGroup[i][j + 1];
                if (next.getNumber() == cur.getNumber()) {
                    cur.setDoubleNumber();
                    addScore(cur.getNumber());
                    next.setNumber(0);
                    return true;
                }
            }
        }
        return false;
    }


    /**
     * 向上滑动
     */
    private void goTop() {
        for (int j = 0; j < DEFAULT_COLUMN; j++) {
            for (int i = 0; i < DEFAULT_ROW; i++) {
                Card cur = mGroup[i][j];
                if (cur.getNumber() > 0) {
                    mergeTop(i, j);
                    if (indexs != null && indexs.size() > 0) {
                        mGroup[indexs.get(0)][j].setNumber(cur.getNumber());
                        if (!mergeTop(indexs.get(0) - 1, j)) {
                            mergeTop(indexs.get(0), j);
                        }
                        cur.setNumber(0);
                        indexs.remove(0);
                    }
                } else {
                    indexs.add(i);
                }
            }
            if (indexs != null && indexs.size() > 0) {
                indexs.clear();
            }
        }
        getNextRandom();
    }

    private boolean mergeTop(int i, int j) {
        if (i >= 0 && i < DEFAULT_ROW && j >= 0 && j < DEFAULT_COLUMN) {
            Card cur = mGroup[i][j];
            if (i < DEFAULT_ROW - 1) {
                Card next = mGroup[i + 1][j];
                if (next.getNumber() == cur.getNumber()) {
                    cur.setDoubleNumber();
                    addScore(cur.getNumber());
                    next.setNumber(0);
                    return true;
                }
            }
        }
        return false;
    }


    /**
     * 向右滑动
     */
    private void goRight() {
        for (int i = 0; i < DEFAULT_ROW; i++) {
            for (int j = DEFAULT_COLUMN - 1; j >= 0; j--) {
                Card cur = mGroup[i][j];
                if (cur.getNumber() > 0) {
                    mergeRight(i, j);
                    if (indexs != null && indexs.size() > 0) {
                        mGroup[i][indexs.get(0)].setNumber(cur.getNumber());
                        if (!mergeRight(i, indexs.get(0) + 1)) {
                            mergeRight(i, indexs.get(0));
                        }
                        cur.setNumber(0);
                        indexs.remove(0);
                    }
                } else {
                    indexs.add(j);
                }

            }
            if (indexs != null && indexs.size() > 0) {
                indexs.clear();
            }
        }
        getNextRandom();
    }

    private boolean mergeRight(int i, int j) {
        if (i >= 0 && i < DEFAULT_ROW && j >= 0 && j < DEFAULT_COLUMN) {
            Card cur = mGroup[i][j];
            if (j > 0) {
                Card last = mGroup[i][j - 1];
                if (last.getNumber() == cur.getNumber()) {
                    cur.setDoubleNumber();
                    addScore(cur.getNumber());
                    last.setNumber(0);
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 向下滑动
     */
    private void goBottom() {
        for (int j = 0; j < DEFAULT_COLUMN; j++) {
            for (int i = DEFAULT_ROW - 1; i >= 0; i--) {
                Card cur = mGroup[i][j];
                if (cur.getNumber() > 0) {
                    mergeBottom(i, j);
                    if (indexs != null && indexs.size() > 0) {
                        mGroup[indexs.get(0)][j].setNumber(cur.getNumber());
                        if (!mergeBottom(indexs.get(0) + 1, j)) {
                            mergeBottom(indexs.get(0), j);
                        }
                        cur.setNumber(0);
                        indexs.remove(0);
                    }
                } else {
                    indexs.add(i);
                }
            }
            if (indexs != null && indexs.size() > 0) {
                indexs.clear();
            }
        }
        getNextRandom();
    }

    private boolean mergeBottom(int i, int j) {
        if (i >= 0 && i < DEFAULT_ROW && j >= 0 && j < DEFAULT_COLUMN) {
            Card cur = mGroup[i][j];
            if (i > 0) {
                Card last = mGroup[i - 1][j];
                if (last.getNumber() == cur.getNumber()) {
                    cur.setDoubleNumber();
                    addScore(cur.getNumber());
                    last.setNumber(0);
                    return true;
                }
            }
        }
        return false;
    }

    public int getScore() {
        return score;
    }

    public void setOnChangeListener(OnChangeListener l) {
        mListener = l;
    }


    public interface OnChangeListener {
        void onChange();

        void onGameOver(boolean isSuccess);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值