Android 小游戏之五子棋 代码简单实现

鸿洋写的五子棋教程

public class WuZhiQiView extends View { //自定义的五子棋View
    //画一个棋盘,在中间画一个一个的小正方形,主要实现在onDraw   method
    //画棋子,主要实现在onDraw   method
    //点击那里实现具体判断具体位置,在具体位置画棋子
    //实现输赢判断机制
    protected static int GRID_SIZE = 15;    //一排有几个格子 ,线要比实际多一条
    protected static int GRID_WIDTH = 20;  //棋盘格的宽度 --下面做了自动适配屏幕 --这里数字无效
    protected static int CHESS_DIAMETER = 16; // 棋的直径  --下面做了自动适配屏幕 --这里数字无效
    protected static int mStartX;// 棋盘定位的左上角X
    protected static int mStartY;// 棋盘定位的左上角Y
    private static int[][] mGridArray; // 网格 ---进行标识棋子的位置 -- 用来画旗子和判断输赢
    boolean key = false;//是否下棋了
    int wbflag = 1; //该下白棋了=2,该下黑棋了=1. 这里先下黑棋(黑棋以后设置为机器自动下的棋子)
    int mWinFlag = 0;//游戏赢了的标志 为1就是黑棋赢了 2为白棋子赢了
    private final int BLACK = 1;//黑棋
    private final int WHITE = 2;//白棋

    int mGameState = GAMESTATE_RUN; //游戏阶段:0=尚未游戏,1=正在进行游戏,3=游戏结束
    static final int GAMESTATE_PRE = 0;
    static final int GAMESTATE_RUN = 1;
    static final int GAMESTATE_PAUSE = 2;  //游戏暂停
    static final int GAMESTATE_END = 3;  //游戏结束



    private final Paint mPaint = new Paint();//是声明用来画棋子图片的笔,没用上

    CharSequence mText;
    CharSequence STRING_WIN = "白方棋子赢,按返回键重新开始";
    CharSequence STRING_LOSE = "黑方棋子赢,按返回键重新来过";
    CharSequence STRING_EQUAL = "Cool! You are equal! /n Press Fire Key to start new Game.";
    private static Bitmap mBitmap;   //记录这一刻的画面 ---不用每次画棋盘和旗子
    private Canvas mMCanvas; //在画布上操作mBitmap的画面 --- 进行给上次的bitmap添加一个旗子就可以了


    public WuZhiQiView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.setFocusable(true);//设置获取焦点
        setFocusableInTouchMode(true);//设置可以触摸
        init();//画棋子
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        return super.dispatchTouchEvent(event);
    }

    private void init() {//画棋子等逻辑
        mGameState = 1; //设置游戏为开始状态
        wbflag = BLACK; //初始为先下黑棋
        mWinFlag = 0;   //清空输赢标志。
        mGridArray = new int[GRID_SIZE + 1][GRID_SIZE + 1];//初始化网格的大小
    }

    public TextView mStatusTextView; //  根据游戏状态设置显示的文字 --- 这里只是简单的显示谁赢了

    public void setTextView(TextView tv) { //给外面的接口显示输赢信息 // TODO 可以自己修改
        mStatusTextView = tv;
        mStatusTextView.setVisibility(View.INVISIBLE);//显示输赢的textView
    }

    public  int dip2px(float dpValue) { //dp 转 px
        final float scale = getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        GRID_WIDTH = w/GRID_SIZE-dip2px(2);//自行匹配屏幕
        CHESS_DIAMETER =GRID_WIDTH -dip2px(5);//自行匹配棋子的宽度
        mStartX = w / 2 - GRID_SIZE * GRID_WIDTH / 2;//棋盘定位的左上角X
        mStartY = h / 2 - GRID_SIZE * GRID_WIDTH / 2;//棋盘定位的左上角Y
    }

    int x;//记录触摸最后棋子落子的位置(是在数据里的角标记录)
    int y;//记录触摸最后棋子落子的位置

    //触摸事件的处理
    @Override
    public boolean onTouchEvent(MotionEvent event) {//处理棋子落子后的逻辑
        key = true;
        switch (mGameState) {//游戏状态
            case GAMESTATE_PRE://游戏未开始
                break;
            case GAMESTATE_RUN: {//游戏开始
                float x0 = GRID_WIDTH - (event.getX() - mStartX) % GRID_WIDTH;//是否是触摸了网格上面的x
                float y0 = GRID_WIDTH - (event.getY() - mStartY) % GRID_WIDTH;//是否是触摸了网格上面的y
                if (x0 < GRID_WIDTH / 2) {//判断是否超过了网格线的一半
                    x = (int) ((event.getX() - mStartX) / GRID_WIDTH) + 1;//x为网格的线上
                } else {
                    x = (int) ((event.getX() - mStartX) / GRID_WIDTH);//x为网格的线上 上一格
                }
                if (y0 < GRID_WIDTH / 2) {//判断是否超过了网格线的一半
                    y = (int) ((event.getY() - mStartY) / GRID_WIDTH) + 1;
                } else {
                    y = (int) ((event.getY() - mStartY) / GRID_WIDTH);
                }
                if ((x >= 0 && x < GRID_SIZE + 1)
                        && (y >= 0 && y < GRID_SIZE + 1)) {//是否是在网格线上
                    if (mGridArray[x][y] == 0) {//如果棋盘的点没有没赋值,就可以被下子
                        if (wbflag == BLACK) {//判断是黑棋 下棋
                            putChess(x, y, BLACK);//下子,给数组里的棋子赋值做标记
                            //this.mGridArray[x][y] = 1;
                            if (checkWin(BLACK)) { //如果是黑棋赢了,判断机制
                                mText = STRING_LOSE;//文本
                                mGameState = GAMESTATE_END;//标记游戏结束,不能下棋子
                                showTextView(mText);//显示文本
                            } else if (checkFull()) {//如果棋盘满了
                                mText = STRING_EQUAL;//文本
                                mGameState = GAMESTATE_END;//标记游戏结束,不能下棋子
                                showTextView(mText);//显示文本
                            }

                            wbflag = WHITE;//标记另一方下子
                            this.invalidate();//重画界面
                        } else if (wbflag == WHITE) { //判断是白棋下子
                            putChess(x, y, WHITE);
                            //this.mGridArray[x][y] = 2;
                            if (checkWin(WHITE)) {
                                mText = STRING_WIN;
                                mGameState = GAMESTATE_END;
                                showTextView(mText);
                            } else if (checkFull()) {//如果棋盘满了
                                mText = STRING_EQUAL;
                                mGameState = GAMESTATE_END;
                                showTextView(mText);
                            }
                            wbflag = BLACK;
                            this.invalidate();//重画界面
                        }
                    }
                }

            }

            break;
            case GAMESTATE_PAUSE://游戏暂停
                break;
            case GAMESTATE_END://游戏结束
                break;
        }
            return true;

    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent msg) {//复写返回按钮,重新开始

        if (keyCode == KeyEvent.KEYCODE_BACK) {
            switch (mGameState) {
                case GAMESTATE_PRE://游戏状态,游戏准备前
                    break;
                case GAMESTATE_RUN:
                    break;
                case GAMESTATE_PAUSE:
                    break;
                case GAMESTATE_END: {//游戏结束后,按CENTER键继续
                    mGameState = GAMESTATE_RUN;//改变游戏状态
                    this.setVisibility(View.VISIBLE);//本view可见
                    this.mStatusTextView.setVisibility(View.INVISIBLE);//提示信息不可见
                    this.init();//重画棋子等,重走逻辑
                    flag = false;
                    this.invalidate();//重画
                }
                break;
            }
        }

        return true;//复写方法,自己处理
    }

    boolean flag;

    @Override
    public void onDraw(Canvas canvas) {// 画棋盘
        canvas.drawColor(Color.YELLOW);
        if (flag == false) {//控制画棋盘的次数,只画一次棋盘,提高绘制效率
            mBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
            mMCanvas = new Canvas(mBitmap);
            // 画棋盘
            //画棋盘的外边框
            mPaint.setColor(Color.GRAY);//设置画笔的颜色,灰色
            mPaint.setStyle(Paint.Style.STROKE);//设置风格是描边
            mPaint.setStrokeWidth(4);
            mMCanvas.drawRect(mStartX, mStartY, mStartX + GRID_WIDTH * GRID_SIZE, mStartY + GRID_WIDTH * GRID_SIZE, mPaint);

            mPaint.setStrokeWidth(2);//设置线条宽度
            //画中间的格子
            for (int i = 0; i < GRID_SIZE; i++) {//画线
                for (int j = 0; j < GRID_SIZE; j++) {
                    int mLeft = i * GRID_WIDTH + mStartX;
                    int mTop = j * GRID_WIDTH + mStartY;
                    int mRright = mLeft + GRID_WIDTH;
                    int mBottom = mTop + GRID_WIDTH;
                    mMCanvas.drawRect(mLeft, mTop, mRright, mBottom, mPaint);//画一段一段小矩形,形成棋盘
                }
            }
            flag = true;
        }
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);  //设置风格是描边和填充
        if (mGridArray[x][y] == BLACK) { //画黑棋子
            mPaint.setColor(Color.BLACK);
            mMCanvas.drawCircle(mStartX + x * GRID_WIDTH, mStartY + y * GRID_WIDTH, CHESS_DIAMETER / 2, mPaint);
        } else if (mGridArray[x][y] == WHITE) { //画白棋
            mPaint.setColor(Color.WHITE);
            mMCanvas.drawCircle(mStartX + x * GRID_WIDTH, mStartY + y * GRID_WIDTH, CHESS_DIAMETER / 2, mPaint);
        }
        canvas.drawBitmap(mBitmap, 0, 0, mPaint);
    }

    public void putChess(int x, int y, int blackwhite) {//标志棋子赋值,给棋子做标记
        mGridArray[x][y] = blackwhite;
    }

    public boolean checkWin(int wbflag) {//输赢判断机制
        for (int i = 0; i < GRID_SIZE - 1; i++) //i表示列(根据宽度算出来的)
            for (int j = 0; j < GRID_SIZE - 1; j++) {//i表示行(根据高度算出来的)
                //检测横轴五个相连
                if (((i + 4) < (GRID_SIZE - 1)) &&
                        (mGridArray[i][j] == wbflag) && (mGridArray[i + 1][j] == wbflag) && (mGridArray[i + 2][j] == wbflag) && (mGridArray[i + 3][j] == wbflag) && (mGridArray[i + 4][j] == wbflag)) {
                    Log.e("check win or loss:", wbflag + "win");

                    mWinFlag = wbflag;
                }

                //纵轴5个相连
                if (((j + 4) < (GRID_SIZE - 1)) &&
                        (mGridArray[i][j] == wbflag) && (mGridArray[i][j + 1] == wbflag) && (mGridArray[i][j + 2] == wbflag) && (mGridArray[i][j + 3] == wbflag) && (mGridArray[i][j + 4] == wbflag)) {
                    Log.e("check win or loss:", wbflag + "win");

                    mWinFlag = wbflag;
                }

                //左上到右下5个相连
                if (((j + 4) < (GRID_SIZE - 1)) && ((i + 4) < (GRID_SIZE - 1)) &&
                        (mGridArray[i][j] == wbflag) && (mGridArray[i + 1][j + 1] == wbflag) && (mGridArray[i + 2][j + 2] == wbflag) && (mGridArray[i + 3][j + 3] == wbflag) && (mGridArray[i + 4][j + 4] == wbflag)) {
                    Log.e("check win or loss:", wbflag + "win");

                    mWinFlag = wbflag;
                }

                //右上到左下5个相连
                if (((i - 4) >= 0) && ((j + 4) < (GRID_SIZE - 1)) &&
                        (mGridArray[i][j] == wbflag) && (mGridArray[i - 1][j + 1] == wbflag) && (mGridArray[i - 2][j + 2] == wbflag) && (mGridArray[i - 3][j + 3] == wbflag) && (mGridArray[i - 4][j + 4] == wbflag)) {
                    Log.e("check win or loss:", wbflag + "win");

                    mWinFlag = wbflag;
                }
            }

        if (mWinFlag == wbflag) {
            return true;
        } else {
            return false;
        }

    }

    public boolean checkFull() {//判断是否棋子已经满棋盘了
        int mNotEmpty = 0;
        for (int i = 0; i < GRID_SIZE - 1; i++)
            for (int j = 0; j < GRID_SIZE - 1; j++) {
                if (mGridArray[i][j] != 0) mNotEmpty += 1;
            }

        if (mNotEmpty == (GRID_SIZE - 1) * (GRID_SIZE - 1))
            return true;
        else
            return false;
    }

    public void showTextView(CharSequence mT) {//显示提示文本
        if(mStatusTextView==null) return; 
        this.mStatusTextView.setText(mT);
        mStatusTextView.setVisibility(View.VISIBLE);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值