溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

java如何實(shí)現(xiàn)微信跳一跳刷分功能

發(fā)布時(shí)間:2021-07-10 15:01:37 來源:億速云 閱讀:119 作者:小新 欄目:編程語言

小編給大家分享一下java如何實(shí)現(xiàn)微信跳一跳刷分功能,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

首先大概說一下步驟:

1.百度下載刷分代碼

2.安裝adb

3.找個(gè)手機(jī)使用USB調(diào)試模式連接電腦

4.啟動跳一跳微信小程序

5.在eclipse中運(yùn)行代碼(此處要不斷調(diào)試根據(jù)手機(jī)屏幕大小修改參數(shù))

結(jié)果就是你的手機(jī)屏幕會自動按壓然后讓棋子跳。

再說下問題:

一、安裝adb問題集:

下載adb工具地址

在此處的設(shè)備管理器中,如果沒有安裝在其他設(shè)備這里,adb就是一個(gè)感嘆號,安裝完畢后如圖所示,會出現(xiàn)android device 這一行

java如何實(shí)現(xiàn)微信跳一跳刷分功能

安裝的話在adb一欄里右擊選擇屬性,彈出如下界面,點(diǎn)擊更新驅(qū)動程序,選擇瀏覽計(jì)算機(jī)選擇程序(也就是第二個(gè)選項(xiàng)),此時(shí)會彈出一個(gè)瀏覽計(jì)算機(jī)上的驅(qū)動程序選項(xiàng),選擇安裝包所在地,然后一切放行,就能安裝。

java如何實(shí)現(xiàn)微信跳一跳刷分功能

java如何實(shí)現(xiàn)微信跳一跳刷分功能

問題來了:

安裝完后,你在cmd命令窗口下能使用adb,但是在eclipse中運(yùn)行代碼完全沒有效果(程序不報(bào)錯(cuò),手機(jī)里也沒有截圖),然后eclipse控制臺就顯示圖片不存在,

此時(shí)需要把你安裝好的一個(gè)exe程序,兩個(gè)動態(tài)鏈接庫dll拷貝到如下兩個(gè)目錄下:(找不到就在c盤全局搜一下)

adb.exe

AdbWinApi.dll

AdbWinUsbApi.dll

C:\Windows\System32

C:\Windows\SysWOW64

此時(shí)一定要放在SysWOW64下,我是win7 64位,所以有這個(gè)目錄(網(wǎng)上其他人說win32就不需要放這個(gè)了,我沒試過),

如果沒有放SysWOW64目錄,此時(shí)eclipse運(yùn)行依舊沒有效果:但如果你在cmd中運(yùn)行adb shell screencap -p /sdcard/tencent/customerpic/current.png這條命令,發(fā)現(xiàn)手機(jī)里面會有current.png圖片,這說明eclipse沒有找到對應(yīng)的adb工具。

我找出這個(gè)問題是通過cd到System32和安裝目錄(C:\Program Files (x86)\Thunder Network\Thunder\Program)下,我在Program中運(yùn)行上述命令成功,在System32中運(yùn)行報(bào)錯(cuò):

---------------------------adb.exe - 系統(tǒng)錯(cuò)誤---------------------------

無法啟動此程序,因?yàn)橛?jì)算機(jī)中丟失 AdbWinApi.DLL。嘗試重新安裝該程序以解決此問題。 

---------------------------

確定   

---------------------------

OK,這說明System32中的adb找不到AdbWinApi.Dll動態(tài)鏈接文件,但明明就有,機(jī)緣巧合之下,老夫看到了SysWOW64這個(gè)目錄,然后百度這個(gè)目錄是什么意思,什么作用,OK,將拷貝到System32目錄下的三個(gè)文件再次拷貝一份到此SysWOW64目錄下,搞定。

問題二:device offline

在cmd命令窗口運(yùn)行adb shell結(jié)果報(bào)錯(cuò)device offline,我以為是我adb安裝有問題,百度了一大堆,試過adb kill server,adb remount等命令都沒用,后來換了發(fā)現(xiàn)代碼里面是/sdcard/,一看這應(yīng)該是外置SD卡吧,是不是路徑不對,(我用的是vivo x9,這手機(jī)沒有外置SD卡選項(xiàng)),換了舊一點(diǎn)的手機(jī)(vivo y27)后運(yùn)行adb shell可以了,不過/sdcard不是外置SD卡路徑,而是手機(jī)U盤路徑。

那么就說明不應(yīng)該是代碼路徑問題,又是百度了一番,被告知是adb工具太老,adb version得到版本 1.0.26,好吧,我也懶得去找新版adb,用老的vivo y27調(diào)試了下能刷就行。

列舉一下我學(xué)到的:

1.知道有adb這東西,也知道使用adb shell可以得到手機(jī)的bash會話,可以截圖,使用adb pull可以從手機(jī)里面得到文件,更多命令的話官網(wǎng)有,我看多了也記不住。

2.知道原來代碼里面java使用Runtime.getRuntime().exec()可以在windows中調(diào)用系統(tǒng)命令:

process = Runtime.getRuntime().exec(command); 
 System.out.println("exec command start: " + command); 
 process.waitFor(); 
 process.getInputStream(); 
 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); 
 String line = bufferedReader.readLine();

3.明白代碼中通過計(jì)算截圖的RGB顏色值等分析一張圖片int pixel = bufferedImage.getRGB(x, y);

全部代碼:

