温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

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

发布时间:2021-09-27 11:44:54 来源:亿速云 阅读:109 作者:小新 栏目:编程语言

小编给大家分享一下如何使用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<Point> mWhiteArray = new ArrayList<>();//白棋数组 private List<Point> 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<Point> 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<Point> 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<Point> 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<Point> 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<Point> 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:

<HorizontalScrollView 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="#fff" tools:context=".MainActivity"> <ScrollView  android:layout_width="match_parent"  android:layout_height="match_parent">  <com.helloworld.game.GobangPanel   android:id="@+id/gobang_panel"   android:layout_width="1000dp"   android:layout_height="1000dp"   android:layout_centerInParent="true" /> </ScrollView></HorizontalScrollView>

以上是“如何使用Android自定义View实现五子棋游戏”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI