如何使用Android自定义View实现五子棋游戏
发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,小编给大家分享一下如何使用Android自定义View实现五子棋游戏,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!具体内容
千家信息网最后更新 2026年11月03日如何使用Android自定义View实现五子棋游戏
小编给大家分享一下如何使用Android自定义View实现五子棋游戏,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
具体内容如下
GobangPanel棋盘面板:
public class GobangPanel extends View { private int mPanelWidth;//棋盘的宽度 private float mLineHeight;//行,高要为float private int MAX_LINE = 15;//棋盘行数 private int MAX_COUNT_IN_LINE = 5;//设置赢棋子个数(6子棋设置为6) private Paint mPaint = new Paint();//画笔 private Bitmap mWhitePiece;//白色棋子 private Bitmap mBlackPiece;//黑色棋子 private float ratioPieceOfLineHeight = 3 * 1.0f / 4;//2个棋子间3/4距离 //白旗先手,当前轮到白棋了 private boolean mIsWhite = true; private ArrayList mWhiteArray = new ArrayList<>();//白棋数组 private List mBlackArray = new ArrayList<>();//黑骑数组 private boolean mIsGameOver;//游戏是否结束 private boolean mIsWhiteWinner;//白色棋子赢 true白子赢,false黑色赢 public GobangPanel(Context context, AttributeSet attrs) { super(context, attrs); init(); } /** * 初始化画笔参数 */ private void init() { mPaint.setColor(0x88000000);//Paint颜色 半透明灰色 mPaint.setAntiAlias(true);//抗锯齿(边界明显变模糊) mPaint.setDither(true);//设置防抖动(图片柔和) mPaint.setStyle(Paint.Style.STROKE);//样式 //黑、白棋资源图片 mWhitePiece = BitmapFactory.decodeResource(getResources(), R.mipmap.white_bg); mBlackPiece = BitmapFactory.decodeResource(getResources(), R.mipmap.black_bg); } /** * 自定义View尺寸的规则 */ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //宽和高 int widthSize = MeasureSpec.getSize(widthMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int width = Math.max(widthSize, heightSize); //最大值 if (widthMode == MeasureSpec.UNSPECIFIED) { width = heightSize; } else if (heightMode == MeasureSpec.UNSPECIFIED) { width = widthSize; } setMeasuredDimension(width, width); } /** * 控件大小发生改变时调用 */ protected 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); } //触摸焦点 public boolean onTouchEvent(MotionEvent event) { if (mIsGameOver) return false; int action = event.getAction(); if (action == MotionEvent.ACTION_UP) { 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;//感兴趣交给其处理 } private Point getValidPoint(int x, int y) { return new Point((int) (x / mLineHeight), (int) (y / mLineHeight)); } protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawBoard(canvas); drawPieces(canvas); checkGameOver(); } private static final String TAG = "GobangPanel"; /** * 游戏结束方法 */ public void checkGameOver() { boolean whiteWin = checkFiveInLine(mWhiteArray); boolean blackWin = checkFiveInLine(mBlackArray); //黑棋或白棋赢游戏结束 if (whiteWin || blackWin) { mIsGameOver = true; mIsWhiteWinner = whiteWin; if (null != listener) { listener.onFinish(mIsWhiteWinner); Log.e(TAG, "checkGameOver: 111111" ); } Log.e(TAG, "checkGameOver: 222222" ); } } /** * 判断棋子是否5个相邻【5个相连只有4中情况分别是:水平、垂直、左斜和右斜】 */ private boolean checkFiveInLine(List points) { for (Point p : points) { int x = p.x; int y = p.y; boolean win = checkLevel(x, y, points); if (win) return true; win = checkVetical(x, y, points); if (win) return true; win = checkLeftWin(x, y, points); if (win) return true; win = checkRightWin(x, y, points); if (win) return true; } return false; } /** * 判断x,y位置的棋子是否【水平】有相邻的五个一致 */ private boolean checkLevel(int x, int y, List points) { int count = 1; //横向左边棋子个数 for (int i = 1; i < MAX_COUNT_IN_LINE; i++) { //如果有加1,没有重新计算是否有五个,否者中断 if (points.contains(new Point(x - i, y))) { count++; } else { break; } } //有5个时则赢 if (count == MAX_COUNT_IN_LINE) return true; //横向右边棋子个数 for (int i = 1; i < MAX_COUNT_IN_LINE; i++) { //如果有加1,没有重新计算是否有五个,否者中断 if (points.contains(new Point(x + i, y))) { count++; } else { break; } } //有5个时则赢 if (count == MAX_COUNT_IN_LINE) return true; return false; } /** * 判断x,y位置的棋子是否[垂直]有相邻的五个一致 */ private boolean checkVetical(int x, int y, List points) { int count = 1; //上下棋子个数 for (int i = 1; i < MAX_COUNT_IN_LINE; i++) { //如果有加1,没有重新计算是否有五个,否者中断 if (points.contains(new Point(x, y - i))) { count++; } else { break; } } //有5个时则赢,return true; if (count == MAX_COUNT_IN_LINE) return true; for (int i = 1; i < MAX_COUNT_IN_LINE; i++) { //如果有加1,没有重新计算是否有五个,否者中断 if (points.contains(new Point(x, y + i))) { count++; } else { break; } } //有5个时则赢 if (count == MAX_COUNT_IN_LINE) return true; return false; } /** * 判断x,y位置的棋子是否【左斜和右斜】有相邻的五个一致 */ private boolean checkLeftWin(int x, int y, List points) { int count = 1; //横向上下棋子个数 for (int i = 1; i < MAX_COUNT_IN_LINE; i++) { //如果有加1,没有重新计算是否有五个,否者中断 if (points.contains(new Point(x - i, y + i))) { count++; } else { break; } } //有5个时则赢,return true; if (count == MAX_COUNT_IN_LINE) return true; for (int i = 1; i < MAX_COUNT_IN_LINE; i++) { //如果有加1,没有重新计算是否有五个,否者中断 if (points.contains(new Point(x + i, y - i))) { count++; } else { break; } } //有5个时则赢 if (count == MAX_COUNT_IN_LINE) return true; return false; } /** * 判断x,y位置的棋子是否【右斜】有相邻的五个一致 */ private boolean checkRightWin(int x, int y, List points) { int count = 1; //横向上下棋子个数 for (int i = 1; i < MAX_COUNT_IN_LINE; i++) { //如果有加1,没有重新计算是否有五个,否者中断 if (points.contains(new Point(x - i, y - i))) { count++; } else { break; } } //有5个时则赢,return true; if (count == MAX_COUNT_IN_LINE) return true; for (int i = 1; i < MAX_COUNT_IN_LINE; i++) { //如果有加1,没有重新计算是否有五个,否者中断 if (points.contains(new Point(x + i, y + i))) { count++; } else { break; } } //有5个时则赢 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) { 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 start() { if (null != mWhiteArray && null != mBlackArray) { mWhiteArray.clear();//清除数据 mBlackArray.clear(); } mIsGameOver = false; mIsWhiteWinner = false; invalidate(); //再次调用 } /** * 后台运行时,调用此方法,防止数据丢失 */ 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"; /** * 保存数据 */ protected 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, mWhiteArray); return bundle; } /** * 恢复时调用 */ protected 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); } /** * 游戏结束回调 */ public OnFinishListener listener; public void setListener(OnFinishListener listener) { this.listener = listener; } public interface OnFinishListener { void onFinish(boolean mIsWhiteWinner); }} 使用MainActivity
public class MainActivity extends AppCompatActivity { private GobangPanel panel; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); panel = this.findViewById(R.id.gobang_panel); panel.setListener(new GobangPanel.OnFinishListener() { @Override public void onFinish(boolean mIsWhiteWinner) { initDialog(mIsWhiteWinner); } }); } /** * 初始化弹框 */ private void initDialog(boolean mIsWhiteWinner) { AlertDialog dialog = new AlertDialog.Builder(this) //.setTitle("这是标题") .setMessage(mIsWhiteWinner ? "白棋胜利,是否重新开始?" : "黑棋胜利,是否重新开始?") //.setIcon(R.mipmap.ic_launcher) .setPositiveButton("确定", new DialogInterface.OnClickListener() {//添加"Yes"按钮 @Override public void onClick(DialogInterface dialogInterface, int i) { panel.start(); } })// .setNegativeButton("取消", new DialogInterface.OnClickListener() {//添加取消// @Override// public void onClick(DialogInterface dialogInterface, int i) {// Toast.makeText(MainActivity.this, "这是取消按钮", Toast.LENGTH_SHORT).show();// }// }) //方法一:setCanceledOnTouchOutside(false);按对话框以外的地方不起作用。按返回键起作用 //方法二:setCanceleable(false);按对话框以外的地方不起作用。按返回键也不起作用 .setCancelable(false) .create(); dialog.show(); }}对应布局文件:activity_main:
以上是"如何使用Android自定义View实现五子棋游戏"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!
棋子
个数
棋盘
白棋
一致
位置
作用
横向
上下
内容
数据
方法
白色
篇文章
黑色
五子棋
五子
图片
地方
对话框
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
山东特亿宝互联网科技有限公司
互联网巨头反垄断金融科技
美国互联网科技巨头监管
西安互联网科技
互联网 科技创业
互联网科技的英文
极限挑战互联网科技
科技创新互联网企业
人人互联网科技是培训
互联网科技创新服务
武汉健翔互联网络科技有限公司
消费医药和互联网科技
允成互联网科技有限公司融资
东莞新华互联网科技学校
济南有互联网科技公司吗
互联网科技融合创新
数字科技和互联网金融哪个好
互联网领先科技成果宣传视频
互联网科技自媒体灵感
互联网科技企业文化
互联网金融科技
盈实互联网科技
深圳互联网络科技有限公司
期待互联网科技
互联网科技排名
天津摩尔互联网科技
融贸通互联网科技
撒么互联网科技公司
互联网经济与金融科技
特约风豹互联网科技为什么扣费