亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

微信跳一跳輔助Java代碼實現(xiàn)

 更新時間:2018年01月04日 15:58:50   作者:憶虎思甜  
這篇文章主要為大家詳細介紹了微信跳一跳輔助的Java代碼實現(xiàn)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下

微信跳一跳輔助的Java具體實現(xiàn)代碼,供大家參考,具體內(nèi)容如下

1.參考知乎教你用Python來玩微信跳一跳,鑒于本人Python一直都是半吊子水平,之前打算用python刷分,可無奈安裝python環(huán)境各種模塊缺失,報錯不停,于是乎,使用Java重新實現(xiàn)了一下。

2.環(huán)境配置及相關(guān)說明:

1)、Windows系統(tǒng),本人win10
2)、AVA環(huán)境安裝,JDK7以上即可
3)、安卓手機一部、數(shù)據(jù)線一條
4)、電腦安裝ADB驅(qū)動,連接安卓手機,同時打開USB調(diào)試模式
5)、打開微信小程序的跳一跳游戲,JAVA程序跑起來,具體代碼往下看
6)、本人所用為魅藍note2安卓手機,屏幕 分辨率1920x1080,不同型號的手機,可能需要調(diào)整相關(guān)參數(shù),具體看代碼注釋
7)、增加了刷分失敗后游戲自動重新開局功能
8)、娛樂而已,不要較真,據(jù)說微信官方已經(jīng)關(guān)注,分數(shù)太高可能會被清零,哈哈

3、廢話不多說,上代碼:

package com.yihusitian.gamehelper; 
 
import java.awt.image.BufferedImage; 
import java.io.BufferedReader; 
import java.io.File; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.util.Arrays; 
import java.util.concurrent.TimeUnit; 
 
import javax.imageio.ImageIO; 
 
/** 
 * 參考知乎 
 * 
 * @link <a  rel="external nofollow" rel="external nofollow" target="_blank">https://zhuanlan.zhihu.com/p/32452473</a> 
 * 
 * 跳一跳輔助 
 * 
 * @author LeeHo 
 */ 
public class JumpJumpHelper 
{ 
 
 private static final String IMAGE_NAME    = "current.png"; 
 
 private static final String STORE_DIR    = "d:/jump_screencapture"; 
 
 //數(shù)量 
 private static final int imageLengthLength  = 5; 
 
 //存放圖片的大小 
 private static final long[] imageLength    = new long[imageLengthLength]; 
 
 private final RGBInfo  rgbInfo     = new RGBInfo(); 
 
 private final String[]  ADB_SCREEN_CAPTURE_CMDS = 
              { "adb shell screencap -p /sdcard/" + IMAGE_NAME, 
   "adb pull /sdcard/current.png " + STORE_DIR }; 
 
 //截屏中游戲分數(shù)顯示區(qū)域最下方的Y坐標,300是 1920x1080的值,根據(jù)實際情況修改 
 private final int   gameScoreBottomY  = 300; 
 
 //按壓的時間系數(shù),可根據(jù)具體情況適當調(diào)節(jié) 
 private final double  pressTimeCoefficient = 1.35; 
 
 //按壓的起始點坐標,也是再來一局的起始點坐標 
 private final int   swipeX     = 550; 
 
 private final int   swipeY     = 1580; 
 
 //二分之一的棋子底座高度 
 private final int   halfBaseBoardHeight  = 20; 
 
 //棋子的寬度,從截屏中量取,自行調(diào)節(jié) 
 private final int   halmaBodyWidth   = 74; 
 
 //游戲截屏里的兩個跳板的中點坐標,主要用來計算角度,可依據(jù)實際的截屏計算,計算XY的比例 
 private final int   boardX1     = 813; 
 
 private final int   boardY1     = 1122; 
 
 private final int   boardX2     = 310; 
 
 private final int   boardY2     = 813; 
 
