慕课上学习的五子棋
2016-05-08 14:54
387 查看
没有什么可讲的,我的注释写的很细了,核心的就是自定义的控件这个很重要的,整个类继承的VIew。
整个思想:
Ps:自己画的两张草图
![](http://img.blog.csdn.net/20160511164656059?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
MainActivity中进行重来一局的监听。
效果:
![](http://img.blog.csdn.net/20160508144500182?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
源码:http://download.csdn.net/detail/csdnhejingzhou/9513588
整个思想:
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
相关文章推荐
- CPU的内部架构和工作原理
- CentOS6.5安装RHadoop
- C#属性
- DirectX9 渲染设置
- Xorshift RNGs生成随机数
- 获取HTTP信息
- C++制作俄罗斯方块
- C语言中const的用法
- chrome浏览器广告屏蔽插件adblock下载地址
- Android LayoutInflater详解
- Phoenix Salted Table
- Fabricate equation(dfs + 模拟)
- 内存管理---slab机制 销毁对象
- android项目之通讯录数据库
- HDU 2732 —— Leapin' Lizards
- 淘宝购物倒计时
- C++第五次实验——数组分离
- C#索引器
- Android内存泄漏分享
- 图片中的exif数据