跳一跳自动跳跃C#代码实现

最近这款“跳一跳”很火,在段子里面看到有人才放了张画着坐标的纸在手机上,说根据距离确定摁的“嘟”的次数,还有通过程序来实现自动计算的。看得心血来潮忍不住来试一试?话不多说,先上图。

因为比较急着做出成品,所以细节上没多细抠。感觉设置的跳跃速度稍快了一点,有兴趣的同学可以实测一下。也有一个因素是测试时后台程序比较多,影响了结果。
       原理其实也是跟大家想的一样很简单,无非就是三个要素:距离、速度、时间。就是通过当前小蓝人脚底所在的像素坐标和目标平台中心像素的坐标计算距离,除以事先通过测试得出的速度,得出触摸屏幕时间,由程序发出“触摸”指令,实现定点跳跃。不过在做自动计算跳跃所需触摸时间之前还是要做一些准备功夫的。下面直接说一下详细的过程吧。

准备工作:

1、通过PS等工具获取①小蓝人最底下一行(作为当前位置Y坐标)和最左边一列(作为当前位置X坐标)的像素RGB,实测在本机基本都是一样的X(54,63, 102),Y(43, 43, 73)。图片左上角、右下角坐标分别为[0,0][Xmax,Ymax]。②获取小蓝人的头的宽度(所占像素点)。③获取左上角分数最底下一行的像素y坐标。

2、通过指令

adb shell input touchscreen swipe x y x y 延时(ms)

(x、y为触摸屏幕的坐标),结合photoshop测试出“跳一跳”每一条的速度。本例中测得结果约为17 / 24(pixel/ms),实际游戏中的速度略小于这个速度。大家用代码可以精确测一下,我已经没耐心了0.0。

