- 浏览: 260877 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
sunshine_bean:
第四行改进下URL=`svn info |grep &quo ...
linux判断是否需要svn up的脚本 -
leokelly001:
设置请求头,user-agent就行了
android使用豆瓣API出现500错误及解决方法 -
貌似掉线:
txy7121 写道HandlerFactory和AntiCo ...
大谈android安全2——Activity劫持的防范程序 -
txy7121:
HandlerFactory和AntiConstants这两个 ...
大谈android安全2——Activity劫持的防范程序 -
貌似掉线:
hyc_willie 写道关注着你的框架,希望能见到它的发布 ...
androidkit——Android开发框架
差点忘了写接下来的这两篇博客了,这篇如果接不上上一篇,请勿见怪啊,因为我自己都忘了。
上两篇分别提到了截图和图像识别,接下来这一篇是说一下连连看的消除算法。
这个算法看似很厉害,其实我在这里采用的是很笨拙的方法,就是枚举。
在上一篇已经连游戏里的方块转换成一个二维数组,所以就通过一个两层循环,遍历每一个元素,看能不能跟其他元素消除,代码如下:
其中search方法是搜索可以与该广场消除的方块,返回的point表示另一个方块的坐标。如果搜索不到就返回null,传的对象分别是纵坐标与横坐标。touch是向模拟器发送点击事件,当然每次消除我们要点击两个。消除之后,将对应元素设为。
关于search()方法的实现,就是枚举。我们知道连连看消除有三类路线,一类是直线的,有4种情况,第二类是拐一个弯的,有8种情况,第三类是拐两个弯的,有16种情况。我采用的是比较直接也是比较笨拙的方法,直接对它们进行枚举,代码如下:
举其中的一个例子,比如我们往右搜索,如果发现右边的不为0但也不和它相等,说明是其他方块,那这条路径就不能执行了。如果与它相等,说明是两个相同的方块,那么返回这个位置的坐标。如果为0,那么我们就可以进行下一步的搜索,比如继续往右(直线情况),或者往上往下(有拐弯的路径)。我把这三种情况都写在一起了,因为我在写的时候发现,直线路径是直角路径的一种特殊情况,而直角路径其实也是两个拐弯的路径的特殊情况。
当每个元素都遍历完之后,我们要判断是否全部消除完毕,如果消除完了,方法执行结束,进行下一次截图。如果没有,那么我们要再遍历搜索一次,因为可能存在的情况是一开始的方块不能被消除,但随着其他方块被消除之后,他们可以被消除了。
另外,我在这里还增加了一个anyClear的布尔变量,这是为了避免死循环,比如出现以下情况:
xo
ox
这种情况下是无法被消除的,游戏里面将会重新组合这些广场。所以当遍历完发现没有方块被消除时,需要重新截图。当然除了出现上面情况,实际操作时发现,其他情况也可能出现无法被消除问题,比如消除了一些方块后,会出现perfect等图案,这些图会影响一些方块的识别。这时也需要重新截图。所以实际上startSearch方法应该如下:
这篇就写到这里。下一篇说一下模拟按键,以及针对游戏、手机的实际情况,对程序的优化。
上两篇分别提到了截图和图像识别,接下来这一篇是说一下连连看的消除算法。
这个算法看似很厉害,其实我在这里采用的是很笨拙的方法,就是枚举。
在上一篇已经连游戏里的方块转换成一个二维数组,所以就通过一个两层循环,遍历每一个元素,看能不能跟其他元素消除,代码如下:
for (int i = 1; i < CODE_ROW - 1; i++) { for (int j = 1; j < CODE_COL - 1; j++) { if (imageCodes[i][j] != 0) { Point point = search(i, j); if (point == null) { continue; } touch(new Point(i, j)); touch(point); imageCodes[i][j] = 0; imageCodes[point.x][point.y] = 0; anyClear = true; System.out .println(String.format("消除 %d:%d %d:%d", i, j, point.x, point.y)); } }
其中search方法是搜索可以与该广场消除的方块,返回的point表示另一个方块的坐标。如果搜索不到就返回null,传的对象分别是纵坐标与横坐标。touch是向模拟器发送点击事件,当然每次消除我们要点击两个。消除之后,将对应元素设为。
关于search()方法的实现,就是枚举。我们知道连连看消除有三类路线,一类是直线的,有4种情况,第二类是拐一个弯的,有8种情况,第三类是拐两个弯的,有16种情况。我采用的是比较直接也是比较笨拙的方法,直接对它们进行枚举,代码如下:
/** * 搜索,返回最优点。 * * @return */ public Point search(int x, int y) { return LianlianKan.twoCornerSearch(imageCodes, x, y); } /** * 连连看搜索算法。 * * @author Geek_Soledad */ public static class LianlianKan { /** * 水平搜索 * * @param datas * 数组 * @param row * 对比数值所在的行 * @param col * 对比数值所在的列 * @param atRow * 进行水平搜索时所在的行 * @return */ private static Point moveHorizon(int[][] datas, int row, int col, int atRow, int atCol) { // 再拐左 for (int k = atCol - 1; k >= 1; k--) { if (datas[atRow][k] == datas[row][col]) { return new Point(atRow, k); } else if (datas[atRow][k] != 0) { break; } } // 再拐右 for (int k = atCol + 1; k < CODE_COL - 1; k++) { if (datas[atRow][k] == datas[row][col]) { return new Point(atRow, k); } else if (datas[atRow][k] != 0) { break; } } return null; } /** * 竖直搜索 * * @param datas * 数组 * @param row * 对比数值所在的行 * @param col * 对比数值所在的列 * @param atCol * 进行水平搜索时所在的列 * @return */ private static Point movePortrait(int[][] datas, int row, int col, int atRow, int atCol) { // 再拐上 for (int k = atCol - 1; k >= 1; k--) { if (datas[k][atCol] == datas[row][col]) { return new Point(k, atCol); } else if (datas[k][atCol] != 0) { break; } } // 再拐下 for (int k = atCol + 1; k < CODE_ROW - 1; k++) { if (datas[k][atCol] == datas[row][col]) { return new Point(k, atCol); } else if (datas[k][atCol] != 0) { break; } } return null; } /** * 两个角搜索 * * @param datas * 数组 * @param x * 纵坐标 * @param y * 横坐标 * @return */ public static Point twoCornerSearch(int[][] datas, int x, int y) { // 向左进行搜索 for (int i = y - 1; i >= 0; i--) { // 向左进行直线搜索 if (datas[x][i] == datas[x][y]) { return new Point(x, i); } else if (datas[x][i] != 0) { break; } // 向左,然后拐上进行直角搜索 for (int j = x - 1; j >= 0; j--) { if (datas[j][i] == datas[x][y]) { return new Point(j, i); } else if (datas[j][i] != 0) { break; } // 向左,拐上,再水平搜索 Point point = moveHorizon(datas, x, y, j, i); if (point != null) { return point; } } // 向左,然后拐下进行直角搜索 for (int j = x + 1; j < CODE_ROW; j++) { if (datas[j][i] == datas[x][y]) { return new Point(j, i); } else if (datas[j][i] != 0) { break; } // 向左,拐下,再水平搜索 Point point = moveHorizon(datas, x, y, j, i); if (point != null) { return point; } } } // 横向往右搜索 for (int i = y + 1, length = CODE_COL; i < length; i++) { // 向右直线搜索 if (datas[x][i] == datas[x][y]) { return new Point(x, i); } else if (datas[x][i] != 0) { break; } // 向右,然后拐上进行直角搜索。 for (int j = x - 1; j >= 0; j--) { if (datas[j][i] == datas[x][y]) { return new Point(j, i); } else if (datas[j][i] != 0) { break; } // 向右,拐上,再水平搜索 Point point = moveHorizon(datas, x, y, j, i); if (point != null) { return point; } } // 向右,然后拐下进行直角搜索 for (int j = x + 1; j < CODE_ROW; j++) { if (datas[j][i] == datas[x][y]) { return new Point(j, i); } else if (datas[j][i] != 0) { break; } // 向右,拐下,再水平搜索。 Point point = moveHorizon(datas, x, y, j, i); if (point != null) { return point; } } } // 纵向往上搜索 for (int i = x - 1; i >= 0; i--) { if (datas[i][y] == datas[x][y]) { return new Point(i, y); } else if (datas[i][y] != 0) { break; } // 向上,然后拐左进行直角搜索。 for (int j = y - 1; j >= 0; j--) { if (datas[i][j] == datas[x][y]) { return new Point(i, j); } else if (datas[i][j] != 0) { break; } // 向上,拐左,再竖直搜索 Point point = movePortrait(datas, x, y, i, j); if (point != null) { return point; } } // 向上,然后拐右进行直角搜索 for (int j = y + 1; j < CODE_COL; j++) { if (datas[i][j] == datas[x][y]) { return new Point(i, j); } else if (datas[i][j] != 0) { break; } // 向上,拐右,再竖直搜索 Point point = movePortrait(datas, x, y, i, j); if (point != null) { return point; } } } // 纵向往下搜索 for (int i = x + 1, length = CODE_ROW; i < length; i++) { if (datas[i][y] == datas[x][y]) { return new Point(i, y); } else if (datas[i][y] != 0) { break; } // 向下,然后拐左进行直角搜索。 for (int j = y - 1; j >= 0; j--) { if (datas[i][j] == datas[x][y]) { return new Point(i, j); } else if (datas[i][j] != 0) { break; } // 向下,拐右,再竖直搜索 Point point = movePortrait(datas, x, y, i, j); if (point != null) { return point; } } // 向下,然后拐右进行直角搜索 for (int j = y + 1; j < CODE_COL; j++) { if (datas[i][j] == datas[x][y]) { return new Point(i, j); } else if (datas[i][j] != 0) { break; } // 向下,拐右,再竖直搜索 Point point = movePortrait(datas, x, y, i, j); if (point != null) { return point; } } } return null; } }
举其中的一个例子,比如我们往右搜索,如果发现右边的不为0但也不和它相等,说明是其他方块,那这条路径就不能执行了。如果与它相等,说明是两个相同的方块,那么返回这个位置的坐标。如果为0,那么我们就可以进行下一步的搜索,比如继续往右(直线情况),或者往上往下(有拐弯的路径)。我把这三种情况都写在一起了,因为我在写的时候发现,直线路径是直角路径的一种特殊情况,而直角路径其实也是两个拐弯的路径的特殊情况。
当每个元素都遍历完之后,我们要判断是否全部消除完毕,如果消除完了,方法执行结束,进行下一次截图。如果没有,那么我们要再遍历搜索一次,因为可能存在的情况是一开始的方块不能被消除,但随着其他方块被消除之后,他们可以被消除了。
另外,我在这里还增加了一个anyClear的布尔变量,这是为了避免死循环,比如出现以下情况:
xo
ox
这种情况下是无法被消除的,游戏里面将会重新组合这些广场。所以当遍历完发现没有方块被消除时,需要重新截图。当然除了出现上面情况,实际操作时发现,其他情况也可能出现无法被消除问题,比如消除了一些方块后,会出现perfect等图案,这些图会影响一些方块的识别。这时也需要重新截图。所以实际上startSearch方法应该如下:
public boolean startSearch(BufferedImage image) throws InterruptedException { boolean anyClear = false; do { anyClear = false; for (int i = 1; i < CODE_ROW - 1; i++) { for (int j = 1; j < CODE_COL - 1; j++) { if (imageCodes[i][j] != 0) { Point point = search(i, j); if (point == null) { continue; } touch(new Point(i, j)); touch(point); imageCodes[i][j] = 0; imageCodes[point.x][point.y] = 0; anyClear = true; System.out .println(String.format("消除 %d:%d %d:%d", i, j, point.x, point.y)); } } } } while (anyClear && !isEmpty()); return anyClear; }
这篇就写到这里。下一篇说一下模拟按键,以及针对游戏、手机的实际情况,对程序的优化。
发表评论
-
利用电脑玩Android版“天天连萌”刷高分(四)——模拟按键及程序优化
2014-01-22 00:14 1719这一系列文章,没想到从去年10月份以来,写了三篇我就忘了写了, ... -
利用电脑玩Android版“天天连萌”刷高分(二)——图像识别
2013-10-20 15:44 1549上一篇只是提到了在PC端利用android sdk里面的工具进 ... -
利用电脑玩Android版“天天连萌”刷高分(一)——截图
2013-10-20 11:22 3415这几周微信游戏“天天 ... -
在PC端进行android截屏的多种方法
2013-10-18 11:01 3601昨晚意外的发现在PC端进行截屏的方法相当多,在android ... -
Java获取照片EXIF信息
2013-10-16 17:40 1564目前最简单易用的EXIF信息处理的Java包是Drew Noa ... -
近期计划
2013-09-01 20:02 1238在上一篇(http://maosidiao ... -
Android开源游戏引擎之Angle(二)——开始前的准备
2013-09-01 12:04 2526在上一篇博客(http://mao ... -
Android开源游戏引擎之Angle(一)——概述
2013-08-31 19:26 6050Angle是一个Android平台上 ... -
设置tabWidget标题的字体大小及颜色
2013-03-27 13:47 9464/* * @(#)TextAppearenceUtil ... -
一一对应的键值对象
2013-03-22 13:19 3065最近写程序需要用到一种结构,像HashMap的,但是却是一对一 ... -
桌面小部件AppWidget的使用
2013-02-23 13:49 1732在android平台中,显示在HOME界面的一些挂件,即桌面小 ... -
android使用actionbar与fragment
2013-01-16 23:12 2296android使用actionbar中的tab,及fragme ... -
android使用豆瓣API出现500错误及解决方法
2013-01-10 18:56 6307为团队做一个图书管理的应用,涉及到扫描ISBN然后查询图书信息 ... -
DES加密及解密封装
2012-12-20 23:40 1587/* * @(#)CipherUtil.java ... -
MD5加密封装
2012-12-20 23:38 1548/* * @(#)DigestUtil.java ... -
进入程序的动画IntroActivity增强版
2012-12-11 10:19 1478这是对上一次谈到的android程序进入前的动画的封装(详见: ... -
androidkit发布0.5.3alpha版
2012-12-07 09:26 1332androidkit是一个用于android应用层开发的工具包 ... -
使用Zxing及豆瓣API
2012-12-06 20:30 2403本文原创,转载请注明原文地址:http://maosidiao ... -
androidkit——减少android开发代码的工具包
2012-11-16 22:25 2231androidkit是我学android开发以来,慢慢在封装的 ... -
windows平台下用java解析apk包
2012-11-09 20:05 2391抽空把以前写的解析apk包的工具,重新写了一个,也解决了以前许 ...
相关推荐
《Android游戏星座连萌》是一款深受玩家喜爱的休闲益智类手机游戏,它结合了星座元素和连连看的玩法,为玩家带来独特的娱乐体验。在深入探讨这款游戏之前,我们需要了解Android平台的基础知识以及游戏开发的相关技术...
天天连萌源码
【标题】"安卓Android源码——星座连萌.zip" 提供的是一个基于Android平台开发的休闲游戏“星座连萌”的源代码。这个压缩包中包含了应用程序的可执行文件(星座连萌.apk)以及可能的其他开发资源或配置文件(xzlm)...
基于Java实现的天天连萌游戏自动玩+源码,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用~ 基于Java实现的天天连萌游戏自动玩+源码,适合毕业设计、课程设计、项目...
《安卓Android源码——娱乐项目安卓星座连萌》是一个针对Android平台开发的娱乐应用源代码,旨在提供一种轻松有趣的星座连连看游戏体验。这个项目的源码对于学习Android应用开发,尤其是游戏开发的开发者来说,是一...
【标题】"安卓Android源码——精典源码之星座连萌"是一个关于安卓应用程序开发的项目,重点在于分析和理解其源代码。这个项目的目的是为开发者提供一个学习和研究Android应用开发的实例,特别是针对游戏开发的部分。...
【标题】"安卓Android源码——[安卓开源]星座连萌.7z" 提供的是一个基于Android平台的开源项目,名为“星座连萌”。这个项目可能是为了展示Android应用程序的开发技术,或者是教学材料,让开发者能够理解并学习...
【安卓Android源码——[安卓开源]星座连萌】是一个以星座为主题的开源安卓游戏项目,其源码可供开发者学习和研究。在这个项目中,我们可以深入理解Android应用开发的基本流程、UI设计、游戏逻辑以及Android平台上的...
《Android应用源码解析——以“星座连萌”为例》 在移动开发领域,Android作为全球最广泛使用的操作系统之一,其应用开发对于学生和开发者来说是至关重要的技能。本篇文章将深入探讨一个名为“星座连萌”的Android...
这款应用可能结合了星座知识、消除类游戏玩法以及萌系元素,旨在吸引广大用户群体,尤其是喜欢星座文化和休闲游戏的玩家。 在Android应用开发中,我们通常会涉及以下几个关键知识点: 1. **项目结构**:Android...
【描述】"Android应用源码娱乐项目安卓星座连萌.zip"的描述暗示了这是一个与星座相关的游戏或应用,可能包含连连看或者匹配类的游戏玩法。源码的提供使得开发者能够深入理解如何在Android平台上实现游戏逻辑、图形...
【Android 星座连萌】是一款基于Android平台的毕业设计项目,主要展示了移动应用开发的基本技术和设计理念。这个项目可以作为Android编程初学者深入理解和实践Android应用开发的一个实例,同时也是对毕业设计者展示...
"心动连萌"可能是一款休闲益智类型的游戏,其玩法可能类似于经典的连连看,旨在吸引玩家通过匹配相同的图形来消除它们,同时可能加入了一些情感元素,使得游戏体验更加有趣。 【描述解析】 描述与标题相同,"小游戏...
《星座连萌》是一款基于Android平台的休闲游戏,其源码是学习Android开发,特别是对于初学者和进行毕业设计的学生来说,极具参考价值。通过分析和研究这份源码,我们可以深入理解Android应用开发的各个环节,包括但...
Android应用源码娱乐项目安卓星座连萌
这个项目可能是围绕星座主题设计的一款休闲游戏,命名为"星座连萌",暗示了它可能融合了星座知识与连连看或者消除类游戏玩法。通过分析这个项目的源码,我们可以深入理解Android应用开发的多个重要知识点。 1. **...