前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android自定义View实现五子棋游戏

Android自定义View实现五子棋游戏

作者头像
砸漏
发布2020-10-16 10:33:37
9810
发布2020-10-16 10:33:37
举报
文章被收录于专栏:恩蓝脚本恩蓝脚本

本文实例为大家分享了Android五子棋游戏的具体代码,供大家参考,具体内容如下

1、效果图:

2、GobangPanel棋盘面板:

代码语言:javascript
复制
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);
}
}

3、使用MainActivity

代码语言:javascript
复制
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:

代码语言:javascript
复制
<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 

以上就是本文的全部内容,希望对大家的学习有所帮助。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-09-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档