3、电脑准备好调试环境(因为穷所以测试用的是自己的Android机,所以要准备好ADK(platform-tools/adb.exe);另外本次测试语言是C#)

4、手机开启调试模式,连接电脑,打开“跳一跳”

过程:

一、获取设备号(获取序列号,或者直接查看手机信息),指令:

adb devices 

二、截取手机当前画面到sd卡(本机存储格式为png,实测手机按键截屏为jpg(失真)),指令:

adb -s 设备号 shell screencap -p /sdcard/temp.png

三、复制文件到电脑,指令:

adb -s 设备号 pull /sdcard/temp.png 保存路径

四、删除文件,指令:

adb -s 设备号 shell rm /sdcard/temp.png

五、获取小蓝人脚底像素坐标和目标平台中心像素坐标,下面详细说说里面的步骤

1、通过Bitmap类读取图片,再用unsafe代码利用指针把RGB数据直接从内存拷出来存放到byte数组中(这步其实不用也可以但不知道直接通过Bitmap获取像素效率会不会很低,大家可以测了分享一下结果)
2、用两层循环y从max->0,遍历x轴像素,通过对比找出小蓝人位置,本例通过两个rgb像素的标准差不超过3作为置信偏差判断两个像素是否为同一元素。再稍微处理一下就可得出当前坐标。
3、利用上面得到的坐标P以及一开始准备工作中提到的分数底行y坐标(取大于该y作为startY即可)再进行对目标坐标的搜索:用两层循环y从startY->Py,遍历x轴像素(利用P的x坐标缩小搜索的x坐标范围:若x位于左半屏则搜索Px+40->Xmax,反之搜索0->Px-40,注:不缩小范围会出错,原因大家想想)。(这个40可取大于小蓝人头宽度一半的值即可)
4、那就用我们的勾三股四弦五定理再开根求出距离。距离除以速度得出时间。

六、发送触摸指令实现定时跳跃,指令:

adb shell input touchscreen swipe x y x y延时(ms)

这里不得不说一下,当时找半天找不到定时触摸的指令,网上有个用6个指令组合实现定时触摸屏幕的方法,但实测无效,而且也怕指令这么多,延时还是分开控制,肯定会对跳跃结果有很大影响。后面看到一条利用swipe指令实现的评论,真是醒目。swipe虽然是滑动指令,但如果设置起止坐标都是同一个坐标不就相当于实现了定点定时触摸了吗。

七、七就是一直重复二~六的步骤就是了。

本次测试很东西都是急着做,没仔细研究,例如获取跳跃速度这个就是傻瓜式的通过手动发送跳跃指令、截图用ps手动计算出来的。大家可以用代码实现一下。希望大家指正可以改进的地方。

C#源码如下

Cmd类,实现cmd执行命令

class Cmd
{
 private System.Diagnostics.Process process;
 private bool isExecuted; // 是否执行过命令
 private string command; // 上次执行命令
 private int result;  // 上次执行命令结果
 private string resultContent; // 上次执行命令返回结果
 public Cmd()
 {
 process = new System.Diagnostics.Process();
 process.StartInfo.FileName = "cmd.exe";
 process.StartInfo.UseShellExecute = false; //是否使用操作系统shell启动
 process.StartInfo.RedirectStandardInput = true;//接受来自调用程序的输入信息
 process.StartInfo.RedirectStandardOutput = true;//由调用程序获取输出信息
 process.StartInfo.RedirectStandardError = true;//重定向标准错误输出
 process.StartInfo.CreateNoWindow = true;//不显示程序窗口 

 isExecuted = false;
 }
 public int ExecuteCmd(string cmd)
 {
 command = cmd;
 try
 {
  process.Start();
  process.StandardInput.WriteLine(cmd + "&exit");
  process.StandardInput.AutoFlush = true;
  string content = process.StandardOutput.ReadToEnd();
  process.WaitForExit();//等待程序执行完退出进程
  process.Close(); 

  result = 0;
  resultContent = content.Split(new string[] { "&exit" }, StringSplitOptions.None)[1].Replace("\n", "");
 }
 catch (Exception ex)
 {
  result = -1;
  resultContent = ex.Message;
 } 

 if (!isExecuted) isExecuted = true; 

 return result;
 }
 private int ExecuteCmd(string adbPath, string cmd)
 {
 command = $"\"{adbPath}\" {cmd}";
 try
 {
  process.Start();
  process.StandardInput.WriteLine(command + "&exit");
  process.StandardInput.AutoFlush = true;
  string content = process.StandardOutput.ReadToEnd();
  process.WaitForExit();//等待程序执行完退出进程
  process.Close(); 

  result = 0;
  resultContent = content.Split(new string[] { "&exit" }, StringSplitOptions.None)[1].Replace("\n", "");
 }
 catch (Exception ex)
 {
  result = -1;
  resultContent = ex.Message;
 } 

 if (!isExecuted) isExecuted = true; 

 return result;
 }
 public string GetExcResult()
 {
 if (isExecuted)
 {
  if (result == 0)
  {
  return resultContent;
  }
  else
  {
  return $"Execute Failed! Command:{command}\n{resultContent}";
  }
 }
 else
 {
  return "从未执行过命令";
 }
 }
 public void DisposeProcess()
 {
 process.Dispose();
 }
} 

class Pixel
{
 public byte[] pixel = new byte[3];
 public Pixel()
 { 

 }
}

Pixel类,存放RGB字节

class Pixel
 {
 public byte[] pixel = new byte[3];
 public Pixel()
 { 

 }
 }

PlayJumpJump类,实现主要分析计算和跳跃操作

class PlayJumpJump
 {
 private static readonly int confidenceItv = 3; // 两个rgb标准差小于等于3认为是同一元素
 private static readonly Pixel manXRgb = new Pixel { pixel = new byte[] { 54, 63, 102 } }; // 小人X坐标rgb
 private static readonly Pixel manYRgb = new Pixel { pixel = new byte[] { 43, 43, 73 } }; // 小人Y坐标rgb
 private static readonly double startYPer = 0.15625; // 分数下一行Y为第289,取 300 / 1920 = 0.15625, 从下一行开始搜索目标
 private static readonly double Speed = 17.0 / 24; // 速度,最重要的因素,这也是约摸算出来的
 private static readonly string[] TouchCoor = new string[] { "800", "1700" }; // 触屏位置
 private static readonly string Format = "png"; // 本人用机子截取为png,也可不设格式(实测bitmap与ps cc打开同一jpg,同一像素点rgb值不一致,怀疑是bitmap打开jpg会有失真)
 private static readonly string TempDir = "/sdcard/";
 private static readonly string SaveDir = "temp/";
 private static readonly string CaptureScreen_Command = $"-s {{0}} shell screencap -p {TempDir}{{1}}";
 private static readonly string CopyFile_Command = $"-s {{0}} pull {TempDir}{{1}} \"{SaveDir}{{1}}\"";
 private static readonly string RemoveFile_Command = $"-s {{0}} shell rm {TempDir}{{1}}";
 private static readonly string LongPress_Command = "shell input touchscreen swipe {0} {1} {0} {1} {2}";
 private Cmd myCmd;
 private string adbCmdPrefix;
 private string result;
 public List<string> devices; 

 public PlayJumpJump(string adbPath)
 {
  myCmd = new Cmd();
  adbCmdPrefix = $"\"{adbPath}\" ";
  if (!Directory.Exists(SaveDir))
  {
  Directory.CreateDirectory(SaveDir);
  }
 }
 public void Init()
 {
  myCmd = new Cmd();
 }
 public bool GetDevices()
 {
  devices = new List<string>();
  myCmd.ExecuteCmd(ReturnCommand("devices"));
  result = myCmd.GetExcResult();
  foreach (string line in result.Split(new char[] { '\n'}))
  {
  if (line.Contains("device"))
  {
   List<string> items = line.Split(new char[] { '\t', '\r' }, StringSplitOptions.None).ToList();
   if (items.Count > 1)
   {
   devices.Add(items[items.IndexOf("device") - 1]);
   }
  }
  }
  return devices.Count > 0 ? true : false;
 }
 public string CaptureScreen()
 {
  string fileName = $"temp{DateTime.Now.ToString("HHmmssfff")}.{Format}";
  myCmd.ExecuteCmd(ReturnCommand(CaptureScreen_Command, new string[] { devices[0], fileName }));
  myCmd.ExecuteCmd(ReturnCommand(CopyFile_Command, new string[] { devices[0], fileName }));
  myCmd.ExecuteCmd(ReturnCommand(RemoveFile_Command, new string[] { devices[0], fileName }));
  return AppDomain.CurrentDomain.BaseDirectory + SaveDir + fileName;
 }
 public static unsafe Pixel[][] GetPixelArray(string path)
 {
  Bitmap bitmap = new Bitmap(path);
  int depth = Image.GetPixelFormatSize(bitmap.PixelFormat);
  if (depth == 24)
  {
  int width = bitmap.Width;
  int height = bitmap.Height;
  Pixel[][] pixelArray = new Pixel[height][];
  for (int i = 0; i < pixelArray.Length; i++) pixelArray[i] = new Pixel[width]; 

  Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
  BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); 

  byte* ptr = (byte*)bmpData.Scan0;
  for (int i = 0; i < pixelArray.Length; i++)
  {
   for (int j = 0; j < pixelArray[i].Length; j++)
   {
   pixelArray[i][j] = new Pixel { pixel = new byte[] { *(ptr + 2), *(ptr + 1), *ptr } };
   ptr += 3;
   }
   ptr += bmpData.Stride - 3 * bmpData.Width; // 减去占位字节(可能出于性能或兼容性考虑,Stride为4的倍数)
  } 

  bitmap.UnlockBits(bmpData);
  return pixelArray;
  }
  else if (depth == 32)
  {
  int width = bitmap.Width;
  int height = bitmap.Height;
  Pixel[][] pixelArray = new Pixel[height][];
  for (int i = 0; i < pixelArray.Length; i++) pixelArray[i] = new Pixel[width]; 

  Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
  BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb); 

  byte* ptr = (byte*)bmpData.Scan0;
  for (int i = 0; i < pixelArray.Length; i++)
  {
   for (int j = 0; j < pixelArray[i].Length; j++)
   {
   pixelArray[i][j] = new Pixel { pixel = new byte[] { *(ptr + 2), *(ptr + 1), *ptr } };
   ptr += 4; // 每3个字节忽略1个透明度字节
   }
  } 

  bitmap.UnlockBits(bmpData);
  return pixelArray;
  }
  else
  {
  return null;
  }
 }
 public void Jump2Happy()
 {
  string picture = CaptureScreen();
  Pixel[][] pixelArray = GetPixelArray(picture);
  int[] curCoor = GetCurCoordinates(pixelArray);
  int[] destCoor = GetDestCoordinates(pixelArray, curCoor);
  double distance = Math.Round(Math.Sqrt(Math.Pow(Math.Abs(destCoor[0] - curCoor[0]), 2) + Math.Pow(Math.Abs(destCoor[1] - curCoor[1]), 2)), 3);
  int time = (int)(distance / Speed);
  Console.WriteLine($"from [{curCoor[0]},{curCoor[1]}]\tto [{destCoor[0]},{destCoor[1]}] distance≈{distance} take≈{time}ms ==>> Jump ");
  myCmd.ExecuteCmd(ReturnCommand(LongPress_Command, new string[] { TouchCoor[0], TouchCoor[1], time.ToString() }));
 }
 public static int[] GetCurCoordinates(Pixel[][] pixelArray)
 {
  int[] coordinates = new int[2];
  List<int[]> xList = new List<int[]>();
  List<int[]> yList = new List<int[]>();
  // y从max -> 0,遍历x轴像素
  for (int i = pixelArray.Length - 1; i >= 0; i--)
  {
  for (int j = 0; j < pixelArray[i].Length; j++)
  {
   if (isSameElement(pixelArray[i][j], manXRgb, confidenceItv))
   {
   xList.Add(new int[] { j, i });
   }
  }
  if (xList.Count > 0) break;
  }
  coordinates[0] = xList.Count > 0 ? (xList[0][0] + xList[xList.Count - 1][0]) / 2 : 0; 

  // x从0 -> max,遍历y轴像素
  for (int i = 0; i < pixelArray[0].Length; i++)
  {
  for (int j = pixelArray.Length - 1; j >= 0; j--)
  {
   if (isSameElement(pixelArray[j][i], manYRgb, confidenceItv))
   {
   yList.Add(new int[] { i, j });
   }
  }
  if (yList.Count > 0) break;
  }
  coordinates[1] = yList.Count > 0 ? (yList[0][1] + yList[yList.Count - 1][1]) / 2 : 0; 

  return coordinates;
 }
 public static int[] GetDestCoordinates(Pixel[][] pixelArray, int[] curCoor)
 {
  Pixel enviRgb; // 排除rgb采样
  Pixel destRgb = null; // 采样
  int[] coordinates = new int[2];
  List<int[]> xList = new List<int[]>();
  List<int[]> yList = new List<int[]>();
  int startY = (int)(pixelArray.Length * startYPer);
  int start, end, inc;
  if (curCoor[0] < (pixelArray[0].Length / 2))
  {
  start = curCoor[0] + 40;
  end = pixelArray[0].Length;
  }
  else
  {
  start = 0;
  end = curCoor[0] - 40;
  }
  // y从0 -> max,遍历x轴像素
  for (int i = startY; i < pixelArray.Length; i++)
  {
  enviRgb = pixelArray[i][0];
  for (int j = start; j < end; j++)
  {
   if (!isSameElement(pixelArray[i][j], enviRgb, confidenceItv))
   {
   xList.Add(new int[] { j, i });
   if (destRgb == null) destRgb = pixelArray[i][j];
   }
  }
  if (xList.Count > 0) break;
  }
  coordinates[0] = xList.Count > 0 ? (xList[0][0] + xList[xList.Count - 1][0]) / 2 : 0; 

  // x从0 -> max,遍历y轴像素
  if (coordinates[0] < (pixelArray[0].Length / 2))
  {
  start = 0;
  end = pixelArray[0].Length - 1;
  inc = 1;
  }
  else
  {
  start = pixelArray[0].Length - 1;
  end = 0;
  inc = -1;
  }
  bool isFond = false;
  for (int i = start; i != end; i+=inc)
  {
  for (int j = startY; j < curCoor[1]; j++)
  {
   if (isSameElement(pixelArray[j][i], destRgb, confidenceItv))
   {
   coordinates[1] = j;
   isFond = true;
   break;
   }
  }
  if (isFond) break;
  } 

  return coordinates;
 }
 public static bool isSameElement(Pixel pixel1, Pixel pixel2, int confidence)
 {
  return Math.Pow(pixel1.pixel[0] - pixel2.pixel[0], 2) + Math.Pow(pixel1.pixel[1] - pixel2.pixel[1], 2) + Math.Pow(pixel1.pixel[2] - pixel2.pixel[2], 2) <= 3 * Math.Pow(confidence, 2);
 }
 public string ReturnCommand(string command, string[] parameter)
 {
  return adbCmdPrefix + string.Format(command, parameter);
 }
 public string ReturnCommand(string command, string parameter)
 {
  return adbCmdPrefix + string.Format(command, parameter);
 }
 public string ReturnCommand(string command)
 {
  return adbCmdPrefix + command;
 }
 public void DisposeProcess()
 {
  myCmd.DisposeProcess();
  myCmd = null;
 }

