千家信息网

如何使用Android自定义View实现五子棋游戏

发表于:2025-01-21 作者:千家信息网编辑
千家信息网最后更新 2025年01月21日,小编给大家分享一下如何使用Android自定义View实现五子棋游戏,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!具体内容
千家信息网最后更新 2025年01月21日如何使用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安全错误 数据库的锁怎样保障安全 存储服务器维修费用清单 数据库设计表的时候需要注意什么 无锡智能化软件开发创新服务 黑龙江存储服务器虚拟主机 网络安全管理局梁斌 青岛网络安全技术中心 成都企米网络技术公司怎么样 社保增员显示网络技术问题 哪个网站可以估价软件开发 英雄之城2什么服务器好 中国的网络技术心得 崇明区大型软件开发厂家现货 宝徳服务器上市 防城港软件开发工程师证 如何运用java写数据库 中国电信网络安全惠民生 百世网络技术有限公司信用代码 用易语言做数据库查询 网络安全怎么写四年级 哪种服务器安全一点 gpu渲染服务器软件开发 虚拟网络安全问题 计算机网络技术专业宣传标语 查看虚拟机所在服务器信息 服务器bmc一直连接又断开 网络安全层级薄弱 专业软件开发价格咨询 阿里云服务器 ip 太原理工大学数据库技术研讨会 学生拍网络安全微电影
0