在这里说一下啊,我的所有文章都是根据看慕课上的视频写出来的,所以都不是原创的,因为能力不够。。。。
今天我在这里记一下,五子棋的编写方法,归根结底还是要到自定义View里面去。
上面是一张我完成过后的截图,要完成这个功能,必不可少的就是自定义控件。在此过程,我最主要的是要学习自定义控件的方法。
1.布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context="com.example.android_wuziqi.MainActivity">
<com.example.android_wuziqi.WuziqiView
android:id="@+id/id_wuziqiView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#44ff"
/>
</LinearLayout>
2.在自定义View当中,测量棋盘的大小
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (widthMode == MeasureSpec.UNSPECIFIED) {
widthSize = heightSize;
} else if (heightMeasureSpec == MeasureSpec.UNSPECIFIED) {
heightSize = widthSize;
}
int width = Math.min(widthSize, heightSize);
setMeasuredDimension(width, width);
}
上面的代码要注意的是:当我们父布局使用ScrollView时,会发现有时候子空间取不到宽或者是高,那是因为子控件的测量模式是UNSPECIFIED,因此在测量的时候,我们要考虑到这个问题。
3.在onSizechanged方法里面取得棋盘上每两条边之间的距离
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mLineHeight = (int) (w * 1.0f / MAX_LINE_COUNT);
int scaleWidth = (int) (mLineHeight * mRadioPieceOfLineHeight);
mBlackPiece = Bitmap.createScaledBitmap(mBlackPiece, scaleWidth, scaleWidth, false);
mWhitePiece = Bitmap.createScaledBitmap(mWhitePiece, scaleWidth, scaleWidth, false);
}
Bitmap.createScaledBitmap主要是用来缩放bitmap的,因为棋子的大小由棋盘的边之间的距离来决定。
4.绘制棋盘
private void drawBorad(Canvas canvas) {
int width = getMeasuredWidth();
for (int i = 0; i < MAX_LINE_COUNT; i++) {
float startX = (mLineHeight * 1.0f / 2);
float startY = (mLineHeight * 1.0f / 2) + mLineHeight * i;
float endX = (width - mLineHeight * 1.0f / 2);
float endY = mLineHeight / 2 + mLineHeight * i;
canvas.drawLine(startX, startY, endX, endY, mPaintLine);
canvas.drawLine(startY, startX, endY, endX, mPaintLine);
}
}
5.设置onTouchEvent事件
在设置之前,先考虑一下,下棋的事件是定在DOWN还是UP里面,具体原因我也不想去解释,我在这里设置UP里面,因为教学视频里面也是这样的,而我觉得挺不错的。
public boolean onTouchEvent(MotionEvent event) {
if(mIsGameOver)
{
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_UP: {
int x = (int) event.getX();
int y = (int) event.getY();
Point point = getLeglaPoint(x, y);
if (mBlackArray.contains(point) || mWhiteArray.contains(point)) {
return false;
}
if (mIsWhite) {
mWhiteArray.add(point);
} else {
mBlackArray.add(point);
}
invalidate();
mIsWhite = !mIsWhite;
return true;
}
}
return true;
}
private Point getLeglaPoint(int x, int y) {
return new Point(x / mLineHeight, y / mLineHeight);
}
这里注意一点的就是:当我们在某一个地方已经下了棋子了,如果再次点击一次的话,不能将前面的棋子覆盖了。因此我们在这里必须有一个判断,那就是我们点击的地方的是否有棋子。这里不是直接通过x和y来判断的,因为每次点击同一个地方,x和y有一定的偏差。我们这里使用有x和y来整除边之间的距离,这样即使有偏差,也是被忽略的。
6.画棋子
private void drawPiece(Canvas canvas) {
for (int i = 0; i < mBlackArray.size(); i++) {
Point point = mBlackArray.get(i);
canvas.drawBitmap(mBlackPiece, (point.x + (1 - mRadioPieceOfLineHeight) / 2) * mLineHeight, (point.y + (1 - mRadioPieceOfLineHeight) / 2) * mLineHeight, mPaintBitmap);
}
for (int i = 0; i < mWhiteArray.size(); i++) {
Point point = mWhiteArray.get(i);
canvas.drawBitmap(mWhitePiece, (point.x + (1 - mRadioPieceOfLineHeight) / 2) * mLineHeight, (point.y + (1 - mRadioPieceOfLineHeight) / 2) * mLineHeight, mPaintBitmap);
}
}