绘制棋盘面板:

MainActivity.java
package com.xbmu.wuziqi;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.xbmu.wuziqi.MainActivity"><com.xbmu.wuziqi.WuziqiPanelandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_centerInParent="true" />
</RelativeLayout>

WuziqiPanel.java

package com.xbmu.wuziqi;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;/*** 五子棋面板* Created by Administrator on 2016/5/2 0002.*/
public class WuziqiPanel extends View {private int mPanelWidth;//棋盘宽度private float mLineHeight;//棋盘每行行高private int MAX_LINE = 10;//棋盘最大行数//创建绘画对象private Paint mPaint = new Paint();public WuziqiPanel(Context context, AttributeSet attrs) {super(context, attrs);setBackgroundColor(0x44ff0000);init();}/**初始化画笔属性*/private void init() {mPaint.setColor(0x88000000);//设置颜色为灰色效果mPaint.setAntiAlias(true);mPaint.setDither(true);mPaint.setStyle(Paint.Style.STROKE);}/**测量一个view的大小*/@Overrideprotected 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(widthMeasureSpec);int width = Math.min(widthSize,heightSize);if(widthMode == MeasureSpec.UNSPECIFIED){width = heightSize;}else if(heightMode == MeasureSpec.UNSPECIFIED){width = widthSize;}//设置自身大小setMeasuredDimension(width,width);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mPanelWidth = w;mLineHeight = mPanelWidth*1.0f / MAX_LINE;}/**Draw画出View的显示内容*/@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);drawBoard(canvas);}private void drawBoard(Canvas canvas) {/*** 分析:根据棋盘的效果,我们知道棋子是下在边界的交叉点上的。可得棋盘中间有9个完整的lineHeight,* 上下两边有半个lineHeight,总共10个lineHeight。左右也是。*/int w = mPanelWidth;float lineHeight = mLineHeight;for(int i=0;i<MAX_LINE;i++){int startX = (int) (lineHeight / 2);//起点坐标int endX = (int) (w - lineHeight / 2);//终点坐标int y = (int) ((0.5+i)*lineHeight);canvas.drawLine(startX,y,endX,y,mPaint);canvas.drawLine(y,startX,y,endX,mPaint);}}
}

运行效果:

绘制黑白棋子:

WuziqiPanel.java
package com.xbmu.wuziqi;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.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;import java.util.ArrayList;
import java.util.List;/*** 五子棋面板* Created by Administrator on 2016/5/2 0002.*/
public class WuziqiPanel extends View {private int mPanelWidth;//棋盘宽度private float mLineHeight;//棋盘每行行高private int MAX_LINE = 10;//棋盘最大行数//创建绘画对象private Paint mPaint = new Paint();private Bitmap mWhitePiece;//白色棋子private Bitmap mBlackPiece;//黑色棋子//比例:棋子的大小是行高的3/4;private float ratioPieceOfLineHeight = 3*1.0f / 4;//白棋先手,当前轮到白棋。private boolean mIsWhite = true;private List<Point> mWhiteArray = new ArrayList<>();private List<Point> mBlackArray = new ArrayList<>();public WuziqiPanel(Context context, AttributeSet attrs) {super(context, attrs);setBackgroundColor(0x44ff0000);init();}/**初始化画笔属性*/private void init() {mPaint.setColor(0x88000000);//设置颜色为灰色效果mPaint.setAntiAlias(true);mPaint.setDither(true);mPaint.setStyle(Paint.Style.STROKE);mWhitePiece = BitmapFactory.decodeResource(getResources(),R.drawable.stone_w2);mBlackPiece = BitmapFactory.decodeResource(getResources(),R.drawable.stone_b1);}/**测量一个view的大小*/@Overrideprotected 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(widthMeasureSpec);int width = Math.min(widthSize,heightSize);if(widthMode == MeasureSpec.UNSPECIFIED){width = heightSize;}else if(heightMode == MeasureSpec.UNSPECIFIED){width = widthSize;}//设置自身大小setMeasuredDimension(width,width);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mPanelWidth = w;mLineHeight = mPanelWidth*1.0f / MAX_LINE;int pieceWidth = (int) (mLineHeight * ratioPieceOfLineHeight);//棋子宽度mWhitePiece = Bitmap.createScaledBitmap(mWhitePiece,pieceWidth,pieceWidth,false);mBlackPiece = Bitmap.createScaledBitmap(mBlackPiece,pieceWidth,pieceWidth,false);}@Overridepublic boolean onTouchEvent(MotionEvent event) {int action = event.getAction();if(action == MotionEvent.ACTION_DOWN){int x = (int) event.getX();int y = (int) event.getY();Point p = getValidPoint(x,y);if(mWhiteArray.contains(p) || mBlackArray.contains(p)){return false;}if(mIsWhite){mWhiteArray.add(p);}else{mBlackArray.add(p);}invalidate();//请求重绘mIsWhite = !mIsWhite;return true;}return super.onTouchEvent(event);}private Point getValidPoint(int x, int y) {return new Point((int)(x/mLineHeight) ,(int)(y/mLineHeight));}/**Draw画出View的显示内容*/@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//绘制棋盘drawBoard(canvas);//绘制棋子drawPieces(canvas);}private void drawPieces(Canvas canvas) {for(int i=0,n = mWhiteArray.size(); i< n ;i++){Point whitePoint = mWhiteArray.get(i);canvas.drawBitmap(mWhitePiece,(whitePoint.x+(1-ratioPieceOfLineHeight)/2)*mLineHeight,(whitePoint.y+(1-ratioPieceOfLineHeight)/2)*mLineHeight,null);}for(int i=0,n = mBlackArray.size(); i< n ;i++){Point blackPoint = mBlackArray.get(i);canvas.drawBitmap(mBlackPiece,(blackPoint.x+(1-ratioPieceOfLineHeight)/2)*mLineHeight,(blackPoint.y+(1-ratioPieceOfLineHeight)/2)*mLineHeight,null);}}private void drawBoard(Canvas canvas) {/*** 分析:根据棋盘的效果,我们知道棋子是下在边界的交叉点上的。可得棋盘中间有9个完整的lineHeight,* 上下两边有半个lineHeight,总共10个lineHeight。左右也是。*/int w = mPanelWidth;float lineHeight = mLineHeight;for(int i=0;i<MAX_LINE;i++){int startX = (int) (lineHeight / 2);//起点坐标int endX = (int) (w - lineHeight / 2);//终点坐标int y = (int) ((0.5+i)*lineHeight);canvas.drawLine(startX,y,endX,y,mPaint);canvas.drawLine(y,startX,y,endX,mPaint);}}
}

