java android 五子棋游戏_Android自定义View实现五子棋游戏

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

1、效果图:

56ba0fd7f8746f4624783a66d1324374.gif

2、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);

}

}

3、使用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:

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#fff"

tools:context=".MainActivity">

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/gobang_panel"

android:layout_width="1000dp"

android:layout_height="1000dp"

android:layout_centerInParent="true" />

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值