五子棋的实现

大家好,今天我来说说五子棋游戏的实现.
五子棋,包涵了棋盘和棋子,在这里我使用BitMap实现了棋盘和棋子,通过SurfaceView(对SurfaceView不熟悉的同学,可以看看其他博客了解一下)来展示BitMap,通过在工作线程中在BitMap上绘制棋盘和棋子,也就是使用二级缓存。这样减轻了View的绘制负担,提高了游戏的流畅度.废话不多说,上图.
这里是棋盘是正方形

棋盘是正方形,棋子是绘制的BitMap:代码如下

 public void drawQiPan() {
    Canvas ca = new Canvas(mMyQiPan);
    int w = (getWidth() - 100) / 100 * 100;
    int h = (getHeight() - 100) / 100 * 100;
    value = Math.min(w, h);
    mPaint.setColor(Color.BLACK);
    mPaint.setStrokeWidth(5);
    mPaint.setAntiAlias(true);
    //起点
    int x = (getWidth() - value) / 2;
    int y = (getHeight() - value) / 2;
    for (int i = 0; i <= value; i = i + 100) {
        ca.drawLine(i + x, 0 + y, i + x, value + y, mPaint);
        ca.drawLine(0 + x, i + y, value + x, i + y, mPaint);
    }
}

//这里是绘制棋子BitMap和一些初始化工作

private void init() {
    holder = getHolder();
    mThread = new Thread(this);
    mMyQiPan = BitmapFactory.decodeResource(getResources(), R.mipmap.bg).copy(Config.ARGB_8888, true);
    mWhite = Bitmap.createBitmap(100, 100, Config.ARGB_8888).copy(Config.ARGB_8888, true);
    mBlack = Bitmap.createBitmap(100, 100, Config.ARGB_8888).copy(Config.ARGB_8888, true);
    mPaint = new Paint();
    mPaint.setColor(Color.WHITE);
    Canvas ca = new Canvas(mWhite);
    mPaint.setColor(Color.RED);
    mPaint.setAntiAlias(true);
    ca.drawCircle(45, 45, 46, mPaint);
    mPaint.setColor(Color.WHITE);
    ca.drawCircle(45, 45, 44, mPaint);
    mPaint.setColor(Color.BLACK);
    Canvas caa = new Canvas(mBlack);
    mPaint.setColor(Color.WHITE);
    mPaint.setAntiAlias(true);
    caa.drawCircle(45, 45, 46, mPaint);
    mPaint.setColor(Color.BLACK);
    caa.drawCircle(45, 45, 44, mPaint);
    mQiZiBlack = new ArrayList<>();
    mQiZiWihte = new ArrayList<>();
    mRect = new Rect(0, 0, getWidth(), getHeight());
    holder.addCallback(this);
}

// 这里写图片描述
绘制好棋盘和准备好棋子后,需要对触摸操作进行绘制棋子

public boolean onTouchEvent(MotionEvent event) {
    //起点
    int x = (getWidth() - value) / 2;
    int y = (getHeight() - value) / 2;
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            return true;
        case MotionEvent.ACTION_MOVE:
            isMoving = true;
            return false;
        case MotionEvent.ACTION_UP:
            if (isWin||isMoving) {
                break;
            }
            int xx = (int) event.getX();
            int yy = (int) event.getY();
            currentPoint = new Point((xx - x) / 100, (yy - y) / 100);
            if (!check(currentPoint)) {
                break;
            }
            isWhite = !isWhite;
            if (isWhite) {
                mQiZiWihte.add(currentPoint);
            } else {
                mQiZiBlack.add(currentPoint);
            }
            //判断在那个位置上
            new Thread(this).start();
            //判断
            if (isWhite) {
                if (mQiZiWihte.size() < 5) {
                    break;
                }
            } else {
                if (mQiZiBlack.size() < 5) {
                    break;
                }
            }

            if (currentPoint != null ) {
                checkH(currentPoint,true);
                if (!isWin){
                    checkH(currentPoint,false);
                }
                if (!isWin){
                    checkDuijiao();
                }
                if (!isWin){
                    chekZhengXianxian();
                }

                if (isWin) {
                    Toast.makeText(getContext().getApplicationContext(), "赢了", Toast.LENGTH_LONG).show();
                }
            }
            break;
    }

    return super.onTouchEvent(event);
}
这里是当收到UP事件的时候进行处理,当移动事件发生时,我们就不作处理.保存完黑白棋子集合后,就要绘制它们了,代码如下:
 //线程方法