运行效果:

五子棋业务逻辑判断:

WuziqiPanel.java
package com.xbmu.wuziqi;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.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;import java.util.ArrayList;
import java.util.List;/*** 五子棋面板* Created by Administrator on 2016/5/2 0002.*/
public class WuziqiPanel extends View {private int mPanelWidth;//棋盘宽度private float mLineHeight;//棋盘每行行高private int MAX_LINE = 10;//棋盘最大行数//创建绘画对象private Paint mPaint = new Paint();private Bitmap mWhitePiece;//白色棋子private Bitmap mBlackPiece;//黑色棋子//比例:棋子的大小是行高的3/4;private float ratioPieceOfLineHeight = 3*1.0f / 4;//白棋先手,当前轮到白棋。private boolean mIsWhite = true;private List<Point> mWhiteArray = new ArrayList<>();private List<Point> mBlackArray = new ArrayList<>();private boolean mIsGameOver;private boolean mIsWhiteWinner;private int MAX_COUNT_IN_LINE = 5;public WuziqiPanel(Context context, AttributeSet attrs) {super(context, attrs);setBackgroundColor(0x44ff0000);init();}/**初始化画笔属性*/private void init() {mPaint.setColor(0x88000000);//设置颜色为灰色效果mPaint.setAntiAlias(true);mPaint.setDither(true);mPaint.setStyle(Paint.Style.STROKE);mWhitePiece = BitmapFactory.decodeResource(getResources(),R.drawable.stone_w2);mBlackPiece = BitmapFactory.decodeResource(getResources(),R.drawable.stone_b1);}/**测量一个view的大小*/@Overrideprotected 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(widthMeasureSpec);int width = Math.min(widthSize,heightSize);if(widthMode == MeasureSpec.UNSPECIFIED){width = heightSize;}else if(heightMode == MeasureSpec.UNSPECIFIED){width = widthSize;}//设置自身大小setMeasuredDimension(width,width);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mPanelWidth = w;mLineHeight = mPanelWidth*1.0f / MAX_LINE;int pieceWidth = (int) (mLineHeight * ratioPieceOfLineHeight);//棋子宽度mWhitePiece = Bitmap.createScaledBitmap(mWhitePiece,pieceWidth,pieceWidth,false);mBlackPiece = Bitmap.createScaledBitmap(mBlackPiece,pieceWidth,pieceWidth,false);}@Overridepublic boolean onTouchEvent(MotionEvent event) {int action = event.getAction();if(action == MotionEvent.ACTION_DOWN){int x = (int) event.getX();int y = (int) event.getY();Point p = getValidPoint(x,y);if(mWhiteArray.contains(p) || mBlackArray.contains(p)){return false;}if(mIsWhite){mWhiteArray.add(p);}else{mBlackArray.add(p);}invalidate();//请求重绘mIsWhite = !mIsWhite;return true;}return super.onTouchEvent(event);}private Point getValidPoint(int x, int y) {return new Point((int)(x/mLineHeight) ,(int)(y/mLineHeight));}/**Draw画出View的显示内容*/@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//绘制棋盘drawBoard(canvas);//绘制棋子drawPieces(canvas);//检查游戏结束checkGameOver();}private void checkGameOver() {boolean whiteWin = checkFiveInLine(mWhiteArray);boolean blackWin = checkFiveInLine(mBlackArray);if(whiteWin || blackWin){mIsGameOver = true;mIsWhiteWinner = whiteWin;String text = mIsWhiteWinner ? "白棋胜利":"黑棋胜利";Toast.makeText(getContext(),text,Toast.LENGTH_LONG).show();}}private boolean checkFiveInLine(List<Point> points) {for (Point p : points){int x = p.x;int y = p.y;boolean win = checkHorizontal(x,y,points);if(win) return true;win = checkVertical(x,y,points);if(win) return true;win =checkLeftDiagonal(x,y,points);if(win) return true;win = checkRightDiagonal(x,y,points);if(win) return true;}return false;}/*** 判断x,y位置的棋子,是否横向有相邻的五个一致。* @param x* @param y* @param points* @return*/private boolean checkHorizontal(int x, int y, List<Point> points) {int count = 1;//左for(int i=0;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;}/*** 判断x,y位置的棋子,是否纵向有相邻的五个一致。* @param x* @param y* @param points* @return*/private boolean checkVertical(int x, int y, List<Point> points) {int count = 1;//上for(int i=0;i<MAX_COUNT_IN_LINE;i++){if(points.contains(new Point(x,y-i))){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,y+i))){count++;}else{break;}}if(count==MAX_COUNT_IN_LINE) return true;return  false;}/*** 判断x,y位置的棋子,是否左斜有相邻的五个一致。* @param x* @param y* @param points* @return*/private boolean checkLeftDiagonal(int x, int y, List<Point> points) {int count = 1;for(int i=0;i<MAX_COUNT_IN_LINE;i++){if(points.contains(new Point(x-i,y+i))){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-i))){count++;}else{break;}}if(count==MAX_COUNT_IN_LINE) return true;return  false;}/*** 判断x,y位置的棋子,是否右斜有相邻的五个一致。* @param x* @param y* @param points* @return*/private boolean checkRightDiagonal(int x, int y, List<Point> points) {int count = 1;for(int i=0;i<MAX_COUNT_IN_LINE;i++){if(points.contains(new Point(x-i,y-i))){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+i))){count++;}else{break;}}if(count==MAX_COUNT_IN_LINE) return true;return  false;}private void drawPieces(Canvas canvas) {for(int i=0,n = mWhiteArray.size(); i< n ;i++){Point whitePoint = mWhiteArray.get(i);canvas.drawBitmap(mWhitePiece,(whitePoint.x+(1-ratioPieceOfLineHeight)/2)*mLineHeight,(whitePoint.y+(1-ratioPieceOfLineHeight)/2)*mLineHeight,null);}for(int i=0,n = mBlackArray.size(); i< n ;i++){Point blackPoint = mBlackArray.get(i);canvas.drawBitmap(mBlackPiece,(blackPoint.x+(1-ratioPieceOfLineHeight)/2)*mLineHeight,(blackPoint.y+(1-ratioPieceOfLineHeight)/2)*mLineHeight,null);}}private void drawBoard(Canvas canvas) {/*** 分析:根据棋盘的效果,我们知道棋子是下在边界的交叉点上的。可得棋盘中间有9个完整的lineHeight,* 上下两边有半个lineHeight,总共10个lineHeight。左右也是。*/int w = mPanelWidth;float lineHeight = mLineHeight;for(int i=0;i<MAX_LINE;i++){int startX = (int) (lineHeight / 2);//起点坐标int endX = (int) (w - lineHeight / 2);//终点坐标int y = (int) ((0.5+i)*lineHeight);canvas.drawLine(startX,y,endX,y,mPaint);canvas.drawLine(y,startX,y,endX,mPaint);}}
}

