利用电脑玩android版天天连萌刷高分 二,利用计算机玩Android版“天天连萌”刷高分(一)——截图...
利用电脑玩Android版“天天连萌”刷高分(一)——截图
这几周微信游戏“天天连萌”由于第一名总是被一个同学所占据(没办法,我等级不够高游戏细胞又没他好),总在想怎么超越。正好小志同学(http://xiaozhi6156.iteye.com/)发给我一篇帖子,然后我找到原文(http://blog.csdn.net/longteng1116/article/details/12360269),向作者请教了部分问题(该文章下面还有我的大量评论呢),再琢磨了几天,终于自己也实现了这样的一个程序,利用电脑来玩“天天连萌”刷关卡和分数。
对这个程序的思路是这样子的:
1.从手机里截图到电脑。
2.解析这张图,并将其转换为二维数组。
3.循环搜索可以消除的方块对应的两个元素
4.将元素的位置转换为屏幕的坐标,然后对手机进行模拟按键
以上也将我们的焦点聚集在以下四个问题上:
1、如何截图
2、如何进行图像识别,转换为数组
3、连连看搜索算法
4、如何进行模拟按键
下面分别来看这四个问题。
一、在PC端如何对Android手机截图
在电脑端进行Android截图的方法有多种。其中最快的应该是读取/dev/graphics/fb0,但是需要对手机先进行root。如果没有root的话,需要adb连接手机,然后执行adb shell进入android手机终端,将这个目录拷贝到sdcard,然后退出再执行adb pull,将该文件取出。
从网上得到的资料是,这个文件保存了5帧的framebuffer,只要读取出第一帧再进行处理就可以了。这个没试成功,而且这步骤略显麻烦,不适合在我的程序中应用。
上面是第一种方法。
第二种,使用adb shell screencap -p命令。
使用以上命令可以将手机截屏并输出屏幕,但是adb shell在传输时会将结果里的LF转换为CR+LF,所以还需要将结果改一下。如果是linux用户,可以这样做:
adb shell screencap -p | sed 's/\r$//' > screen.png即将每一行末的回车符替换掉,再输出到screen.png。
如果是windows用户,可以先截图保存到sdcard,再使用adb pull命令将其取出。命令如下:
adb shell /system/bin/screencap -p /sdcard/tmp.png
adb pull /sdcard/screen.png d:/tmp.png
使用ImageIO类里的API可以读取这里的png图片为BufferedImage对象,当然也可以将BufferedImage对象保存为图片文件。
由于在程序里需要不停地截图,计算,所以这种方法同样不适合用在程序里。
第三种,使用android sdk里的AndroidDebugBridge。
需要引入ddmlib.jar包。然后通过调用AndroidDebugBridge.init(boolean)方法进行初始化,再调用AndroidDebugBridge.createBridge(str, boolean)创建一个AndroidDebugBridge对象,再使用AndroidDebugBridge对象的getDevices()获取所有连接的设备。该方法返回的是IDevice数组,调用IDevice对象的getScreenshot()方法就可以进行截图了。
下面附近我根据网友提供的相关代码整理之后的代码:
/*
* @(#)ScreenShot.java Project:lianmeng
* Date-Time:2013-10-11 下午1:08:36
*
* Copyright (c) 2013 CFuture09, Institute of Software,
* Guangdong Ocean University, Zhanjiang, GuangDong, China.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package pw.msdx.lianmengassistant;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import com.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.RawImage;
/**
* copy from http://bbs.csdn.net/topics/390502035. modify by Geek_Soledad
*/
public class AdbUtil {
public static IDevice connect() {
// init the lib
// [try to] ensure ADB is running
String adbLocation = System.getProperty("com.android.screenshot.bindir"); //$NON-NLS-1$
if (adbLocation != null && adbLocation.length() != 0) {
adbLocation += File.separator + "adb"; //$NON-NLS-1$
} else {
adbLocation = "adb"; //$NON-NLS-1$
}
AndroidDebugBridge.init(false /* debugger support */);
AndroidDebugBridge bridge = AndroidDebugBridge
.createBridge(adbLocation, true /* forceNewBridge */);
// we can't just ask for the device list right away, as the internal
// thread getting
// them from ADB may not be done getting the first list.
// Since we don't really want getDevices() to be blocking, we wait
// here manually.
int count = 0;
while (bridge.hasInitialDeviceList() == false) {
try {
Thread.sleep(100);
count++;
} catch (InterruptedException e) {
// pass
}
// let's not wait > 10 sec.
if (count > 100) {
System.err.println("Timeout getting device list!");
return null;
}
}
// now get the devices
IDevice[] devices = bridge.getDevices();
if (devices.length == 0) {
System.out.println("No devices found!");
return null;
}
return devices[0];
}
public static BufferedImage screenShot(IDevice device) {
RawImage rawImage;
try {
rawImage = device.getScreenshot();
} catch (Exception ioe) {
System.out.println("Unable to get frame buffer: " + ioe.getMessage());
return null;
}
// device/adb not available?
if (rawImage == null)
return null;
// convert raw data to an Image
BufferedImage image = new BufferedImage(rawImage.width, rawImage.height,
BufferedImage.TYPE_INT_ARGB);
int index = 0;
int IndexInc = rawImage.bpp >> 3;
for (int y = 0; y < rawImage.height; y++) {
for (int x = 0; x < rawImage.width; x++) {
int value = rawImage.getARGB(index);
index += IndexInc;
image.setRGB(x, y, value);
}
}
return image;
}
/**
* Grab an image from an ADB-connected device.
*/
public static boolean screenShotAndSave(IDevice device, String filepath) throws IOException {
boolean result = ImageIO.write(screenShot(device), "png", new File(filepath));
if (result) {
System.out.println("file is saved in:" + filepath);
}
return result;
}
public static void terminate() {
AndroidDebugBridge.terminate();
}
}
最后说下第四种方法。这个是我在做模拟触摸的时候看到的,也是我目前采用的做法。我在做模拟触摸这一部分,用的是chimpchat.jar包里的api(为什么没用monkeyrunner.jar包里的api,具体原因后面会提到)。这里获取的是IChimpDevice对象,它也有截图的方法,即takeSnapshot()方法,返回的是IChimpImage对象,再调用IChimpImage对象的getBufferedImage()方法即可得到屏幕截图的BufferedImage对象。
代码如下:
private IChimpDevice mChimpDevice;
private AdbBackend adbBack;
public Robot() {
mImgHash = new ImageHash();
adbBack = new AdbBackend();
mChimpDevice = adbBack.waitForConnection();
}
/**
* 截图
*/
public BufferedImage snapshot() {
IChimpImage img;
// 这里用一个while循环是有时截图时会抛出超时异常,导致返回的是null对象。
do {
img = mChimpDevice.takeSnapshot();
} while (img == null);
return img.getBufferedImage();
}
使用这种方法,截取一张图在我手机上测试,大概是1200ms左右。读取/dev/graphics/fb0文件截图,据说一秒可以截5、6张,但如果通过java来调用的话,略显蛋疼,故不用。
需要注意的是,上面对我手机的截屏,图像是竖直的,而不是水平的。
接下来是将图片转换为2维数组,用到了一个图像识别算法,这些内容将在下一节续述。
1 楼
明心Xin
2013-10-20
利用电脑玩android版天天连萌刷高分 二,利用计算机玩Android版“天天连萌”刷高分(一)——截图...相关推荐
- Android 10.0 PackageManagerService(二)权限扫描-[Android取经之路]
摘要:PackageManagerService在systemReady()后,进行了/system/etc/permissions中的各种xml进行扫描,进行相应的权限存储,供以后使用 阅读本文大约 ...
- 利用电脑玩android版天天连萌刷高分 二,利用计算机玩Android版“天天连萌”刷高分(四)——模拟按键及程序优化...
利用电脑玩Android版"天天连萌"刷高分(四)--模拟按键及程序优化 这一系列文章,没想到从去年10月份以来,写了三篇我就忘了写了,现在才想起来,所以一不小心就成了跨年系列文章 ...
- 利用电脑玩android版天天连萌刷高分 二,利用电脑玩Android版“天天连萌”刷高分(四)——模拟按键及程序优化...
这一系列文章,没想到从去年10月份以来,写了三篇我就忘了写了,现在才想起来,所以一不小心就成了跨年系列文章了. 第四篇主要是写一下如何进行模拟按键,以及对程序的一些优化以使到分数更容易达到更高的分. ...
- 计算机基础2008版第四次作业,《计算机基础(2008版)》第4次作业
<计算机基础(2008版)>第4次作业 A型题: 请从备选答案中选取一个最佳答案 A型题: 请从备选答案中选取一个最佳答案 1. 公式"=AVERAGE(C3:C5)" ...
- 计算机基础2008版第四次作业,《计算机基础(2008版)》第5次作业_满分
<计算机基础(2008版)>第5次作业_满分 (13页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 11.90 积分 <计算机基础(20 ...
- 利用电脑玩android版天天连萌刷高分 二,利用电脑玩Android版“天天连萌”刷高分(三)...
/** * 搜索,返回最优点. * * @return */ public Point search(int x, int y) { return LianlianKan.twoCornerSearc ...
- 小学二年级计算机考试,人教版二年级语文下学期期中考试试卷
人教版二年级语文下学期期中考试试卷 引导语:科学是为了那些勤奋好学的人,考试是为了让人得到提升,以下是百分网小编分享给大家的人教版二年级语文下学期期中考试试卷,欢迎阅读! 一.我会看拼音,写词语.(8 ...
- 计算机基础2008版第7次作业,中医药大学-计算机基础2008版-1-7次作业.doc
1. 计算机中用来保存程序和数据,以及运算的中间结果和最后结果的装置是 B.内存和外存 2. 计算机显示器画面的清晰度决定于显示器的 C.分辨率 3. 所谓的信息是指 D.处理后的数据 4. 用来表示 ...
- Android libyuv应用系列(二)libyuv在Android中的使用
请尊重分享成果,转载请注明出处,本文来自Coder包子哥,原文链接: http://blog.csdn.net/zxccxzzxz/article/details/53982849 上篇文章Andro ...
最新文章
- java socket超时时间_java中socket 默认超时时间 | 学步园
- tor screenrec屏幕录制+_ScreenFlow for mac(屏幕录制软件) v8.2.4中文版
- CentOS 下 yum(基于rpm的包管理工具) 命令详解
- 记:第一次更新服务器CUDA和GPU驱动
- js模块化之模块依赖处理
- 设计模式之代理模式(上) 静态代理与JDK动态代理
- docker-compose 实战案例
- php点击按钮变文字,点击按钮文字变成input框,点击保存变成文字的实现代码
- jQuery动画的实现
- pdf阅读器或知云文献阅读选中pdf文字乱码
- pci-e串口卡linux 驱动下载,PCI/PCIe卡驱动
- Norsar 3D v5.44 Linux 1CD(功能强大的正演软件)
- mysql odbc 免安装_MySQL免安装版配置
- 一月集 一个会写诗的程序员2019
- 服务器主板显示ff,MSI K9A2-CF主板显示错误代码“FF”
- canvas -小球自由落体运动
- c++之gbk和utf8编码转换
- 希尔顿携手RB和Mayo Clinic,全面升级酒店入住卫生规范
- 2018年9月CSP CCF认证考试 经验
- 二阶龙格库塔公式推导_二阶龙格—库塔公式.PPT
热门文章
- 单行显示三级分销记录(同表自join)
- java生成随机时间_Java生成某段时间内的随机时间
- 互联网“变得更安全了”只是一种错觉
- 微星MSI B360M MORTAR TITANIUM定制USB后typec不识别的问题(opencore0.6.3)
- canal实时同步oracle,canal反向同步数仓方案
- 卖货文案一:激发行动欲望
- 没考计算机二级直接能考三级?计算机三级考试考啥
- “老子化胡”和白马寺焚经
- 毕业设计-微信小程序商城
- android扣扣登录界面,手机QQ