@Override
public void run() {
    int x = (getWidth() - value) / 2;
    int y = (getHeight() - value) / 2;
    drawQiPan();
    Canvas ca = new Canvas(mMyQiPan);

    for (int i = 0; i < mQiZiWihte.size(); i++) {
        ca.drawBitmap(mWhite, mQiZiWihte.get(i).x * 100 + x - 46, mQiZiWihte.get(i).y * 100 + y - 46, mPaint);
    }
    for (int i = 0; i < mQiZiBlack.size(); i++) {
        ca.drawBitmap(mBlack, mQiZiBlack.get(i).x * 100 + x - 46, mQiZiBlack.get(i).y * 100 + y - 46, mPaint);
    }

    Canvas canvas = holder.lockCanvas(mRect);
    canvas.drawBitmap(mMyQiPan, mRect, new Rect(0, 0, getWidth(), getHeight()), mPaint);
    holder.unlockCanvasAndPost(canvas);
}
通过线程绘制图片,再讲图片贴在View上面,减轻View的负担。接下来就要处理棋子落下的正确性检查
1.检查该位置是否已经下过;
public boolean check(Point point) {
    int num = value / 100;
    if (mQiZiWihte.contains(point) || mQiZiBlack.contains(point)) {
        return false;
    }
    if (point.x >= 0 && point.y < num + 1 && point.x < num + 1 && point.y >= 0) {
        return true;
    }
    return false;
}
2.检查是否是5子连珠(横,竖,正对角,斜对角);
public void checkH(Point point,boolean isX) {

    int x = point.x;
    int y = point.y;
    int count = 1;
    int xunhuan;
    if (isX){

        xunhuan = x;
    }else {
        xunhuan = y;
    }
    //想左
    for (int i = xunhuan - 1; i >= 0; i--) {
        int xx;
        int yy;
        if (isX){
           xx = i;
           yy = point.y;
        }else {
            xx = point.x;
            yy = i;
        }
        if (equal(xx, yy)) {
            count++;
            Log.e("==z====","====="+count);
            if (countCheck(count)) {
                isWin = true;
                Log.e("==z====","==1==="+count);
                return;
            }
        } else {
            break;
        }
    }
    //向右
    for (int i = xunhuan + 1; i < value / 100 + 1; i++) {
        int xx;
        int yy;
        if (isX){
            xx = i;
            yy = point.y;
        }else {
            xx = point.x;
            yy = i;
        }
        if (equal(xx, yy)) {
            count++;
            if (countCheck(count)) {
                isWin = true;
                Log.e("==z====","==2==="+count);
                return;
            }
        } else {
            break;
        }
    }

}

//检查斜线
public void checkDuijiao(){
    int count = 1;

    for (int i =1; i <= value/100; i++) {
        if (currentPoint.x+i>value/100||currentPoint.y+i>value/100){
            break;
        }
        if (equal(currentPoint.x+i,currentPoint.y+i)){
            count++;
            countCheck(count);
            if (countCheck(count)){
                isWin = true;
                Log.e("==z====","===3=="+count);
                return;
            }
        }else {
            break;
        }
    }

    for (int i = 1; i<=value/100 ;i++) {
        if (currentPoint.x-i>value/100||currentPoint.y-i>value/100){
            break;
        }
        if (equal(currentPoint.x-i,currentPoint.y-i)){
            count++;
            if (countCheck(count)){
                isWin = true;
                Log.e("==z====","==4==="+count);
                return;
            }
        }else {
            break;
        }
    }
}

public void chekZhengXianxian(){
    int count = 1;
    int mine = Math.min(currentPoint.x,currentPoint.y);
    for (int i = 1; i < value/100; i++) {
        if (currentPoint.x+i>value/100||currentPoint.y-i<0){
            break;
        }
        if (equal(currentPoint.x+i,currentPoint.y-i)){
            count++;
            countCheck(count);
            if (countCheck(count)){
                isWin = true;
                Log.e("==z====","===5=="+count);
                return;
            }
        }else {
            break;
        }
    }

    for (int i = 1; i >=0; i++) {
        if (currentPoint.x+i>value/100||currentPoint.y-i<0){
            break;
        }
        if (equal(currentPoint.x-i,currentPoint.y+i)){
            count++;
            if (countCheck(count)){
                isWin = true;
                Log.e("==z====","===6=="+count);
                return;
            }
        }else {
            break;
        }
    }
}

其中的equal()方法和countChek()方法是判断点是否存在和点的数量是否已经达到5个。由于字数限制,我就不贴出来了。项地址https://github.com/yzzAndroid/5ZiQiPlay。好啦,这样下来我们就完成了五子棋的简单实现,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值