View的存储与恢复:

WuziqiPanel.java
package com.xbmu.wuziqi;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.view.MotionEvent;
import android.view.View;
import android.widget.Toast;import java.util.ArrayList;
import java.util.List;/*** 五子棋面板* Created by Administrator on 2016/5/2 0002.*/
public class WuziqiPanel extends View {private int mPanelWidth;//棋盘宽度private float mLineHeight;//棋盘每行行高private int MAX_LINE = 10;//棋盘最大行数//创建绘画对象private Paint mPaint = new Paint();private Bitmap mWhitePiece;//白色棋子private Bitmap mBlackPiece;//黑色棋子//比例:棋子的大小是行高的3/4;private float ratioPieceOfLineHeight = 3*1.0f / 4;//白棋先手,当前轮到白棋。private boolean mIsWhite = true;private ArrayList<Point> mWhiteArray = new ArrayList<>();private ArrayList<Point> mBlackArray = new ArrayList<>();private boolean mIsGameOver;private boolean mIsWhiteWinner;private int MAX_COUNT_IN_LINE = 5;public WuziqiPanel(Context context, AttributeSet attrs) {super(context, attrs);setBackgroundColor(0x44ff0000);init();}/**初始化画笔属性*/private void init() {mPaint.setColor(0x88000000);//设置颜色为灰色效果mPaint.setAntiAlias(true);mPaint.setDither(true);mPaint.setStyle(Paint.Style.STROKE);mWhitePiece = BitmapFactory.decodeResource(getResources(),R.drawable.stone_w2);mBlackPiece = BitmapFactory.decodeResource(getResources(),R.drawable.stone_b1);}/**测量一个view的大小*/@Overrideprotected 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(widthMeasureSpec);int width = Math.min(widthSize,heightSize);if(widthMode == MeasureSpec.UNSPECIFIED){width = heightSize;}else if(heightMode == MeasureSpec.UNSPECIFIED){width = widthSize;}//设置自身大小setMeasuredDimension(width,width);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mPanelWidth = w;mLineHeight = mPanelWidth*1.0f / MAX_LINE;int pieceWidth = (int) (mLineHeight * ratioPieceOfLineHeight);//棋子宽度mWhitePiece = Bitmap.createScaledBitmap(mWhitePiece,pieceWidth,pieceWidth,false);mBlackPiece = Bitmap.createScaledBitmap(mBlackPiece,pieceWidth,pieceWidth,false);}@Overridepublic boolean onTouchEvent(MotionEvent event) {int action = event.getAction();if(action == MotionEvent.ACTION_DOWN){int x = (int) event.getX();int y = (int) event.getY();Point p = getValidPoint(x,y);if(mWhiteArray.contains(p) || mBlackArray.contains(p)){return false;}if(mIsWhite){mWhiteArray.add(p);}else{mBlackArray.add(p);}invalidate();//请求重绘mIsWhite = !mIsWhite;return true;}return super.onTouchEvent(event);}private Point getValidPoint(int x, int y) {return new Point((int)(x/mLineHeight) ,(int)(y/mLineHeight));}/**Draw画出View的显示内容*/@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//绘制棋盘drawBoard(canvas);//绘制棋子drawPieces(canvas);//检查游戏结束checkGameOver();}private void checkGameOver() {boolean whiteWin = checkFiveInLine(mWhiteArray);boolean blackWin = checkFiveInLine(mBlackArray);if(whiteWin || blackWin){mIsGameOver = true;mIsWhiteWinner = whiteWin;String text = mIsWhiteWinner ? "白棋胜利":"黑棋胜利";Toast.makeText(getContext(),text,Toast.LENGTH_LONG).show();}}private boolean checkFiveInLine(List<Point> points) {for (Point p : points){int x = p.x;int y = p.y;boolean win = checkHorizontal(x,y,points);if(win) return true;win = checkVertical(x,y,points);if(win) return true;win =checkLeftDiagonal(x,y,points);if(win) return true;win = checkRightDiagonal(x,y,points);if(win) return true;}return false;}/*** 判断x,y位置的棋子,是否横向有相邻的五个一致。* @param x* @param y* @param points* @return*/private boolean checkHorizontal(int x, int y, List<Point> points) {int count = 1;//左for(int i=0;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;}/*** 判断x,y位置的棋子,是否纵向有相邻的五个一致。* @param x* @param y* @param points* @return*/private boolean checkVertical(int x, int y, List<Point> points) {int count = 1;//上for(int i=0;i<MAX_COUNT_IN_LINE;i++){if(points.contains(new Point(x,y-i))){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,y+i))){count++;}else{break;}}if(count==MAX_COUNT_IN_LINE) return true;return  false;}/*** 判断x,y位置的棋子,是否左斜有相邻的五个一致。* @param x* @param y* @param points* @return*/private boolean checkLeftDiagonal(int x, int y, List<Point> points) {int count = 1;for(int i=0;i<MAX_COUNT_IN_LINE;i++){if(points.contains(new Point(x-i,y+i))){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-i))){count++;}else{break;}}if(count==MAX_COUNT_IN_LINE) return true;return  false;}/*** 判断x,y位置的棋子,是否右斜有相邻的五个一致。* @param x* @param y* @param points* @return*/private boolean checkRightDiagonal(int x, int y, List<Point> points) {int count = 1;for(int i=0;i<MAX_COUNT_IN_LINE;i++){if(points.contains(new Point(x-i,y-i))){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+i))){count++;}else{break;}}if(count==MAX_COUNT_IN_LINE) return true;return  false;}private void drawPieces(Canvas canvas) {for(int i=0,n = mWhiteArray.size(); i< n ;i++){Point whitePoint = mWhiteArray.get(i);canvas.drawBitmap(mWhitePiece,(whitePoint.x+(1-ratioPieceOfLineHeight)/2)*mLineHeight,(whitePoint.y+(1-ratioPieceOfLineHeight)/2)*mLineHeight,null);}for(int i=0,n = mBlackArray.size(); i< n ;i++){Point blackPoint = mBlackArray.get(i);canvas.drawBitmap(mBlackPiece,(blackPoint.x+(1-ratioPieceOfLineHeight)/2)*mLineHeight,(blackPoint.y+(1-ratioPieceOfLineHeight)/2)*mLineHeight,null);}}private void drawBoard(Canvas canvas) {/*** 分析:根据棋盘的效果,我们知道棋子是下在边界的交叉点上的。可得棋盘中间有9个完整的lineHeight,* 上下两边有半个lineHeight,总共10个lineHeight。左右也是。*/int w = mPanelWidth;float lineHeight = mLineHeight;for(int i=0;i<MAX_LINE;i++){int startX = (int) (lineHeight / 2);//起点坐标int endX = (int) (w - lineHeight / 2);//终点坐标int y = (int) ((0.5+i)*lineHeight);canvas.drawLine(startX,y,endX,y,mPaint);canvas.drawLine(y,startX,y,endX,mPaint);}}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";@Overrideprotected Parcelable onSaveInstanceState() {Bundle bundle = new Bundle();bundle.putParcelable(INSTANCE,super.onSaveInstanceState());bundle.putBoolean(INSTANCE_GAME_OVER,mIsGameOver);bundle.putParcelableArrayList(INSTANCE_WHITE_ARRAY,mWhiteArray);bundle.putParcelableArrayList(INSTANCE_BLACK_ARRAY,mBlackArray);return bundle;}@Overrideprotected void onRestoreInstanceState(Parcelable state) {if(state instanceof Bundle){Bundle bundle = (Bundle) state;mIsGameOver = 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);}
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/bg"tools:context="com.xbmu.wuziqi.MainActivity"><com.xbmu.wuziqi.WuziqiPanelandroid:id="@+id/id_wuziqi"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_centerInParent="true" />
</RelativeLayout>

运行效果:

再来一局&我要悔棋

Wuziqi.java
package com.xbmu.wuziqi;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.view.MotionEvent;
import android.view.View;
import android.widget.Toast;import java.util.ArrayList;
import java.util.List;/*** 五子棋面板* Created by Administrator on 2016/5/2 0002.*/
public class WuziqiPanel extends View {private int mPanelWidth;//棋盘宽度private float mLineHeight;//棋盘每行行高private int MAX_LINE = 10;//棋盘最大行数//创建绘画对象private Paint mPaint = new Paint();private Bitmap mWhitePiece;//白色棋子private Bitmap mBlackPiece;//黑色棋子//比例:棋子的大小是行高的3/4;private float ratioPieceOfLineHeight = 3*1.0f / 4;//白棋先手,当前轮到白棋。private boolean mIsWhite = true;private ArrayList<Point> mWhiteArray = new ArrayList<>();private ArrayList<Point> mBlackArray = new ArrayList<>();private boolean mIsGameOver;private boolean mIsWhiteWinner;private int MAX_COUNT_IN_LINE = 5;public WuziqiPanel(Context context, AttributeSet attrs) {super(context, attrs);setBackgroundColor(0x44ff0000);init();}/**初始化画笔属性*/private void init() {mPaint.setColor(0x88000000);//设置颜色为灰色效果mPaint.setAntiAlias(true);mPaint.setDither(true);mPaint.setStyle(Paint.Style.STROKE);mWhitePiece = BitmapFactory.decodeResource(getResources(),R.drawable.stone_w2);mBlackPiece = BitmapFactory.decodeResource(getResources(),R.drawable.stone_b1);}/**测量一个view的大小*/@Overrideprotected 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(widthMeasureSpec);int width = Math.min(widthSize,heightSize);if(widthMode == MeasureSpec.UNSPECIFIED){width = heightSize;}else if(heightMode == MeasureSpec.UNSPECIFIED){width = widthSize;}//设置自身大小setMeasuredDimension(width,width);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mPanelWidth = w;mLineHeight = mPanelWidth*1.0f / MAX_LINE;int pieceWidth = (int) (mLineHeight * ratioPieceOfLineHeight);//棋子宽度mWhitePiece = Bitmap.createScaledBitmap(mWhitePiece,pieceWidth,pieceWidth,false);mBlackPiece = Bitmap.createScaledBitmap(mBlackPiece,pieceWidth,pieceWidth,false);}@Overridepublic boolean onTouchEvent(MotionEvent event) {int action = event.getAction();if(action == MotionEvent.ACTION_DOWN){int x = (int) event.getX();int y = (int) event.getY();Point p = getValidPoint(x,y);if(mWhiteArray.contains(p) || mBlackArray.contains(p)){return false;}if(mIsWhite){mWhiteArray.add(p);}else{mBlackArray.add(p);}invalidate();//请求重绘mIsWhite = !mIsWhite;return true;}return super.onTouchEvent(event);}private Point getValidPoint(int x, int y) {return new Point((int)(x/mLineHeight) ,(int)(y/mLineHeight));}private Canvas canvas;/**Draw画出View的显示内容*/@Overrideprotected void onDraw(Canvas canvas) {this.canvas = canvas;super.onDraw(canvas);//绘制棋盘drawBoard(canvas);//绘制棋子drawPieces(canvas);//检查游戏结束checkGameOver();}private void checkGameOver() {boolean whiteWin = checkFiveInLine(mWhiteArray);boolean blackWin = checkFiveInLine(mBlackArray);if(whiteWin || blackWin){mIsGameOver = true;mIsWhiteWinner = whiteWin;String text = mIsWhiteWinner ? "白棋胜利":"黑棋胜利";Toast.makeText(getContext(),text,Toast.LENGTH_LONG).show();}}private boolean checkFiveInLine(List<Point> points) {for (Point p : points){int x = p.x;int y = p.y;boolean win = checkHorizontal(x,y,points);if(win) return true;win = checkVertical(x,y,points);if(win) return true;win =checkLeftDiagonal(x,y,points);if(win) return true;win = checkRightDiagonal(x,y,points);if(win) return true;}return false;}/*** 判断x,y位置的棋子,是否横向有相邻的五个一致。* @param x* @param y* @param points* @return*/private boolean checkHorizontal(int x, int y, List<Point> points) {int count = 1;//左for(int i=0;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;}/*** 判断x,y位置的棋子,是否纵向有相邻的五个一致。* @param x* @param y* @param points* @return*/private boolean checkVertical(int x, int y, List<Point> points) {int count = 1;//上for(int i=0;i<MAX_COUNT_IN_LINE;i++){if(points.contains(new Point(x,y-i))){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,y+i))){count++;}else{break;}}if(count==MAX_COUNT_IN_LINE) return true;return  false;}/*** 判断x,y位置的棋子,是否左斜有相邻的五个一致。* @param x* @param y* @param points* @return*/private boolean checkLeftDiagonal(int x, int y, List<Point> points) {int count = 1;for(int i=0;i<MAX_COUNT_IN_LINE;i++){if(points.contains(new Point(x-i,y+i))){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-i))){count++;}else{break;}}if(count==MAX_COUNT_IN_LINE) return true;return  false;}/*** 判断x,y位置的棋子,是否右斜有相邻的五个一致。* @param x* @param y* @param points* @return*/private boolean checkRightDiagonal(int x, int y, List<Point> points) {int count = 1;for(int i=0;i<MAX_COUNT_IN_LINE;i++){if(points.contains(new Point(x-i,y-i))){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+i))){count++;}else{break;}}if(count==MAX_COUNT_IN_LINE) return true;return  false;}private void drawPieces(Canvas canvas) {for(int i=0,n = mWhiteArray.size(); i< n ;i++){Point whitePoint = mWhiteArray.get(i);canvas.drawBitmap(mWhitePiece,(whitePoint.x+(1-ratioPieceOfLineHeight)/2)*mLineHeight,(whitePoint.y+(1-ratioPieceOfLineHeight)/2)*mLineHeight,null);}for(int i=0,n = mBlackArray.size(); i< n ;i++){Point blackPoint = mBlackArray.get(i);canvas.drawBitmap(mBlackPiece,(blackPoint.x+(1-ratioPieceOfLineHeight)/2)*mLineHeight,(blackPoint.y+(1-ratioPieceOfLineHeight)/2)*mLineHeight,null);}}private void drawPieces(Canvas canvas,int whiteCount,int blackCount) {for(int i=0,n =whiteCount; i< n ;i++){Point whitePoint = mWhiteArray.get(i);canvas.drawBitmap(mWhitePiece,(whitePoint.x+(1-ratioPieceOfLineHeight)/2)*mLineHeight,(whitePoint.y+(1-ratioPieceOfLineHeight)/2)*mLineHeight,null);}for(int i=0,n = blackCount; i< n ;i++){Point blackPoint = mBlackArray.get(i);canvas.drawBitmap(mBlackPiece,(blackPoint.x+(1-ratioPieceOfLineHeight)/2)*mLineHeight,(blackPoint.y+(1-ratioPieceOfLineHeight)/2)*mLineHeight,null);}}private void drawBoard(Canvas canvas) {/*** 分析:根据棋盘的效果,我们知道棋子是下在边界的交叉点上的。可得棋盘中间有9个完整的lineHeight,* 上下两边有半个lineHeight,总共10个lineHeight。左右也是。*/int w = mPanelWidth;float lineHeight = mLineHeight;for(int i=0;i<MAX_LINE;i++){int startX = (int) (lineHeight / 2);//起点坐标int endX = (int) (w - lineHeight / 2);//终点坐标int y = (int) ((0.5+i)*lineHeight);canvas.drawLine(startX,y,endX,y,mPaint);canvas.drawLine(y,startX,y,endX,mPaint);}}/**再来一局*/public void reStart(){mWhiteArray.clear();mBlackArray.clear();mIsGameOver = false;mIsWhiteWinner = false;invalidate();}//是否悔棋。true悔棋,false不悔棋private boolean isBlack = true;//悔棋public void goRegret(){//棋盘上无子if(mWhiteArray.size() == 0 && mBlackArray.size() == 0){return;}//棋盘上有子if(mIsWhite){//下一步白棋先手//上一步黑棋可以悔棋mBlackArray.remove(mBlackArray.size()-1);}else{//下一步黑棋先手手//上一步白棋可以悔棋mWhiteArray.remove(mWhiteArray.size()-1);}mIsWhite = !mIsWhite;mIsGameOver = true;mIsWhiteWinner = false;invalidate();isBlack = !isBlack;}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";@Overrideprotected Parcelable onSaveInstanceState() {Bundle bundle = new Bundle();bundle.putParcelable(INSTANCE,super.onSaveInstanceState());bundle.putBoolean(INSTANCE_GAME_OVER,mIsGameOver);bundle.putParcelableArrayList(INSTANCE_WHITE_ARRAY,mWhiteArray);bundle.putParcelableArrayList(INSTANCE_BLACK_ARRAY,mBlackArray);return bundle;}@Overrideprotected void onRestoreInstanceState(Parcelable state) {if(state instanceof Bundle){Bundle bundle = (Bundle) state;mIsGameOver = 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);}
}

MainActivity.java

package com.xbmu.wuziqi;import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;public class MainActivity extends Activity {private WuziqiPanel wuziqiPanel;private Button btnRestart;private Button btnRegret;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);wuziqiPanel  = (WuziqiPanel) findViewById(R.id.id_wuziqi);btnRestart  = (Button) findViewById(R.id.btn_restart);btnRegret = (Button) findViewById(R.id.btn_regret);//再来一局btnRestart.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {wuziqiPanel.reStart();}});//我要悔棋btnRegret.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {wuziqiPanel.goRegret();}});}
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/bg"tools:context="com.xbmu.wuziqi.MainActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:id="@+id/ll_top"android:gravity="center"><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="再来一局"android:id="@+id/btn_restart"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/btn_regret"android:text="我要悔棋"/></LinearLayout><com.xbmu.wuziqi.WuziqiPanelandroid:id="@+id/id_wuziqi"android:layout_marginTop="10dp"android:layout_below="@id/ll_top"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_centerHorizontal="true" />
</RelativeLayout>

运行效果:

感谢慕课网提供的教学资料,源码下载:http://download.csdn.net/detail/btt2013/9508584

Android五子连珠相关推荐