 /** 
  * 獲取跳棋以及下一塊跳板的中心坐標 
  * 
  * @return 
  * @author LeeHo 
  * @throws IOException 
  * @update 2017年12月31日 下午12:18:22 
  */ 
 private int[] getHalmaAndBoardXYValue(File currentImage) throws IOException 
 { 
  BufferedImage bufferedImage = ImageIO.read(currentImage); 
  int width = bufferedImage.getWidth(); 
  int height = bufferedImage.getHeight(); 
  System.out.println("寬度:" + width + ",高度:" + height); 
  int halmaXSum = 0; 
  int halmaXCount = 0; 
  int halmaYMax = 0; 
  int boardX = 0; 
  int boardY = 0; 
  //從截屏從上往下逐行遍歷像素點,以棋子顏色作為位置識別的依據(jù),最終取出棋子顏色最低行所有像素點的平均值,即計算出棋子所在的坐標 
  for (int y = gameScoreBottomY; y < height; y++) 
  { 
   for (int x = 0; x < width; x++) 
   { 
    processRGBInfo(bufferedImage, x, y); 
    int rValue = this.rgbInfo.getRValue(); 
    int gValue = this.rgbInfo.getGValue(); 
    int bValue = this.rgbInfo.getBValue(); 
    //根據(jù)RGB的顏色來識別棋子的位置, 
    if (rValue > 50 && rValue < 60 && gValue > 53 && gValue < 63 && bValue > 95 && bValue < 110) 
    { 
     halmaXSum += x; 
     halmaXCount++; 
     //棋子底行的Y坐標值 
     halmaYMax = y > halmaYMax ? y : halmaYMax; 
    } 
   } 
  } 
 
  if (halmaXSum != 0 && halmaXCount != 0) 
  { 
   //棋子底行的X坐標值 
   int halmaX = halmaXSum / halmaXCount; 
   //上移棋子底盤高度的一半 
   int halmaY = halmaYMax - halfBaseBoardHeight; 
   //從gameScoreBottomY開始 
   for (int y = gameScoreBottomY; y < height; y++) 
   { 
    processRGBInfo(bufferedImage, 0, y); 
    int lastPixelR = this.rgbInfo.getRValue(); 
    int lastPixelG = this.rgbInfo.getGValue(); 
    int lastPixelB = this.rgbInfo.getBValue(); 
    //只要計算出來的boardX的值大于0,就表示下個跳板的中心坐標X值取到了。 
    if (boardX > 0) 
    { 
     break; 
    } 
    int boardXSum = 0; 
    int boardXCount = 0; 
    for (int x = 0; x < width; x++) 
    { 
     processRGBInfo(bufferedImage, x, y); 
     int pixelR = this.rgbInfo.getRValue(); 
     int pixelG = this.rgbInfo.getGValue(); 
     int pixelB = this.rgbInfo.getBValue(); 
     //處理棋子頭部比下一個跳板還高的情況 
     if (Math.abs(x - halmaX) < halmaBodyWidth) 
     { 
      continue; 
     } 
 
     //從上往下逐行掃描至下一個跳板的頂點位置,下個跳板可能為圓形,也可能為方框,取多個點,求平均值 
     if ((Math.abs(pixelR - lastPixelR) + Math.abs(pixelG - lastPixelG) + Math.abs(pixelB - lastPixelB)) > 10) 
     { 
      boardXSum += x; 
      boardXCount++; 
     } 
    } 
 
    if (boardXSum > 0) 
    { 
     boardX = boardXSum / boardXCount; 
    } 
   } 
 
   //按實際的角度來算,找到接近下一個 board 中心的坐標 
   boardY = (int) (halmaY - Math.abs(boardX - halmaX) * Math.abs(boardY1 - boardY2) 
     / Math.abs(boardX1 - boardX2)); 
   if (boardX > 0 && boardY > 0) 
   { 
    int[] result = new int[4]; 
    //棋子的X坐標 
    result[0] = halmaX; 
    //棋子的Y坐標 
    result[1] = halmaY; 
    //下一塊跳板的X坐標 
    result[2] = boardX; 
    //下一塊跳板的Y坐標 
    result[3] = boardY; 
    return result; 
   } 
  } 
 
  return null; 
 } 
 
 /** 
  * 執(zhí)行命令 
  * 
  * @param command 
  * @author LeeHo 
  * @update 2017年12月31日 下午12:13:39 
  */ 
 private void executeCommand(String command) 
 { 
  Process process = null; 
  try 
  { 
   process = Runtime.getRuntime().exec(command); 
   System.out.println("exec command start: " + command); 
   process.waitFor(); 
   BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); 
   String line = bufferedReader.readLine(); 
   if (line != null) 
   { 
    System.out.println(line); 
   } 
   System.out.println("exec command end: " + command); 
  } 
  catch (Exception e) 
  { 
   e.printStackTrace(); 
  } 
  finally 
  { 
   if (process != null) 
   { 
    process.destroy(); 
   } 
  } 
 } 
 
 /** 
  * ADB獲取安卓截屏 
  * 
  * @author LeeHo 
  * @update 2017年12月31日 下午12:11:42 
  */ 
 private void executeADBCaptureCommands() 
 { 
  for (String command : ADB_SCREEN_CAPTURE_CMDS) 
  { 
   executeCommand(command); 
  } 
 } 
 
 /** 
  * 跳一下 
  * 
  * @param distance 
  * @author LeeHo 
  * @update 2017年12月31日 下午12:23:19 
  */ 
 private void doJump(double distance) 
 { 
  System.out.println("distance: " + distance); 
  //計算按壓時間,最小200毫秒 
  int pressTime = (int) Math.max(distance * pressTimeCoefficient, 200); 
  System.out.println("pressTime: " + pressTime); 
  //執(zhí)行按壓操作 
  String command = String.format("adb shell input swipe %s %s %s %s %s", swipeX, swipeY, swipeX, swipeY, 
    pressTime); 
  System.out.println(command); 
  executeCommand(command); 
 } 
 
 /** 
  * 再來一局 
  * 
  * @author LeeHo 
  * @update 2017年12月31日 下午12:47:06 
  */ 
 private void replayGame() 
 { 
  String command = String.format("adb shell input tap %s %s", swipeX, swipeY); 
  executeCommand(command); 
 } 
 
 /** 
  * 計算跳躍的距離,也即兩個點之間的距離 
  * 
  * @param halmaX 
  * @param halmaY 
  * @param boardX 
  * @param boardY 
  * @return 
  * @author LeeHo 
  * @update 2017年12月31日 下午12:27:30 
  */ 
 private double computeJumpDistance(int halmaX, int halmaY, int boardX, int boardY) 
 { 
  return Math.sqrt(Math.pow(Math.abs(boardX - halmaX), 2) + Math.pow(Math.abs(boardY - halmaY), 2)); 
 } 
 
 public static void main(String[] args) 
 { 
  try 
  { 
   File storeDir = new File(STORE_DIR); 
   if (!storeDir.exists()) { 
    boolean flag = storeDir.mkdir(); 
    if (!flag) { 
     System.err.println("創(chuàng)建圖片存儲目錄失敗"); 
     return; 
    } 
   } 
    
   JumpJumpHelper jumpjumpHelper = new JumpJumpHelper(); 
   //執(zhí)行次數(shù) 
   int executeCount = 0; 
   for (;;) 
   { 
    //執(zhí)行ADB命令,獲取安卓截屏 
    jumpjumpHelper.executeADBCaptureCommands(); 
    File currentImage = new File(STORE_DIR, IMAGE_NAME); 
    if (!currentImage.exists()) 
    { 
     System.out.println("圖片不存在"); 
     continue; 
    } 
 
    long length = currentImage.length(); 
    imageLength[executeCount % imageLengthLength] = length; 
    //查看是否需要重新開局 
    jumpjumpHelper.checkDoReplay(); 
    executeCount++; 
    System.out.println("當前第" + executeCount + "次執(zhí)行!"); 
    //獲取跳棋和底板的中心坐標 
    int[] result = jumpjumpHelper.getHalmaAndBoardXYValue(currentImage); 
    if (result == null) 
    { 
     System.out.println("The result of method getHalmaAndBoardXYValue is null!"); 
     continue; 
    } 
    int halmaX = result[0]; 
    int halmaY = result[1]; 
    int boardX = result[2]; 
    int boardY = result[3]; 
    System.out.println("halmaX: " + halmaX + ", halmaY: " + halmaY + ", boardX: " + boardX + ", boardY: " 
      + boardY); 
    //計算跳躍的距離 
    double jumpDistance = jumpjumpHelper.computeJumpDistance(halmaX, halmaY, boardX, boardY); 
    jumpjumpHelper.doJump(jumpDistance); 
    //每次停留2.5秒 
    TimeUnit.MILLISECONDS.sleep(2500); 
   } 
  } 
  catch (Exception e) 
  { 
   e.printStackTrace(); 
  } 
 } 
 
 /** 
  * 檢查是否需要重新開局 
  * 
  * @author LeeHo 
  * @update 2017年12月31日 下午1:39:18 
  */ 
 private void checkDoReplay() 
 { 
  if (imageLength[0] > 0 && imageLength[0] == imageLength[1] && imageLength[1] == imageLength[2] 
    && imageLength[2] == imageLength[3] && imageLength[3] == imageLength[4]) 
  { 
   //此時表示已經(jīng)連續(xù)5次圖片大小一樣了,可知當前屏幕處于再來一局 
   Arrays.fill(imageLength, 0); 
   //模擬點擊再來一局按鈕重新開局 
   replayGame(); 
  } 
 } 
 
 /** 
  * 獲取指定坐標的RGB值 
  * 
  * @param bufferedImage 
  * @param x 
  * @param y 
  * @author LeeHo 
  * @update 2017年12月31日 下午12:12:43 
  */ 
 private void processRGBInfo(BufferedImage bufferedImage, int x, int y) 
 { 
  this.rgbInfo.reset(); 
  int pixel = bufferedImage.getRGB(x, y); 
  //轉(zhuǎn)換為RGB數(shù)字 
  this.rgbInfo.setRValue((pixel & 0xff0000) >> 16); 
  this.rgbInfo.setGValue((pixel & 0xff00) >> 8); 
  this.rgbInfo.setBValue((pixel & 0xff)); 
 } 
 
 class RGBInfo 
 { 
  private int RValue; 
 
  private int GValue; 
 
  private int BValue; 
 
  public int getRValue() 
  { 
   return RValue; 
  } 
 
  public void setRValue(int rValue) 
  { 
   RValue = rValue; 
  } 
 
  public int getGValue() 
  { 
   return GValue; 
  } 
 
  public void setGValue(int gValue) 
  { 
   GValue = gValue; 
  } 
 
  public int getBValue() 
  { 
   return BValue; 
  } 
 
  public void setBValue(int bValue) 
  { 
   BValue = bValue; 
  } 
 
  public void reset() 
  { 
   this.RValue = 0; 
   this.GValue = 0; 
   this.BValue = 0; 
  } 
 } 
}

