博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
五子棋--自定义控件
阅读量:6999 次
发布时间:2019-06-27

本文共 12352 字,大约阅读时间需要 41 分钟。

package com.example.administrator.viewapp;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Point;import android.os.Bundle;import android.os.Parcelable;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.Toast;import java.util.ArrayList;/** * Created by Zyh on 2016/11/18. */public class WuZiPanel extends View {    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        //系统传递的参数widthMeasureSpec和heightMeasureSpec,我们可以根据这两个参数获取当前控件的宽高        //首先获取当前的大小        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        //我们画正方形需要去宽和高中的最小值        int width = Math.min(widthSize, heightSize);        //然后将测量的结果设置给系统,这个方法是最终设置自定义view大小的方法        setMeasuredDimension(width, width);//        Log.d("系统给我们的宽度-------------->", "" + width);//        Log.d("系统给我们的宽度(转换后)---->", widthSize+"----" + heightSize);        //初始化棋盘宽度和线的间距,需要在setMeasureDimsion之后进行    }    //在onMeasure中调用setMeasuredDimension方法之后,接下来系统会执行onSizeChanged方法    //所以初始化棋盘宽度和线的间距要在onSizeChanged中进行    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        Log.d("new-----------",w+"----"+h);        Log.d("old-----------",oldw+"---"+oldh);        mPanelWidth = w;        mLineHeight = w * 1.0f / MAX_LIME;//首先将宽度转换成float类型        //规定旗子的宽高        int width = (int) (mLineHeight * 3 / 4);        //按比例重新设置宽高        mWhitePiece = Bitmap.createScaledBitmap(mWhitePiece, width, width, false);        mBlackPiece = Bitmap.createScaledBitmap(mBlackPiece, width, width, false);    }    //初始化画笔,    private Paint mPaint = new Paint();    //横线竖线的数量,    private static final int MAX_LIME = 12;    //棋盘的宽度,和高度    private int mPanelWidth;    //线和线之间的间距    private float mLineHeight;    //记录白棋和黑棋的落子位置    private ArrayList
mWhiteArry = new ArrayList<>(); private ArrayList
mBlackArray = new ArrayList<>(); private boolean mIsWhite = true;//判断目前谁走 //系统会默认调用两个参数的构造方法 public WuZiPanel(Context context, AttributeSet attrs) { super(context, attrs);// 0X--代表16进制的数值的写法前缀 setBackgroundColor(0x66ff0000); mPaint.setStrokeWidth(2);//设置画笔的宽度 mPaint.setTextSize(18); inte(); } private void inte() { mPaint.setColor(0xaa000000); mPaint.setStyle(Paint.Style.STROKE); //设置划一条线 mWhitePiece = BitmapFactory.decodeResource(getResources(), R.mipmap.baizi); mBlackPiece = BitmapFactory.decodeResource(getResources(), R.mipmap.heizi); } /** * onTouchEvent内有四个返回值:true,false,和super.onTouchEvent(event) * true:表示拦截此次事件,不再交给其他方法使用 * false:表示对此次事件不感兴趣,让系统分发给其他的方法 * * @param event * @return */ @Override public boolean onTouchEvent(MotionEvent event) { //游戏已结束那么点击事件就不关心了 if (misGameOver){ return false; } //MotionEvent.ACTION_DOWN--指鼠标点下的事件 //MotionEvent.ACTION_UP---指鼠标抬起的事件 if (event.getAction() == MotionEvent.ACTION_UP) {// Toast.makeText(getContext(), "鼠标抬起事件", Toast.LENGTH_SHORT).show(); int x = (int) event.getX(); int y = (int) event.getY(); Point p = new Point((int) (x / mLineHeight), (int) (y / mLineHeight)); //表示不能重复落子,那么此次的点击事件我们交给系统,我们不做任何的处理 if (mWhiteArry.contains(p) || mBlackArray.contains(p)) { return false; } //如果正确落子,记录当前的落子的位置,并将它加入黑白集合当中 mCurPoint=p;// Toast.makeText(getContext(), (int) (y / mLineHeight) + "当前交叉点的坐标" + (int) (x / mLineHeight), Toast.LENGTH_SHORT).show(); //判断该谁走 if (mIsWhite) { mWhiteArry.add(new Point((int) (x / mLineHeight), (int) (y / mLineHeight))); mIsWhite = false; } else { mBlackArray.add(new Point((int) (x / mLineHeight), (int) (y / mLineHeight))); mIsWhite = true; }// Toast.makeText(getContext(), x + "---" + y, Toast.LENGTH_SHORT).show(); //记录下点击的位置,请求重新绘制界面,重新调用onDraw方法 invalidate();//作用重新调用onDraw postInvalidate();//请求在非UI线程中重绘 return true;//这里代表我们已经处理过点击事件不需要去返回给系统 } //我们必须首先将点击下的动作拦截下来才能接下来拦截抬起的动作 else if (event.getAction() == MotionEvent.ACTION_DOWN) {// Toast.makeText(getContext(), "鼠标抬起事件", Toast.LENGTH_SHORT).show(); return true; } return super.onTouchEvent(event); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); /**canvas---画布,系统提供 canvas.drawLine(0,0,300,300,mPaint);//画一条线:参数起始的坐标和终止的坐标以及画笔 canvas.drawCircle(150,150,40,mPaint);//画圆,起始坐标指定的是圆心的坐标 canvas.drawText("我的世界",150,150,mPaint);//写字,参数说明:字体,起始坐标,画笔 canvas.drawRect(10,10,200,200,mPaint);//画矩形 画Bitmap, canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher),0,0,mPaint); */ drawBoard(canvas); drawPiece(canvas); //每一次落子之后都要进行胜负判断 checkGameIsOver(); } private boolean misGameOver=false; private boolean misWhiteWinner=false; private void checkGameIsOver() { boolean isBlackWin=false; boolean isWhiteWin=false; if (mIsWhite){ isBlackWin=checkFiveInLine(mBlackArray); }else { isWhiteWin=checkFiveInLine(mWhiteArry); } if (isBlackWin||isWhiteWin){ //只要有一个胜利,那么游戏就结束 misGameOver=true; misWhiteWinner=isWhiteWin; //写一个监听的接口,将胜负发送到对应的activity中处理 //问号在这里表示判断的 String str=misWhiteWinner?"白棋胜利":"黑棋胜利"; Toast.makeText(getContext(),str, Toast.LENGTH_SHORT).show(); } } private Point mCurPoint; private boolean checkFiveInLine(ArrayList
mArry) { //如果落下的是白子,mIsWhite是false,如果落下的是黑子,那么mIsWhite是true// if ((!mIsWhite&&isWhite)||(mIsWhite&&!isWhite)){// //mCurPoint白棋+白棋mArray或者mCurPoint黑棋+黑棋mArray// //符合这两种情况接下来往下判断,否则跳出// }else {// return false;// } //如果当前位置旗子的位置不为空,判断他的四个方向是否满足胜利条件 if (mCurPoint!=null){// Toast.makeText(getContext(),x+""+y, Toast.LENGTH_SHORT).show(); if (checkHorIsFive(mArry,mCurPoint)) return true; if (checkVerIsFive(mArry,mCurPoint)){ return true; } if (checkRightAngileIsFive(mArry,mCurPoint)){ return true; } if (checkLelfeAngileIsFive(mArry,mCurPoint)){ return true; } } return false; } private boolean checkHorIsFive(ArrayList
mArry,Point mPoint) { //首先判断横向是否凑齐五个子 第二次遍历向右判断 int x=mCurPoint.x; int y=mCurPoint.y; int count=1; boolean isFirstBreak=true; boolean isSecondBreak=true; for (int i=1;i<5;i++){ if (isFirstBreak){ if (mArry.contains(new Point(x-i,y))){ count++; }else { //向右判断 isFirstBreak=false; } } //如果是true的话,就代表当前位置旗子右边有相同的子,count加1 if (isSecondBreak){ if (mArry.contains(new Point(x+i,y))){ count++; }else { //向右判断 isSecondBreak=false; } } //如果已经达到5颗子,跳出循环 } if(count==5){ return true; }else { return false; } } private boolean checkVerIsFive(ArrayList
mArry,Point mPoint) { //首先判断横向是否凑齐五个子 第二次遍历向右判断 int x=mCurPoint.x; int y=mCurPoint.y; int count=1; boolean isFirstBreak=true; boolean isSecondBreak=true; for (int i=1;i<5;i++){ if (isFirstBreak){ if (mArry.contains(new Point(x,y-i))){ count++; }else { //向右判断 isFirstBreak=false; } } //如果是true的话,就代表当前位置旗子右边有相同的子,count加1 if (isSecondBreak){ if (mArry.contains(new Point(x,y+i))){ count++; }else { //向右判断 isSecondBreak=false; } } //如果已经达到5颗子,跳出循环 } if(count==5){ return true; }else { return false; } } private boolean checkRightAngileIsFive(ArrayList
mArry,Point mPoint) { //首先判断横向是否凑齐五个子 第二次遍历向右判断 int x=mCurPoint.x; int y=mCurPoint.y; int count=1; boolean isFirstBreak=true; boolean isSecondBreak=true; for (int i=1;i<5;i++){ if (isFirstBreak){ if (mArry.contains(new Point(x-i,y-i))){ count++; }else { //向右判断 isFirstBreak=false; } } //如果是true的话,就代表当前位置旗子右边有相同的子,count加1 if (isSecondBreak){ if (mArry.contains(new Point(x+i,y+i))){ count++; }else { //向右判断 isSecondBreak=false; } } //如果已经达到5颗子,跳出循环 } if(count==5){ return true; }else { return false; } } private boolean checkLelfeAngileIsFive(ArrayList
mArry,Point mPoint) { //首先判断横向是否凑齐五个子 第二次遍历向右判断 int x=mCurPoint.x; int y=mCurPoint.y; int count=1; boolean isFirstBreak=true; boolean isSecondBreak=true; for (int i=1;i<5;i++){ if (isFirstBreak){ if (mArry.contains(new Point(x-i,y+i))){ count++; }else { //向右判断 isFirstBreak=false; } } //如果是true的话,就代表当前位置旗子右边有相同的子,count加1 if (isSecondBreak){ if (mArry.contains(new Point(x+i,y-i))){ count++; }else { //向右判断 isSecondBreak=false; } } //如果已经达到5颗子,跳出循环 } if(count==5){ return true; }else { return false; } } private void drawPiece(Canvas canvas) { //画旗子的方法 for (int i = 0; i < mWhiteArry.size(); i++) { Point point = mWhiteArry.get(i); float x = (float) ((point.x + 1.0 / 8) * mLineHeight); float y = (float) ((point.y + 1.0 / 8) * mLineHeight); canvas.drawBitmap(mWhitePiece, x, y, null); } for (int i = 0; i < mBlackArray.size(); i++) { Point point = mBlackArray.get(i); float x = (float) ((point.x + 1.0 / 8) * mLineHeight); float y = (float) ((point.y + 1.0 / 8) * mLineHeight); canvas.drawBitmap(mBlackPiece, x, y, null); } } private Bitmap mWhitePiece; private Bitmap mBlackPiece; private void drawBoard(Canvas canvas) { int w = mPanelWidth; float lineHeight = mLineHeight; for (int i = 0; i < MAX_LIME; i++) { int startX = (int) (lineHeight / 2); int endX = w - startX; int Y = (int) ((0.5 + i) * lineHeight); canvas.drawLine(startX, Y, endX, Y, mPaint); } for (int i = 0; i < MAX_LIME; i++) { int starY = (int) (lineHeight / 2); int X = (int) ((int) (lineHeight / 2) + i * lineHeight); int endY = (int) (w - lineHeight / 2); canvas.drawLine(X, starY, X, endY, mPaint); } } /** * 状态的保存和恢复, * @return */private static final String INSTANCE="INSTANCE"; private static final String INSTANCE_mWhiteArry="mWhiteArry"; private static final String INSTANCE_mBlackArray="mBlackArray"; private static final String INSTANCE_misGameOver="misGameOver"; private static final String INSTANCE_mIsWhite="mIsWhite"; @Override protected Parcelable onSaveInstanceState() { Bundle bundle=new Bundle(); bundle.putParcelableArrayList(INSTANCE_mWhiteArry,mWhiteArry); bundle.putParcelableArrayList(INSTANCE_mBlackArray,mBlackArray); bundle.putBoolean(INSTANCE_misGameOver,misGameOver); bundle.putBoolean(INSTANCE_mIsWhite,mIsWhite); bundle.putParcelable(INSTANCE,super.onSaveInstanceState()); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { //如果是bundle类型就表明我们传递的有值,屏幕发生旋转或者activity强制被杀死,保存过信息 if (state instanceof Bundle){ Bundle bundle= (Bundle) state; mIsWhite=bundle.getBoolean(INSTANCE_mIsWhite,false); misGameOver=bundle.getBoolean(INSTANCE_misGameOver,false); mBlackArray=bundle.getParcelableArrayList(INSTANCE_mBlackArray); mWhiteArry=bundle.getParcelableArrayList(INSTANCE_mWhiteArry); super.onRestoreInstanceState(bundle.getParcelable(INSTANCE)); return; } super.onRestoreInstanceState(state); }}

 

转载于:https://www.cnblogs.com/zhaiyaohua/p/6088192.html

你可能感兴趣的文章
存储的IOPS
查看>>
操作系统位数
查看>>
JQuery学习系列(一)简介
查看>>
centos 6.8 安装php5.5,php5.6,php7
查看>>
我的友情链接
查看>>
Hyper-V之01 恢复Hyper-V管理界面中误删除的虚拟机
查看>>
快捷创建H-v虚拟机
查看>>
装了百度卫士的烦恼
查看>>
Android开发:又是Menu
查看>>
mysql创建定时任务
查看>>
练习题3
查看>>
找寻下一波浪潮
查看>>
【linux网络配置】虚拟机与宿主机可以互相ping通,但是外网不能
查看>>
牛顿方法(Newton's Method)
查看>>
淘宝tfs配置
查看>>
漫谈shell脚本
查看>>
passwd shadow文件说明
查看>>
aix 存储管理
查看>>
TCP会绕程序
查看>>
Rsync+inotify实时同步笔记
查看>>