  1. 我的五子连珠-android

    一直没有写博客了,这段时间在看一些书,提升下自己的理论基础.为了给女友写一个五子连珠,所以开始设计这款游戏,目前完成了游戏的路径寻找和动画移动.代码还是比较乱的,等我整理了会贴出来的,经常在博客里看别 ...

  2. 游戏更新-五子连珠-Android

    五子连珠游戏,在9×9方格中,鼠标点击小球移动,每当5个或5个以上同颜色的小球连成1行,则消去并得分,如果移动时没有得分,将随机产生三个小球,当游戏不能放3个球时游戏结束. 下载地址: http:// ...

  3. 五子连珠游戏使用手册

    [size=large]使用手册User Manual[/size] 本程序为一款五子连珠游戏,每移动一粒珠子,即随机出现三粒彩色珠子,当同颜色珠子连续排列超过五粒(含五粒)时,该排列成功消除并行分, ...

  4. [从零开始unity3D]“五子连珠”游戏实现,网格数组的创建(1)

    大概是一周前,在知乎上偶然看见一位前辈提供的意见,他认为在一个立志于进入游戏行业发展的程序员在大学期间应该多动手,亲自去完成一些项目,在遇到坑,填补坑的过程中快速的提升技术水平.想来我虽然已经入职游戏 ...

