Android自定义View实现五子棋游戏
程序员文章站
2022-06-20 14:50:15
本文实例为大家分享了android五子棋游戏的具体代码,供大家参考,具体内容如下
1、效果图:
2、gobangpanel棋盘面板:
public class gob...
本文实例为大家分享了android五子棋游戏的具体代码,供大家参考,具体内容如下
1、效果图:
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<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
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>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。