更多內(nèi)容大家可以參考專題《微信跳一跳》進行學(xué)習(xí)。

 以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java之Thread的join方法實例

    Java之Thread的join方法實例

    這篇文章主要介紹了Java之Thread的join方法,實例形式講述了join方法的應(yīng)用,需要的朋友可以參考下
    2014-10-10
  • Java實現(xiàn)PDF打印的解決方案

    Java實現(xiàn)PDF打印的解決方案

    今天小編就為大家分享一篇關(guān)于Java實現(xiàn)PDF打印的解決方案,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • SpringBoot?AOP?Redis實現(xiàn)延時雙刪功能實戰(zhàn)

    SpringBoot?AOP?Redis實現(xiàn)延時雙刪功能實戰(zhàn)

    本文主要介紹了SpringBoot?AOP?Redis實現(xiàn)延時雙刪功能實戰(zhàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • SpringBoot項目執(zhí)行腳本 自動拉取最新代碼并重啟的實例內(nèi)容

    SpringBoot項目執(zhí)行腳本 自動拉取最新代碼并重啟的實例內(nèi)容

    在本篇文章里小編給大家整理的是一篇關(guān)于SpringBoot項目執(zhí)行腳本 自動拉取最新代碼并重啟的實例內(nèi)容,有需要的朋友們參考下。
    2019-12-12
  • Spring AOP如何實現(xiàn)注解式的Mybatis多數(shù)據(jù)源切換詳解

    Spring AOP如何實現(xiàn)注解式的Mybatis多數(shù)據(jù)源切換詳解

    這篇文章主要給大家介紹了關(guān)于Spring AOP如何實現(xiàn)注解式的Mybatis多數(shù)據(jù)源切換的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • JAVA入門教學(xué)之快速搭建基本的springboot(從spring boot到spring cloud)

    JAVA入門教學(xué)之快速搭建基本的springboot(從spring boot到spring cloud)

    本文主要入門者介紹怎么搭建一個基礎(chǔ)的springboot環(huán)境,本文通過圖文并茂的形式給大家介紹從spring boot到spring cloud的完美搭建過程,適用java入門教學(xué),需要的朋友可以參考下
    2021-02-02
  • 詳解如何將JAVA程序制作成可以直接執(zhí)行的exe文件

    詳解如何將JAVA程序制作成可以直接執(zhí)行的exe文件

    這篇文章主要介紹了詳解如何將JAVA程序制作成可以直接執(zhí)行的exe文件,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Java?獲取本機IP地址的實例代碼

    Java?獲取本機IP地址的實例代碼

    這篇文章主要介紹了Java?獲取本機IP地址,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2022-05-05
  • Java使用I/O流讀取文件內(nèi)容的方法詳解

    Java使用I/O流讀取文件內(nèi)容的方法詳解

    這篇文章主要介紹了Java使用I/O流讀取文件內(nèi)容的方法,結(jié)合實例形式詳細分析了java使用I/O流讀取文件常見操作技巧,需要的朋友可以參考下
    2019-11-11
  • 詳解@Autowired是如何注入變量的

    詳解@Autowired是如何注入變量的

    在?Spring?容器中,當我們想給某一個屬性注入值的時候,有多種不同的方式,例如使用?@Autowired、@Inject等注解,下面小編就來和小伙伴們聊一聊,@Autowired?到底是如何把數(shù)據(jù)注入進來的
    2023-07-07

最新評論