测试:

static void Main(string[] args)
 {
  string adbPath = ""; // adb.exe路径 

  PlayJumpJump testPlay = new PlayJumpJump(adbPath);
  if (testPlay.GetDevices())
  {
  while (true)
  {
   testPlay.Jump2Happy();
   Thread.Sleep(1200);
  }
  } 

  testPlay.DisposeProcess(); 

  Console.ReadKey();
 }
 }

更多内容大家可以参考专题《微信跳一跳》进行学习。

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

(0)

相关推荐

  • C#实现微信跳一跳小游戏的自动跳跃助手开发实战

    一.前言: 前段时间微信更新了新版本后,带来的一款H5小游戏"跳一跳"在各朋友圈里又火了起来,类似以前的"打飞机"游戏,这游戏玩法简单,但加上了积分排名功能后,却成了"装逼"的地方,于是很多人花钱花时间的刷积分抢排名.后来越来越多的聪明的"程序哥们"弄出了不同方式不同花样的跳一跳助手(外挂?),有用JS实现的.有JAVA实现的.有Python实现的,有直接物理模式的.有机械化的.有量尺子的等等,简直是百花齐放啊-- 赶一下潮流

  • C#图像识别 微信跳一跳机器人

    更新 GitHub中所有类库的源码已经转换为C#版本. 准备 IDE:VisualStudio Language:C#/VB.NET GitHub:AutoJump.NET 本文将向你介绍一种通过图像识别实现"跳一跳"机器人的方法. 第一节 图像识别 文中提到的所有方法和步骤只涉及简单的向量计算. 需要用到哪些计算? 比较像素点的颜色 求向量集合的中心 计算颜色的相似度 一个RGB颜色可以看作一个三维向量 比较两个颜色的相似度可以计算它们的欧几里得距离 也可以直接比较它们的夹角:夹角越

  • 微信跳一跳自动脚本C#代码实现

    前言 CSDN前阵子推送了篇文章,讲的是微信跳一跳的技术实现,大致浏览,发现难度不高,很适合练手. 思路 ADB得到屏幕截图,转换成bitmap逐像素分析图像,得到跳跃起点和终点坐标,最后ADB按压屏幕进行跳跃 相关知识 ADB创建 ·在https://adb.clockworkmod.com提前下载ADB ·通过 Process类 创建进程运行ADB Process p = new Process(); p.StartInfo = new ProcessStartInfo() { FileNa

  • 跳一跳自动跳跃C#代码实现

    最近这款"跳一跳"很火,在段子里面看到有人才放了张画着坐标的纸在手机上,说根据距离确定摁的"嘟"的次数,还有通过程序来实现自动计算的.看得心血来潮忍不住来试一试?话不多说,先上图. 因为比较急着做出成品,所以细节上没多细抠.感觉设置的跳跃速度稍快了一点,有兴趣的同学可以实测一下.也有一个因素是测试时后台程序比较多,影响了结果.        原理其实也是跟大家想的一样很简单,无非就是三个要素:距离.速度.时间.就是通过当前小蓝人脚底所在的像素坐标和目标平台中心像素的

  • 使用Python实现跳一跳自动跳跃功能

    1.   OpenCV:模板匹配.    获得小跳棋中心位置 2.   OpenCV:边缘检测.    获得下一方块中心位置 Python+ADB+OpenCv,实现「 跳一跳 」自动化. / 01 / ADB ADB工具即Android Debug Bridge(安卓调试桥) tools. ADB 是一个命令行窗口,用于通过电脑端与模拟器或者真实设备交互. 与之前小F接触过的Appium有点相似. ADB的安装很简单,就是将安装包解压后,将路径添加到系统的环境变量中即可. 然后使用Python

  • 微信跳一跳自动运行python脚本

    本文实例为大家分享了微信小程序跳一跳自动运行脚本,供大家参考,具体内容如下 1.压缩包带了adb等必须工具,配置一下环境变量即可 2.Python 直接运行即可 (Python3.6) 代码: wechat_jump_auto.py # coding: utf-8 ''' # === 思路 === # 核心:每次落稳之后截图,根据截图算出棋子的坐标和下一个块顶面的中点坐标, # 根据两个点的距离乘以一个时间系数获得长按的时间 # 识别棋子:靠棋子的颜色来识别位置,通过截图发现最下面一行大概是一条

  • 安卓版本微信跳一跳自动执行代码剖析

    手动版的这里不多说,图像识别,坐标计算跳跃,要想得高分会点的手疼.这里主要剖析下自动版的,这里仅介绍安卓版本. 整体的结构 脚本的整体结构还是比较简洁的,如下图所示. 手机连接PC,PC通过adb命令对手机游戏界面进行截图: PC通过adb命令将该截图拷贝回PC: PC端通过python对图像进行处理(第一版中使用的opencv,目前使用的是直接读取像素的rgb值),获取棋子的位置,获取下一个棋盘的位置,然后计算出下一跳的距离,从而根据经验值计算出按压时间t: 通过adb命令模拟按压时间t即可实

  • 微信跳一跳游戏Android刷分代码

    本文实例为大家分享了微信跳一跳游戏Android实现刷分,供大家参考,具体内容如下 # coding:utf-8 ''' # === 思路 === # 核心:每次落稳之后截图,根据截图算出棋子的坐标和下一个块顶面的中点坐标, # 根据两个点的距离乘以一个时间系数获得长按的时间 # 识别棋子:靠棋子的颜色来识别位置,通过截图发现最下面一行大概是一条直线,就从上往下一行一行遍历, # 比较颜色(颜色用了一个区间来比较)找到最下面的那一行的所有点,然后求个中点, # 求好之后再让 Y 轴坐标减小棋子底

  • 微信跳一跳python自动代码解读1.0

    微信跳一跳自动代码,具体内容如下 那个跳一跳python"外挂",有几个python文件,其中有一个是得到截图,然后鼠标在图片上点击两次,python窗口上会打印两次鼠标的位置,并且会跟上一行这两个点之间的距离. 这个功能我先给除去获取截屏,就说怎么在某张图片上算出两次点击的距离. 首先,需要用到图形模块,PIL: from PIL import Image img = Image.open('0.jpg') 然后用图形绘制模块matplotlib来给出一个plot对象: import

  • python微信跳一跳游戏辅助代码解析

    这个代码实现的是   手动点击起点 和 终点  ,程序自动判断距离.触屏时间  完成跳跃 原理(摘自项目说明页面): 1. 将手机点击到"跳一跳"小程序界面: 2. 用Adb 工具获取当前手机截图,并用adb将截图pull上来: adb shell screencap -p /sdcard/1.png adb pull /sdcard/1.png . 3. 用matplot显示截图: 4. 用鼠标点击起始点和目标位置,计算像素距离: 5. 根据像素距离,计算按压时间: 6. 用Adb工

  • 微信跳一跳python辅助脚本(总结)

    这段时间微信跳一跳这个游戏非常火爆,但是上分又非常的难,对于程序员来说第一个念头就是通过写一个辅助脚本外挂让上分变的容易,python现在比较火,我们一起来以python语言为基础总结以下各路神仙写的关于跳一跳的辅助脚本,大家在学习的时候主要理解他们的写法思路,对你学习python非常的有帮助. 1.微信跳一跳自动运行python脚本 注解:思路 核心:每次落稳之后截图,根据截图算出棋子的坐标和下一个块顶面的中点坐标, 根据两个点的距离乘以一个时间系数获得长按的时间 识别棋子:靠棋子的颜色来识别

  • 基于VS+Opencv2.4.10微信跳一跳辅助工具

    最近微信的跳一跳小程序可谓火了一把,不是因为它本身多好玩,而是有大部分的程序员们加入其中,利用各种领域方法,实现了微信跳一跳的外挂,分数轻松上千或上万.之前也看了基于Python开源的代码,GitHub上现在的star已经快超过1W了,简直不敢想.趁着今天礼拜天,在实验室中也简单的实现了一下微信跳一跳的辅助工具,精度还不够高,我跑了一下才到90,纯属娱乐好玩的,后期再继续改进,主要是依赖C++来实现了一下. 环境: Win10+VS2012+Opencv2.4.10+ADB工具 环境的搭建请查阅

随机推荐