溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何使用Android自定義View實(shí)現(xiàn)五子棋游戲

發(fā)布時(shí)間:2021-09-27 11:44:54 來源:億速云 閱讀:115 作者:小新 欄目:編程語言

小編給大家分享一下如何使用Android自定義View實(shí)現(xiàn)五子棋游戲,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

具體內(nèi)容如下

GobangPanel棋盤面板:

public class GobangPanel extends View { private int mPanelWidth;//棋盤的寬度 private float mLineHeight;//行,高要為float private int MAX_LINE = 15;//棋盤行數(shù) private int MAX_COUNT_IN_LINE = 5;//設(shè)置贏棋子個(gè)數(shù)(6子棋設(shè)置為6) private Paint mPaint = new Paint();//畫筆 private Bitmap mWhitePiece;//白色棋子 private Bitmap mBlackPiece;//黑色棋子 private float ratioPieceOfLineHeight = 3 * 1.0f / 4;//2個(gè)棋子間3/4距離 //白旗先手,當(dāng)前輪到白棋了 private boolean mIsWhite = true; private ArrayList<Point> mWhiteArray = new ArrayList<>();//白棋數(shù)組 private List<Point> mBlackArray = new ArrayList<>();//黑騎數(shù)組 private boolean mIsGameOver;//游戲是否結(jié)束 private boolean mIsWhiteWinner;//白色棋子贏 true白子贏,false黑色贏 public GobangPanel(Context context, AttributeSet attrs) {  super(context, attrs);  init(); } /**  * 初始化畫筆參數(shù)  */ private void init() {  mPaint.setColor(0x88000000);//Paint顏色 半透明灰色  mPaint.setAntiAlias(true);//抗鋸齒(邊界明顯變模糊)  mPaint.setDither(true);//設(shè)置防抖動(圖片柔和)  mPaint.setStyle(Paint.Style.STROKE);//樣式  //黑、白棋資源圖片  mWhitePiece = BitmapFactory.decodeResource(getResources(), R.mipmap.white_bg);  mBlackPiece = BitmapFactory.decodeResource(getResources(), R.mipmap.black_bg); } /**  * 自定義View尺寸的規(guī)則  */ 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); } /**  * 控件大小發(fā)生改變時(shí)調(diào)用  */ 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); } //觸摸焦點(diǎn) 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"; /**  * 游戲結(jié)束方法  */ public void checkGameOver() {  boolean whiteWin = checkFiveInLine(mWhiteArray);  boolean blackWin = checkFiveInLine(mBlackArray);  //黑棋或白棋贏游戲結(jié)束  if (whiteWin || blackWin) {   mIsGameOver = true;   mIsWhiteWinner = whiteWin;   if (null != listener) {    listener.onFinish(mIsWhiteWinner);    Log.e(TAG, "checkGameOver: 111111" );   }   Log.e(TAG, "checkGameOver: 222222" );  } } /**  * 判斷棋子是否5個(gè)相鄰【5個(gè)相連只有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位置的棋子是否【水平】有相鄰的五個(gè)一致  */ private boolean checkLevel(int x, int y, List<Point> points) {  int count = 1;  //橫向左邊棋子個(gè)數(shù)  for (int i = 1; i < MAX_COUNT_IN_LINE; i++) {   //如果有加1,沒有重新計(jì)算是否有五個(gè),否者中斷   if (points.contains(new Point(x - i, y))) {    count++;   } else {    break;   }  }  //有5個(gè)時(shí)則贏  if (count == MAX_COUNT_IN_LINE) return true;  //橫向右邊棋子個(gè)數(shù)  for (int i = 1; i < MAX_COUNT_IN_LINE; i++) {   //如果有加1,沒有重新計(jì)算是否有五個(gè),否者中斷   if (points.contains(new Point(x + i, y))) {    count++;   } else {    break;   }  }  //有5個(gè)時(shí)則贏  if (count == MAX_COUNT_IN_LINE) return true;  return false; } /**  * 判斷x,y位置的棋子是否[垂直]有相鄰的五個(gè)一致  */ private boolean checkVetical(int x, int y, List<Point> points) {  int count = 1;  //上下棋子個(gè)數(shù)  for (int i = 1; i < MAX_COUNT_IN_LINE; i++) {   //如果有加1,沒有重新計(jì)算是否有五個(gè),否者中斷   if (points.contains(new Point(x, y - i))) {    count++;   } else {    break;   }  }  //有5個(gè)時(shí)則贏,return true;  if (count == MAX_COUNT_IN_LINE) return true;  for (int i = 1; i < MAX_COUNT_IN_LINE; i++) {   //如果有加1,沒有重新計(jì)算是否有五個(gè),否者中斷   if (points.contains(new Point(x, y + i))) {    count++;   } else {    break;   }  }  //有5個(gè)時(shí)則贏  if (count == MAX_COUNT_IN_LINE) return true;  return false; } /**  * 判斷x,y位置的棋子是否【左斜和右斜】有相鄰的五個(gè)一致  */ private boolean checkLeftWin(int x, int y, List<Point> points) {  int count = 1;  //橫向上下棋子個(gè)數(shù)  for (int i = 1; i < MAX_COUNT_IN_LINE; i++) {   //如果有加1,沒有重新計(jì)算是否有五個(gè),否者中斷   if (points.contains(new Point(x - i, y + i))) {    count++;   } else {    break;   }  }  //有5個(gè)時(shí)則贏,return true;  if (count == MAX_COUNT_IN_LINE) return true;  for (int i = 1; i < MAX_COUNT_IN_LINE; i++) {   //如果有加1,沒有重新計(jì)算是否有五個(gè),否者中斷   if (points.contains(new Point(x + i, y - i))) {    count++;   } else {    break;   }  }  //有5個(gè)時(shí)則贏  if (count == MAX_COUNT_IN_LINE) return true;  return false; } /**  * 判斷x,y位置的棋子是否【右斜】有相鄰的五個(gè)一致  */ private boolean checkRightWin(int x, int y, List<Point> points) {  int count = 1;  //橫向上下棋子個(gè)數(shù)  for (int i = 1; i < MAX_COUNT_IN_LINE; i++) {   //如果有加1,沒有重新計(jì)算是否有五個(gè),否者中斷   if (points.contains(new Point(x - i, y - i))) {    count++;   } else {    break;   }  }  //有5個(gè)時(shí)則贏,return true;  if (count == MAX_COUNT_IN_LINE) return true;  for (int i = 1; i < MAX_COUNT_IN_LINE; i++) {   //如果有加1,沒有重新計(jì)算是否有五個(gè),否者中斷   if (points.contains(new Point(x + i, y + i))) {    count++;   } else {    break;   }  }  //有5個(gè)時(shí)則贏  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);//橫坐標(biāo)起點(diǎn),終點(diǎn)   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();//清除數(shù)據(jù)   mBlackArray.clear();  }  mIsGameOver = false;  mIsWhiteWinner = false;  invalidate(); //再次調(diào)用 } /**  * 后臺運(yùn)行時(shí),調(diào)用此方法,防止數(shù)據(jù)丟失  */ private static final String INSTANCE = "instance"; private static final String INSTANCE_GAME_OVER = "instance_game_over"; //游戲結(jié)束 private static final String INSTANCE_WHITE_ARRAY = "instance_white_array"; //白 private static final String INSTANCE_BLACK_ARRAY = "instance_black_array"; /**  * 保存數(shù)據(jù)  */ 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; } /**  * 恢復(fù)時(shí)調(diào)用  */ 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); } /**  * 游戲結(jié)束回調(diào)  */ 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("這是標(biāo)題")    .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(); }}

對應(yīng)布局文件: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實(shí)現(xiàn)五子棋游戲”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI