最近春节,qq上出了一个叫穿越福城的小游戏。游戏的玩法类似挑一挑,也是通过一个个木桩。只不过把跳的过程变成了搭梯子。按的时间越长,梯子越长。梯子过长或者过短小企鹅都会掉下去,游戏失败。我的目的是用python来实现自动玩游戏。(主要原因是我手残。。没办法,只好另辟蹊径,技术开挂)。在刚开始构思的时候,我其实是觉得挺简单的一个小脚本就能搞定。但是在实际编码和测试的过程中,我越发觉得想要完成一个简陋版本,勉强能用的版本非常容易。但是想要做到稳定性好,准确率高实在是不容易。下面我就把我这两天的编码和完善过程记录下来。

先说说我的总体思路。通过adb的截图功能获得截图,然后根据获得的截图计算出应该按压多少毫秒,再通过adb shell input swipe来按压指定毫秒数。循环往复,理论上可以一直刷到无限分。

这里面的难点显然是在第二步,即怎样根据截图计算毫秒数呢?

那我们首先要思考毫秒数和什么变量有关,再从图片中提取或者计算出变量即可。梯子是按得时间越长就越长,所以可以认为按得时间t应该和木桩之间的距离成线性关系。那我们怎样从图片上计算起始木桩和目标木桩之间的距离呢?第一想法肯定是在图片中找到起始点x0,y0,再找到目的点x1,y1.计算这两个点的欧氏距离。但是玩这个游戏会发现,如果木桩之间的距离很长,游戏中会拉高视角。所以要想获得木桩之间的实际距离,不能光考虑像素之间的距离,还要考虑视角高度。视角越高,一个像素点代表的实际距离就越长。所以综上,时间和两个因素有关,一是像素距离,而是视角高度。

第一个因素像素距离,想要获取这个参数的关键在于怎样确定起点和终点。一个图片在计算机中就是一个矩阵,在矩阵中怎样找到起点和终点?这就需要明确起点和终点的特征。根据特征找到满足特征的像素,进而就可以找到起点和终点。从截图可以发现,起点的明显特征就是深色的小企鹅,在明艳的背景中,只有小企鹅是深色的。所以找图片中rgb均小于50的像素点,就可以定位小企鹅所在的位置。终点就更好确定了,每个木桩的中心都有一块红色菱形。这些红色菱形的rgb都是一样的。找这个rgb值就可以找到这些菱形,那么怎么知道哪个菱形是目标点呢?观察可知,在小企鹅上方的,且满足红色菱形的是目标点。找到了起点和终点,我们就可以算出来dis(distance)

第二个因素是视角高度。这个就比较抽象了,改用什么表示呢?视角高度不好直接计算,但是有办法体现出来。视角高度越高,相同面积的东西所占的像素数量就越少,也就是近大远小。而观察游戏可知,每个木桩上的红色菱形的面积是一定的。所以我们可以用目标点红色菱形的像素数(size)来表示视角高度。像素数越多,视角高度越低;像素数越少,视角高度越高。

现在找到了计算dis和size的方法,那么按压时间t怎么计算呢?首先设置一个参数a,用于调整系数。

t = a*dis/sqrt(size)

dis越大,显然按压时间应该越长。size越大,说明视角越低,显然按压时间应该越短。那么为什么size要开一个平方根呢?这是因为dis是一次的长度,而size是二次的面积。所以要开一个平方根,保证量纲一致。a由实验测得。经过实验我发现a=30左右的时候,程序运行良好,虽然做不到每次都非常精准,但是大部分时候都是可以通过的。

到这里为止,我的小程序已经基本可以大部分时候100+了。运气比较好的时候我还拿到了273分。但是在一次次测试中也暴露出了很多问题。接下来开始我的调试之路。

1、广告干扰

观察上图,本来我的起始点是根据颜色判断的。结果广告中也出现了相同的色彩,从颜色来确定起始点的路子走不通了,怎么办?那只好找其他特征。什么特征呢?那就是

1、企鹅是实心的

2、企鹅是近似圆形的

我之前都是用PIL的,现在不根据颜色了,就需要用更加高级和复杂的python-opencv了。先二值化,只保留深色部分,然后用findContours找边缘,然后筛选出满足条件的contour即可。这样一来找对起点的准确率就极高啦。

第二个问题:准确率不高。显然我建立的模型和游戏的内部逻辑还是有一定的差距。

怎么解决?从数学上来说,就是要确定一个二元函数time=f(dis,size).为了找到这个函数到底是啥,我首先得采集足够多的样本点。

采集了300个样本点后,绘制出dis-size函数,发现如下图所示

这说明和我原先想的不一样,这不是一个连续函数,而是一个离散的函数。(dis,size)一共只有十六中组合。

既然这样就好办了。先kmeans聚类,划分成16类,找到每一类的dis,size,time,作为table记录到程序中。每次获得一个dis和size,查找table,找到最先进的dis和size所对应的time,然后用adb按相应的time即可。

经过这么已改进,准确率极高。几乎每一次都是三分。当然其中的time参数由于是取得平均数,和真正的准确值还有一定的差距,在偶尔不是三分的情况下还要对time进行改进。

经过这些改进这个程序可以说已经基本可以跑了。我写了两个版本的代码,一个是aaa.py,这个是使用t=dis/sqrt(size)方法的;另一个是bbb.py,这个是使用table版本的。table版本的正确率更加高。

代码放在github上:https://github.com/blacksungrass/pythons/tree/master/qq%E6%96%B0%E5%B9%B4%E5%B0%8F%E6%B8%B8%E6%88%8F%E8%87%AA%E5%8A%A8%E5%8C%96

即使经过了改进,还是有一些问题,不过出现的次数很少

1、这个小企鹅有时候会跳起来转个圈,截图如果截取的是小企鹅挑起来的图会造成误判断

2、有时候游戏中的一些背景建筑,尤其是塔之类的,会把小企鹅挡住一小块,导致findContours函数无法将小企鹅识别为一个整体。

用python来自动玩类似跳一跳的小游戏的更多相关文章

  1. Python 帮你玩微信跳一跳 GitHub Python脚本

    前言想自己搞游戏小程序的 在github 有人已经利用 python程序, 通过adb 获取不同型号安卓手机的系统截图,然后通过计算小人与目标位置距离之后得到准确的触摸时间,再通过 开发者模式里的 a ...

  2. 教你用.Net来玩微信跳一跳

    目前开发的所有代码都已经上传到了GitHub.欢迎大家来Star https://github.com/GiantLiu/AutoJump 目前程序分为“全自动版本”和“半自动版本” 全自动版本 We ...

  3. 用python实现自动玩21点小游戏

    1. 背景 前段时间发现一个论坛上(https://npupt.com/blackjack.php)有21点小游戏. 这个21点小游戏的规则是每个人开局都会获得随机点数,如果觉得点数小,可以继续摸牌. ...

  4. 用Python来玩微信跳一跳

    微信2017年12月28日发布了新版本,在小程序里面有一个跳一跳小游戏,试着点一点玩了下.第二天刚好在一篇技术公众号中,看到有大神用Python代码计算出按压时间,向手机发送android adb命令 ...

  5. 利用Python玩微信跳一跳

    创建python项目jump_weixin,新建python程序jump.py 需要4个辅助文件[adb.exe,AdbWinApi.dll,AdbWinUsbApi.dll,fastboot.exe ...

  6. Python程序,辅助微信跳一跳游戏介绍

    一.思路介绍 1. 通过Python自动手机截屏,并保存到电脑 2. 通过PhotoShop测量要跳的距离 3. 通过Excel计算按压时间 4. 通过CMD命令控制手机按压时间 二.实现方法详解 1 ...

  7. 了解python,利用python来制作日常猜拳,猜价小游戏

    初次接触python,便被它简洁优美的语言所吸引,正所谓人生苦短,python当歌.python之所以在最近几年越发的炽手可热,离不开它的一些特点: 1.易于学习:Python有相对较少的关键字,结构 ...

  8. python学习笔记(五) 200行实现2048小游戏

    用前文提到的基础知识,和网上流行的2048源码,用python实现该游戏. 先将用户操作和游戏逻辑绑定. WASD分别对应移动方向上.左.下.右 然后实现矩阵的转置和逆置,这样只要实现一个方向的移动, ...

  9. 用 Python 编写剪刀、石头、布的小游戏(快速学习python语句)

    import random#定义手势类型allList = ['石头','剪刀','布']#定义获胜的情况winList = [['石头','剪刀'],['剪刀','布'],['步','石头']]pr ...

随机推荐

  1. 【Java集合系列五】HashMap解析

    2017-07-31 19:36:00 一.简介 1.HashMap作用及使用场景 HashMap利用数组+单向链表的方式,实现了key-value型数据的存储功能.HashMap的size永远是2^ ...

  2. Ubuntu 17.04版本下,opencv进行源码编译安装

    本文主要针对Ubuntu 17.04版本下,opencv进行源码编译安装.开发环境主要针对python 对 openCV库的调用. 安装 gcc cmake 编译环境 sudo apt-get ins ...

  3. Python内存释放

    python自己管理内存,实际上,对于占用很大内存的对象,并不会马上释放. 举例,a=range(10000*10000),会发现内存飙升一个多G,del a 或者a=[]都不能将内存降下来.. de ...

  4. navicat for mysql 12中文破解版(安装+破解)--亲测可用

    http://www.ddooo.com/softdown/129457.htm#dltab

  5. 理解UDP协议的首部校验和校验和

    reference: https://blog.csdn.net/qiuchangyong/article/details/79945630 https://seanwangjs.github.io/ ...

  6. 阶段01Java基础day25网络编程

    26.01_网络编程(网络编程概述) A:计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源 ...

  7. java应用性能分析

    dump内存信息 通过jps -lm找到进程id jmap -dump:format=b,file=./heap.hprof <pid> 使用jprofile等分析内存占用情况 dump线 ...

  8. java 构造方法详解

    构造方法(构造器)    是一种特殊的方法,该方法只有功能:构造对象    特点:        1.没有返回值        2.构造方法的名称一定和类名一致        3.不能在构造方法中写r ...

  9. Oracle启动和关闭数据库

    本机只安装一个数据库的情况下sqlplus / as sysdba启动数据库startup关闭数据库shutdown immediate

  10. Hadoop学习------Hadoop安装方式之(一):单机部署

    Hadoop 默认模式为单机(非分布式模式),无需进行其他配置即可运行.非分布式即单 Java 进程,方便进行调试. 1.创建用户 1.1创建hadoop用户组和用户 一般我们不会经常使用root用户 ...