自定义控件--五子棋
来源:互联网 发布:简单效果图制作软件 编辑:程序博客网 时间:2024/05/19 17:07
1.先测量自定义View自身的宽高,然后保存
2.根据View的确定宽高来画棋盘上面的格子
3.与用户交互的时候落子,根据确定的宽高来确定黑白棋子的宽高
4.绘制棋子
5.处理5颗棋子连成线的逻辑
6.自定义View保存状态的标准写法
7.再来一局实现
----------------------------------------------------
效果图
布局xml
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <com.docwei.wuziqidemo.WuZiQiView android:id="@+id/wuziqi" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:onClick="restart" android:text="再来一局"/></RelativeLayout>
代码第一步:先测量自定义View自身的宽高,然后保存
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //获取在布局文件里面精确测量(match_parent或者具体dp值)的宽高 int widthSize=MeasureSpec.getSize(widthMeasureSpec); int widthMode=MeasureSpec.getMode(widthMeasureSpec); int heightSize=MeasureSpec.getSize(heightMeasureSpec); int heightMode=MeasureSpec.getMode(heightMeasureSpec); //如将该自定义控件放在其他的ViewGroup里面,尤其是ScrollView可能会出现测量模式不是精确测量 if(widthMode==MeasureSpec.UNSPECIFIED){ widthSize=heightSize; }else if(heightMode==MeasureSpec.UNSPECIFIED){ heightSize=widthSize; } //要保证我们的棋盘是一个正方形,所以选取小的作为该正方形的边长 int width=Math.min(widthSize,heightSize); setMeasuredDimension(width,width);//保存自身的宽高 }
代码第二步:根据View的确定宽高来画棋盘上面的格子
代码第三步:.与用户交互的时候落子,根据确定的宽高来确定黑白棋子的宽高
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); panelWidth=w; rawHeight=panelWidth*1.0f/(LINE_MAX);//左右各留一半行高的的空白 //黑白棋子的图片太大也不要紧,这里对图片的显示进行处理 int bitmapWidth= (int) (rawHeight*bitmap2rawHeight); mWhiteBitmap=Bitmap.createScaledBitmap(mWhiteBitmap,bitmapWidth, bitmapWidth,false); mBlackBitmap=Bitmap.createScaledBitmap(mBlackBitmap,bitmapWidth, bitmapWidth,false); }
private void drawGrid(Canvas canvas) { for(int i=0;i<LINE_MAX+1;i++){ float startX=rawHeight/2; float endX=panelWidth-rawHeight/2; float startY=rawHeight/2; float endY=panelWidth-rawHeight/2; canvas.drawLine(startX,startY+i*rawHeight,endX,startY+i*rawHeight,mPaint); canvas.drawLine(startX+i*rawHeight,startY,startX+i*rawHeight,endY,mPaint); } }
代码第四步:绘制棋子
private void drawQiZi(Canvas canvas) { for (int i=0,n=mWhitePoints.size();i<n;i++) { Point point = mWhitePoints.get(i);//里面重写了equals方法 canvas.drawBitmap(mWhiteBitmap,(point.x+(1.0f/2-bitmap2rawHeight*1/2))*rawHeight, (point.y+(1.0f/2-bitmap2rawHeight*1/2))*rawHeight,null); } for(int i=0,n=mBlackPoints.size();i<n;i++) { Point point = mBlackPoints.get(i);//里面重写了equals方法 canvas.drawBitmap(mBlackBitmap,(point.x+(1.0f/2-bitmap2rawHeight*1/2))*rawHeight,(point.y+(1.0f/2-bitmap2rawHeight*1/2))*rawHeight,null); } //遍历每一个点,,这样真的好么 boolean isWhiteWin=check5InLine(mWhitePoints); if(isWhiteWin){ isGameOver=true; Toast.makeText(getContext(),"白棋胜利",Toast.LENGTH_SHORT).show(); } boolean isBlackWin=check5InLine(mBlackPoints); if(isBlackWin){ isGameOver=true; Toast.makeText(getContext(),"黑棋胜利",Toast.LENGTH_SHORT).show(); } }
代码第五步:处理5颗棋子连成线的逻辑
private boolean check5InLine(ArrayList<Point> points) { for(Point point:points){ if(checkHorizatol(point,points)) return true; if(checkVertical(point,points)) return true; if(checkLeftSlant(point,points)) return true; if(chekcRigheSlant(point,points)) return true; } return false; } private boolean chekcRigheSlant(Point CurrentPoint,ArrayList<Point> points) { int count=1;//当前粒是5粒中的1粒 for(int i=1;i<QIZI_IN_LINE;i++){ if(points.contains(new Point(CurrentPoint.x+i,CurrentPoint.y+i))){ count++; }else{ break;//如果不是连续的,立即退出 } } if(count==QIZI_IN_LINE) return true; for(int i=1;i<QIZI_IN_LINE;i++){ if(points.contains(new Point(CurrentPoint.x-i,CurrentPoint.y-i))){ count++; }else{ break;//如果不是连续的,立即退出 } } if(count==QIZI_IN_LINE) return true; return false; } private boolean checkLeftSlant(Point CurrentPoint,ArrayList<Point> points) { int count=1;//当前粒是5粒中的1粒 for(int i=1;i<QIZI_IN_LINE;i++){ if(points.contains(new Point(CurrentPoint.x+i,CurrentPoint.y-i))){ count++; }else{ break;//如果不是连续的,立即退出 } } if(count==QIZI_IN_LINE) return true; for(int i=1;i<QIZI_IN_LINE;i++){ if(points.contains(new Point(CurrentPoint.x-i,CurrentPoint.y+i))){ count++; }else{ break;//如果不是连续的,立即退出 } } if(count==QIZI_IN_LINE) return true; return false; } private boolean checkVertical(Point CurrentPoint,ArrayList<Point> points) { int count=1;//当前粒是5粒中的1粒 for(int i=1;i<QIZI_IN_LINE;i++){ if(points.contains(new Point(CurrentPoint.x,CurrentPoint.y+i))){ count++; }else{ break;//如果不是连续的,立即退出 } } if(count==QIZI_IN_LINE) return true; for(int i=1;i<QIZI_IN_LINE;i++){ if(points.contains(new Point(CurrentPoint.x,CurrentPoint.y-i))){ count++; }else{ break;//如果不是连续的,立即退出 } } if(count==QIZI_IN_LINE) return true; return false; } private boolean checkHorizatol(Point CurrentPoint,ArrayList<Point> points) { int count=1;//当前粒是5粒中的1粒 for(int i=1;i<QIZI_IN_LINE;i++){ if(points.contains(new Point(CurrentPoint.x+i,CurrentPoint.y))){ count++; }else{ break;//如果不是连续的,立即退出 } } if(count==QIZI_IN_LINE) return true; for(int i=1;i<QIZI_IN_LINE;i++){ if(points.contains(new Point(CurrentPoint.x-i,CurrentPoint.y))){ count++; }else{ break;//如果不是连续的,立即退出 } } if(count==QIZI_IN_LINE) return true; return false; } /* private void check5InLine() { //水平的5粒连成线,从当前粒向左或者向右遍历,有5粒在一条线上,就赢了 check5InLine(mWhitePoints); check5InLine(mBlackPoints); }*/
代码第六步:自定义View保存状态的标准写法
//是自定义控件的保存恢复状态的标准写法 @Override protected Parcelable onSaveInstanceState() { Bundle bundle=new Bundle(); bundle.putParcelable("superState",super.onSaveInstanceState()); bundle.putBoolean("isGameOver",isGameOver); bundle.putParcelableArrayList("WhitePoints",mWhitePoints); bundle.putParcelableArrayList("BlackPoints",mBlackPoints); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { if(state instanceof Bundle){ Bundle bundle= (Bundle) state; isGameOver=bundle.getBoolean("isGameOver"); mWhitePoints=bundle.getParcelableArrayList("WhitePoints"); mBlackPoints=bundle.getParcelableArrayList("BlackPoints"); state=bundle.getParcelable("superState"); } super.onRestoreInstanceState(state); }
代码第七步:再来一局实现
//再来一局 public void restart(){ isGameOver=false; mWhitePoints.clear(); mBlackPoints.clear(); invalidate(); }
2 0
- 自定义控件--五子棋
- android 自定义五子棋
- 自定义View之一五子棋
- 五子棋两个控件之一fiveclient
- 自定义View实现五子棋游戏
- 自定义view(二)五子棋
- android自定义View 五子棋小游戏
- 围棋和五子棋控件 v1.6.166 免费
- Android 开发 -------- 自定义View 画 五子棋
- 自定义View+五子棋的简单实现
- Android之自定义view的五子棋游戏
- android自定义View之五子棋小游戏
- Android自定义View实现五子棋小游戏
- 通过自定义view来做一个五子棋
- 五子棋
- 五子棋
- 五子棋
- 五子棋
- MySQL高级配置(二)详细介绍
- 【uoj150】 NOIP2015—运输计划
- 为什么java中的String对象时不可变的
- 鸽子兔子
- PAT:杂项
- 自定义控件--五子棋
- hdu 5877 Weak Pair(树状数组)
- txt导入mysql
- 鸽兔同校
- Flume官方文档翻译之(九)
- 贝叶斯分类算法
- Python爬虫——糗百
- 12. Integer to Roman
- 解决windows server 2008 R2安装到D盘的问题