五子棋的实现“慕课网五子连珠的笔记”

版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎留言。 https://blog.csdn.net/qq_15046309/article/details/82989293

慕课网的视频

首先创建了一个类,这个类继承了View,去实现这个类的构造方法,实现其两个参数的构造方法,老师建议自己写的过程中对这些构造方法都进行实现。

在布局文件中对这个类进行使用,注意是包名。宽高都是match_parent;double-xxhdpi的文件夹里面可以放一些尺寸比较大的图片。

在View中设置了一个background,setBackground(#0x44ff0000)透明的红色,目的是为了运行时具体看到VIew所占据的一些大小。

在布局文件中丢掉了padding。

再累中先去定义它的一个测量方法onMeasure(),首先考虑一个具体的使用情况。为什么layout_width不支持wrap_content?因为这个view内部的绘制依赖与外部的尺寸,但是如果外部的尺寸再变的话就不知道具体得了。

初始化测绘:

在onMeasure方法中拿到宽度的大小,通过一个辅助类叫做MeasureSpec.getSize(WidthMeasureSpec);再去拿宽度的一个Mode

int widthSize=MeasureSpec.getSize(widthMeasureSpec);
int widthMode=MeasureSpec.getMode(widthMeasureSpec);

同理拿到height的size和mode。

用setMeasureDimension来决定宽和高,在mathc_parent的情况下, 某些时候和SCROLLVIEW去嵌套的话机会发生些奇怪的问题,所以去做一些判断,

        if (widthMode==MeasureSpec.UNSPECIFIED)
        {
            width=heightSize;
        }
        else if (heightMode==MeasureSpec.UNSPECIFIED)
        {
            width=widthSize;
        }

接下来我们开始绘制棋盘:
声明两个成员变量(软件开发的技巧)mPanelidth(宽度),mLineHeight(行高),可以把这些变量在onSIzeChanged里面进行声明,这个方法是当宽高发生改变时会回调,那么我们就可以在里面对跟尺寸相关的成员变量进行赋值。

有了行高后可以进行绘制棋盘了,绘制操作肯定是在OnDraw里面(重写OnDraw),绘制需要一个Point,那么声明一个成员变量Point

 private Paint mPaint=new Paint();

在构造函数中对Paint进行初始化,创建了一个init方法,

  mPaint.setColor(0x88000000);
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setStyle( Paint.Style.STROKE);

在OnDraw里面编写了一个方法专门用来绘制棋盘上drawBoard,把参数canvas传进去。

棋盘的绘制:

棋子是会下到边界的交叉点上面的,那么上下左右的线的距离view的高度有半个lineHeight的高度【中间有9个lineHeight,上下共有0.5个】左右和上下的情况是一致的。

在绘制棋盘的过程中,需要mPanelWidth(棋盘的宽度)成员变量先用局部变量去替代(技巧)。

 private void drawBoard(Canvas canvas) {
        int w=mPanelWidth;//棋盘的宽度
        float lineHeight=mLineHeight;
        for(int i=0;i<MAX_LINE;i++)
        {
                int startX=(int)(lineHeight/2);
                int endX=(int)(w-lineHeight/2);//横坐标的起点和终点
                int y=(int) ((0.5+i)*lineHeight);
                canvas.drawLine(startX,y,endX,y,mPaint);//横线都画好了。
                canvas.drawLine(y,startX,y,endX,mPaint);//纵线都画好了
        }
    }

棋子的图片:

先引入棋子的图片:private Bitmap mWhitePiece;private Bitmap mBlackPiece;在init()里面对棋子进行初始化,

  mWhitePiece=BitmapFactory.decodeResource(getResources(),R.drawable.stone_w2);
  mBlackPiece=BitmapFactory.decodeResource(getResources(),R.drawable.stone_b1);

行高,也决定了棋子的大小,因此不可以把棋子弄成一些固定值,也不能任由图片去决定棋子的大小。引入一个比例,让棋子的大小是我们行高的3/4

    private float ratioPieceOfLineHeight=3*1.0f/4;

在跟尺寸相关的在onSizeChange里面进行编写

     mWhitePiece=Bitmap.createScaledBitmap(mWhitePiece,pieceWidth,pieceWidth,false);
     mBlackPiece=Bitmap.createScaledBitmap(mBlackPiece,pieceWidth,pieceWidth,false);

这样棋子的大小就和行高等限制条件有了关系。

onTouchEvent方法:

点击事件,说明这个VIew可以消化掉Touch的这个手势,

int action=event.getAction();

   if (action==MotionEvent.ACTION_UP)
        {
            //存储用户点击的坐标。
            int x=(int) event.getX();
            int y=(int) event.getY();
            Point p=getValidPoint(x,y);
            if (mWhiteArray.contains(p)||mBlackArray.contains(p))
            {
                return false;
            }
            if (mIswhite)
            {
                mWhiteArray.add(p);
            }
            else
            {
                mBlackArray.add(p);
            }
            invalidate();//请求重绘
            mIswhite=!mIswhite;
            return true;//表明view对这个事件感兴趣
        }

Touch方法只是去获得用户点击的坐标。

解决用户点击坐标的问题,用户点的位置和我们的坐标是对不上号的,因此需要进行转化:

    private Point getValidPoint(int x, int y) {
        return new Point((int)(x/mLineHeight),(int)(y/mLineHeight));
    }

注意Point的equals方法。

绘制棋子:这里面有一些比例的问题,建议搞明白,这个方法使用是在onDraw里面。

private void drawPieces(Canvas canvas) {
        for (int i=0,n=mWhiteArray.size();i<n;i++)
        {
            Point whitePoint=mWhiteArray.get(i);
            canvas.drawBitmap(mWhitePiece,
                    (whitePoint.x+(1-ratioPieceOfLineHeight)/2)*mLineHeight,
                    (whitePoint.y+(1-ratioPieceOfLineHeight)/2)*mLineHeight,null
            );//3分21
        }

逻辑判断,和平台相关性不大,也很简单。我略掉了

View的存储与恢复: 注意这是存储

 private static final    String INSTANCE="instance";
    private static final    String INSTANCE_GAME_OVER="instance_game_over";
    private static final    String INSTANCE_WHITE_ARRAY="instance_white_array";
    private static final    String INSTANCE_BLACK_ARRAY="instance_black_array";

    @Override
    protected Parcelable onSaveInstanceState() {
        Bundle bundle=new Bundle();
        bundle.putParcelable(INSTANCE,super.onSaveInstanceState());
        bundle.putBoolean(INSTANCE_GAME_OVER,isGameOver);

        return super.onSaveInstanceState();
    }

恢复的相关代码就不在这里写了,这属于尾声了。如果没有恢复,那么八九不离十是因为没有加上资源的ID。

大体上就是这些相关的代码,这个项目开拓了棋类游戏的思路。目前已经解决了蓝牙问题,绘制问题,剩下的问题大部分都与平台的关系不大了,加油!

猜你喜欢

转载自blog.csdn.net/qq_15046309/article/details/82989293