  5. python +pygame 制作五子连珠小游戏

    python +pygame 制作五子连珠小游戏 学习python半年了,今天分享一个利用pygame制作的五子连珠游戏. 一.代码: 1.球类,ball.py """ ...

  6. c语言五子棋怎么判断五子连珠,分享一个 五子棋 输赢 的 判断逻辑。C#脚本

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 欢迎指出哪里需要改进.头有点晕,想了半天 实现的. 首先棋盘是由二维数组qipan[,]实现. 然后0是没有下子的状态.1是白子,2是黑子. 直接每次下完 ...

  7. 用Java写的简单五子棋游戏(原创五子连珠算法)

    源码jar包(已安装jdk环境可直接运行) 下载地址:http://download.csdn.net/detail/eguid_1/9532912 五子连珠算法为自创算法,对于五子棋该算法性能足以. ...

  8. NowCoder最近爱上了五子棋,现在给你一个棋局,请你帮忙判断其中有没有五子连珠(超过五颗也算)。

    NowCoder最近爱上了五子棋,现在给你一个棋局,请你帮忙判断其中有没有五子连珠(超过五颗也算). 解析: import java.util.*; public class Main {static ...

  9. 计算机游戏五子连珠怎么出来,五子连珠游戏程序流程图

    满意答案 五子连珠介绍:玩家只需依照五子棋的基础规则进行相应怪物击杀凑成五子连珠,便能获得丰厚的通关奖励.脑力与战斗力的紧密结合,相信能带给你不一样的五子棋心得.玩家每天可以在五子连珠活动开启时间内进 ...

最新文章

  1. MFC框架程序----实现十
  2. 惊艳!亚洲规模最大、标准最高的金融数据中心 |上证所金桥技术中心基地项目...
  3. java 23种设计模式(转载)
  4. 100多个很有用的JavaScript函数以及基础写法大集合
  5. ehd边缘直方图描述子 matlab,一种新的图像空间特征提取方法
  6. dell4600服务器不能启动
  7. win 10 系统怎么显示隐藏文件
  8. html 怎么绘制曲线图,用html5绘制折线图的实例代码_html5教程技巧
  9. [转]overflow解决float浮动后高度自适应问题
  10. 遇到问题---hosts不起作用问题的解决方法
  11. 11个绝佳免费矢量素材下载网站,拿走不谢!
  12. SpringCloud整合LCN分布式事务模式
  13. 数据结构严蔚敏--综述
  14. eladmin 批量导入实现方法
  15. php判断字符串长度 strlen()与mb_strlen()函数
  16. 费雪信息 (Fisher information)
  17. 阶段式软件研发项目管理工具
  18. 查看当前Ubuntu系统的版本
  19. 集成电路设计学习笔记(二)基于IC617反相器设计之原理图绘制
  20. web前端-HTML-表格

热门文章

  1. 计算机毕业设计ssm滁州学院考研信息分享论坛0iaj2系统+程序+源码+lw+远程部署
  2. Edgio WAF规则——在混乱中创造秩序(上篇)
  3. Java常用API(三)
  4. Answer to assessment of Fundamentals of Accelerated Computing with OpenACC
  5. 特斯拉印证成本仍是工业制造取胜的关键,反证中国制造的优势
  6. HDLBits Tb/tff
  7. Element-ui升级到最新版 2.4.6
  8. P1983 [NOIP2013 普及组] 车站分级
  9. VUE3.0学习笔记(一)-创建VUE项目
  10. day3-----交付服务准备工作以及k8s版本升级(2)