package com.lw.test; 
 
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 href="https://zhuanlan.zhihu.com/p/32452473" 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 path = "/sdcard/tencent/customerpic/"; 
 private final String[] ADB_SCREEN_CAPTURE_CMDS = 
  {"adb shell screencap -p "+path + IMAGE_NAME, 
 "adb pull "+path+"current.png " + STORE_DIR }; 
 
 //截屏中游戲分?jǐn)?shù)顯示區(qū)域最下方的Y坐標(biāo),300是 1920x1080的值,根據(jù)實(shí)際情況修改 
 private final int gameScoreBottomY = 300; 
 
 //按壓的時(shí)間系數(shù),可根據(jù)具體情況適當(dāng)調(diào)節(jié) 
 private final double pressTimeCoefficient = 2.05; 
 
 //按壓的起始點(diǎn)坐標(biāo),也是再來一局的起始點(diǎn)坐標(biāo) 
 private final int swipeX = 280; 
 
 private final int swipeY = 600; 
 
 //二分之一的棋子底座高度 
 private final int halfBaseBoardHeight = 20; 
 
 //棋子的寬度,從截屏中量取,自行調(diào)節(jié) 
 private final int halmaBodyWidth = 74; 
 
 //游戲截屏里的兩個(gè)跳板的中點(diǎn)坐標(biāo),主要用來計(jì)算角度,可依據(jù)實(shí)際的截屏計(jì)算,計(jì)算XY的比例 
 private final int boardX1 = 813; 
 
 private final int boardY1 = 1122; 
 
 private final int boardX2 = 310; 
 
 private final int boardY2 = 813; 
 
 /** 
 * 獲取跳棋以及下一塊跳板的中心坐標(biāo) 
 * 
 * @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; 
 //從截屏從上往下逐行遍歷像素點(diǎn),以棋子顏色作為位置識別的依據(jù),最終取出棋子顏色最低行所有像素點(diǎn)的平均值,即計(jì)算出棋子所在的坐標(biāo) 
 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坐標(biāo)值 
 halmaYMax = y > halmaYMax ? y : halmaYMax; 
 } 
 } 
 } 
 
 if (halmaXSum != 0 && halmaXCount != 0) 
 { 
 //棋子底行的X坐標(biāo)值 
 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(); 
 //只要計(jì)算出來的boardX的值大于0,就表示下個(gè)跳板的中心坐標(biāo)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(); 
 //處理棋子頭部比下一個(gè)跳板還高的情況 
 if (Math.abs(x - halmaX) < halmaBodyWidth) 
 { 
 continue; 
 } 
 
 //從上往下逐行掃描至下一個(gè)跳板的頂點(diǎn)位置,下個(gè)跳板可能為圓形,也可能為方框,取多個(gè)點(diǎn),求平均值 
 if ((Math.abs(pixelR - lastPixelR) + Math.abs(pixelG - lastPixelG) + Math.abs(pixelB - lastPixelB)) > 10) 
 { 
 boardXSum += x; 
 boardXCount++; 
 } 
 } 
 
 if (boardXSum > 0) 
 { 
 boardX = boardXSum / boardXCount; 
 } 
 } 
 
 //按實(shí)際的角度來算,找到接近下一個(gè) board 中心的坐標(biāo) 
 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坐標(biāo) 
 result[0] = halmaX; 
 //棋子的Y坐標(biāo) 
 result[1] = halmaY; 
 //下一塊跳板的X坐標(biāo) 
 result[2] = boardX; 
 //下一塊跳板的Y坐標(biāo) 
 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(); 
 process.getInputStream(); 
 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); 
 String line = bufferedReader.readLine(); 
 if (line != null) 
 { 
 System.out.println(line); 
 } 
 bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); 
 String line02 = bufferedReader.readLine(); 
 if (line02 != null) 
 { 
 System.out.println(line02); 
 } 
 
 
 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); 
 //計(jì)算按壓時(shí)間,最小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); 
 } 
 
 /** 
 * 計(jì)算跳躍的距離,也即兩個(gè)點(diǎn)之間的距離 
 * 
 * @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) 
 { 
 
 
 JumpJumpHelper jumpjumpHelper = new JumpJumpHelper(); 
// String command = "adb shell screencap -p "+jumpjumpHelper.path + IMAGE_NAME; 
//// command = "adb devices"; 
// jumpjumpHelper.executeCommand(command); 
// 
// if(true){return ;} 
 
 
 
 try 
 { 
 File storeDir = new File(STORE_DIR); 
 if (!storeDir.exists()) { 
 boolean flag = storeDir.mkdir(); 
 if (!flag) { 
 System.err.println("創(chuàng)建圖片存儲目錄失敗"); 
 return; 
 } 
 } 
 
 //執(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("當(dāng)前第" + executeCount + "次執(zhí)行!"); 
 //獲取跳棋和底板的中心坐標(biāo) 
 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); 
 //計(jì)算跳躍的距離 
 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]) 
 { 
 //此時(shí)表示已經(jīng)連續(xù)5次圖片大小一樣了,可知當(dāng)前屏幕處于再來一局 
 Arrays.fill(imageLength, 0); 
 //模擬點(diǎn)擊再來一局按鈕重新開局 
 replayGame(); 
 } 
 } 
 
 /** 
 * 獲取指定坐標(biāo)的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; 
 } 
 } 
}

當(dāng)然,現(xiàn)在刷了一會就被清空成績,但作為一個(gè)程序員知道還是好的。從一開始的post提交漏洞,讓電腦作為代理抓包修改數(shù)據(jù),現(xiàn)在代碼模擬點(diǎn)擊(雖然不會生效。)

以上是“java如何實(shí)現(xiàn)微信跳一跳刷分功能”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI