您的位置:首页 > 其它

慕课上学习的五子棋

2016-05-08 14:54 387 查看
没有什么可讲的,我的注释写的很细了,核心的就是自定义的控件这个很重要的,整个类继承的VIew。

整个思想:

1、就是首先确定自定义控件的大小,我们用的是覆写onMeasure()方法确定大小:

/***
* 用于测量绘制  控制其子控件在父类中所占位置的大小  (继承View) 测量类
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
/***
* 这个模式分为三种
* AT_MOST(这个子控件可以制定大小,常量值是-2147483648)
* EXACTLY (这个子控件根据父类进行调整,最大就是父类的大小,常量值是1073741824)
* UNSPECIFIED (这个子控件是任意大小与父类无关,常量值是0)
*/

Log.i(TAG, "widthSize—" + widthSize);
Log.i(TAG, "widthMode—" + widthMode);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
Log.i(TAG, "heightSize—" + heightSize);
Log.i(TAG, "heightMode—" + heightMode);
int width = Math.min(widthSize, heightSize);
Log.i(TAG, "—" + width);
/*
分辨率:
widthSize—1080
widthMode—1073741824   可以确定下来是子空间最大是父类布局的大小
heightSize—1920
heightMode—1073741824
—1080*/
Log.i(TAG, "" + MeasureSpec.UNSPECIFIED);
Log.i(TAG, "" + MeasureSpec.AT_MOST);
Log.i(TAG, "" + MeasureSpec.EXACTLY);

if (widthMode == MeasureSpec.UNSPECIFIED) {
width = heightSize;
Log.i(TAG, "我不会被运行到1");
} else if (heightMode == MeasureSpec.UNSPECIFIED) {
width = widthSize;
Log.i(TAG, "我不会被运行到2");
}
setMeasuredDimension(width, width);//设置子控件的大小 该方法必须要在onMeasure调用
}


2、初始化行高行宽,不同的设备屏幕尺寸不同为了合理使用的都是比例计算,覆写的onSizeChanged。

/***
* 当屏幕改变时进行调用运行
*
* @param w
* @param h
* @param oldw
* @param oldh
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Log.i(TAG, "w" + w);//1080
mPanelWidth = w;
mLineHeight = mPanelWidth * 1.0f / MAX_LINE;
//确定行高宽  将整个控件的宽平均分成10份,得出一份的宽度,因为是正方形所以也是高度 1080.0/10 = 108.0

//改变棋子的尺寸
int pieceWidth = (int) (mLineHeight * reatioPieceOfLineHeight);
//确定棋子的高款为一个单位的高度宽度的3/4 108.0*3/4 = 81.0
mWhitePiece = Bitmap.createScaledBitmap(mWhitePiece, pieceWidth, pieceWidth, false);
Log.i(TAG, "棋子的宽" + mWhitePiece.getWidth());//81.0
mBlackPiece = Bitmap.createScaledBitmap(mBlackPiece, pieceWidth, pieceWidth, false);
}




3、绘制棋盘和棋子,当然覆写onDraw方法里了,在这个方法还要做一个判断胜利的监听。

/***
* 绘制棋盘
*
* @param canvas
*/
private void drawBoard(Canvas canvas) {
int w = mPanelWidth;//自定义view的宽度  1080
float lineHeight = mLineHeight;//行高 108.0
for (int i = 0; i < MAX_LINE; i++) {//绘制线
int startX = (int) (lineHeight / 2);//54
int endX = (int) (w - lineHeight / 2);//1026
int y = (int) ((0.5 + i) * lineHeight);//y与行高的关系
canvas.drawLine(startX, y, endX, y, mPaint);//绘制横线
canvas.drawLine(y, startX, y, endX, mPaint);//绘制竖线
}
}


/***
* 绘制棋子
*
* @param canvas
*/
private void drawPieces(Canvas canvas) {
for (int i = 0, n = mWhiteArray.size(); i < n; i++) {
Point whitePoint = mWhiteArray.get(i);
Log.i(TAG, "whitePoint" + whitePoint);
//drawBitmap(Bitmap bitmap, float left, float top, Paint paint)
canvas.drawBitmap(mWhitePiece, (whitePoint.x + (1 - reatioPieceOfLineHeight) / 2) * mLineHeight,//  3.0/4  -->  1.0/4  -->  1.0/8 -->
(whitePoint.y + (1 - reatioPieceOfLineHeight) / 2) * mLineHeight, null);
}

for (int i = 0, n = mBlackArray.size(); i < n; i++) {
Point blackPoint = mBlackArray.get(i);
//drawBitmap(Bitmap bitmap, float left, float top, Paint paint)
canvas.drawBitmap(mBlackPiece, (blackPoint.x + (1 - reatioPieceOfLineHeight) / 2) * mLineHeight,//  3.0/4  -->  1.0/4  -->  1.0/8 -->
(blackPoint.y + (1 - reatioPieceOfLineHeight) / 2) * mLineHeight, null);
}
}


/***
* 游戏胜利主监听
*/
private void checkGameOver() {
boolean whiteWin = checkFiveInLine(mWhiteArray);
boolean blackWin = checkFiveInLine(mBlackArray);
if (whiteWin || blackWin) {
mIsGemeoVer = true;
mIsWhiteWinner = whiteWin;
String text = mIsWhiteWinner ? "白棋胜利" : "黑棋胜利";
Toast.makeText(getContext(), text, Toast.LENGTH_SHORT).show();
}
}


Ps:自己画的两张草图



3、还有就是几个输赢逻辑判断(横线上连着五颗,竖着连着五颗,左斜着连着五颗,右斜这五颗)

//横着
private boolean checkWinHorizontal(int x, int y, List<Point> points) {
//横着左
int count = 1;
for (int i = 1; i < MAX_COUNT_IN_LINE; i++) {
if (points.contains(new Point(x - i, y))) {
count++;
} else {
break;
}
}
if (count == MAX_COUNT_IN_LINE) return true;

//横着右
for (int i = 1; i < MAX_COUNT_IN_LINE; i++) {
if (points.contains(new Point(x + i, y))) {
count++;
} else {
break;
}
}
if (count == MAX_COUNT_IN_LINE) return true;
return false;
}


4、覆写一个onTouchEvent对“下棋进行操作”,其实主要的还就是在数组列中添加坐标。

public boolean onTouchEvent(MotionEvent event) {
if (mIsGemeoVer) return false;//如果游戏结束,不能再次下子。
int action = event.getAction();
if (action == MotionEvent.ACTION_UP) {
int x = (int) event.getX();
int y = (int) event.getY();
//Point point = new Point(x, y);//确定的点
Point point = getValidPoint(x, y);//不能重复下 ,不能下到一个点,不能仅仅根据坐标进行下棋所以有合理的点
if (mWhiteArray.contains(point) || mBlackArray.contains(point)) {
return false;
}
if (mIsWhite) {
mWhiteArray.add(point);
} else {
mBlackArray.add(point);
}
invalidate();//刷新View
mIsWhite = !mIsWhite;//改变值
return true;
}
return true;
}


5、作者还精心考虑到了关于资源文件配置出现变化,导致重构,比如你下着下着,然后突然横屏了,View就会重构,导致棋子清空。

/***
* 防止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, mIsGemeoVer);
bundle.putParcelableArrayList(INSTANCE_WHITE_ARRAY, mWhiteArray);
bundle.putParcelableArrayList(INSTANCE_BLACK_ARRAY, mBlackArray);

return bundle;
}

@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
Bundle bundle = (Bundle) state;

mIsGemeoVer = bundle.getBoolean(INSTANCE_GAME_OVER);
mWhiteArray = bundle.getParcelableArrayList(INSTANCE_WHITE_ARRAY);
mBlackArray = bundle.getParcelableArrayList(INSTANCE_BLACK_ARRAY);

super.onRestoreInstanceState(bundle.getParcelable(INSTANCE));
return;
}
super.onRestoreInstanceState(state);
}


6、再来一局进行的方法,我即使贴出来,但是不看源码,你是不知道这是怎么来的。

public void agin() {
mWhiteArray.clear();
mBlackArray.clear();
mIsGemeoVer = false;
mIsWhiteWinner = false;
invalidate();
}


MainActivity中进行重来一局的监听。

wuziqiPanel = (WuziqiPanel) findViewById(R.id.wuziqipanel);
btnAginGame = (Button) findViewById(R.id.buttonAgin);
btnAginGame.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
wuziqiPanel.agin();
}
});


效果:



源码:http://download.csdn.net/detail/csdnhejingzhou/9513588
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: