如何使用Android自定义View实现五子棋游戏
发表于:2025-11-18 作者:千家信息网编辑
千家信息网最后更新 2025年11月18日,小编给大家分享一下如何使用Android自定义View实现五子棋游戏,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!具体内容
千家信息网最后更新 2025年11月18日如何使用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安全错误
数据库的锁怎样保障安全
cs软件开发语言
如何保障数据库服务器的安全
数据库中创建表后怎么加外键
如何利用宏录入客户数据库
数据库概论的封地明码是什么
多盟智胜网络技术有限公司
服务器在手机上能安装吗
小宇服务器管理员工具下载
网络安全数据安全靶场建设
本草纲目下载软件开发
限购网络技术
组态王软件开发狗和加密狗
华为媒体存储删除数据库
网络安全特征的含义
大邑县计算机网络技术培训好
数据库哪里可以看登录密码
只适用外文数据库的检索技术
demo和软件开发区别
2008数据库924
广元市网络安全监察部门
呼和浩特市app软件开发
钱云科技互联网
驾考软件开发定制
rfid的数据库任务
网络安全ppt免费模板大全
无线网络技术WAP
服务器系统设置
怎么看r 包里有哪些数据库
崇明区标准网络安全创新服务
公安机关网络安全处罚