微信跳一跳刷分java代码实现

2025-05-29 0 38

朋友圈晒跳一跳成绩好久了,今天无意中看到以前一个同事小妞晒用代码刷分的视频,百度了一下果然看到了代码(代码在最后),几经波折,终于成功运行,刷了一点分数。

首先大概说一下步骤:

1.百度下载刷分代码

2.安装adb

3.找个手机使用USB调试模式连接电脑

4.启动跳一跳微信小程序

5.在eclipse中运行代码(此处要不断调试根据手机屏幕大小修改参数)

结果就是你的手机屏幕会自动按压然后让棋子跳。

再说下问题:

一、安装adb问题集:

下载adb工具地址

在此处的设备管理器中,如果没有安装在其他设备这里,adb就是一个感叹号,安装完毕后如图所示,会出现android device 这一行

微信跳一跳刷分java代码实现

安装的话在adb一栏里右击选择属性,弹出如下界面,点击更新驱动程序,选择浏览计算机选择程序(也就是第二个选项),此时会弹出一个浏览计算机上的驱动程序选项,选择安装包所在地,然后一切放行,就能安装。

微信跳一跳刷分java代码实现

微信跳一跳刷分java代码实现

问题来了:

安装完后,你在cmd命令窗口下能使用adb,但是在eclipse中运行代码完全没有效果(程序不报错,手机里也没有截图),然后eclipse控制台就显示图片不存在,

此时需要把你安装好的一个exe程序,两个动态链接库dll拷贝到如下两个目录下:(找不到就在c盘全局搜一下)

adb.exe

AdbWinApi.dll

AdbWinUsbApi.dll

C:\\Windows\\System32

C:\\Windows\\SysWOW64

此时一定要放在SysWOW64下,我是win7 64位,所以有这个目录(网上其他人说win32就不需要放这个了,我没试过),

如果没有放SysWOW64目录,此时eclipse运行依旧没有效果:但如果你在cmd中运行adb shell screencap -p /sdcard/tencent/customerpic/current.png这条命令,发现手机里面会有current.png图片,这说明eclipse没有找到对应的adb工具。

我找出这个问题是通过cd到System32和安装目录(C:\\Program Files (x86)\\Thunder Network\\Thunder\\Program)下,我在Program中运行上述命令成功,在System32中运行报错:

—————————adb.exe – 系统错误—————————

无法启动此程序,因为计算机中丢失 AdbWinApi.DLL。尝试重新安装该程序以解决此问题。

—————————

确定

—————————

OK,这说明System32中的adb找不到AdbWinApi.Dll动态链接文件,但明明就有,机缘巧合之下,老夫看到了SysWOW64这个目录,然后百度这个目录是什么意思,什么作用,OK,将拷贝到System32目录下的三个文件再次拷贝一份到此SysWOW64目录下,搞定。

问题二:device offline

在cmd命令窗口运行adb shell结果报错device offline,我以为是我adb安装有问题,百度了一大堆,试过adb kill server,adb remount等命令都没用,后来换了发现代码里面是/sdcard/,一看这应该是外置SD卡吧,是不是路径不对,(我用的是vivo x9,这手机没有外置SD卡选项),换了旧一点的手机(vivo y27)后运行adb shell可以了,不过/sdcard不是外置SD卡路径,而是手机U盘路径。

那么就说明不应该是代码路径问题,又是百度了一番,被告知是adb工具太老,adb version得到版本 1.0.26,好吧,我也懒得去找新版adb,用老的vivo y27调试了下能刷就行。

列举一下我学到的:

1.知道有adb这东西,也知道使用adb shell可以得到手机的bash会话,可以截图,使用adb pull可以从手机里面得到文件,更多命令的话官网有,我看多了也记不住。

2.知道原来代码里面java使用Runtime.getRuntime().exec()可以在windows中调用系统命令:

?

1

2

3

4

5

6
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.明白代码中通过计算截图的RGB颜色值等分析一张图片int pixel = bufferedImage.getRGB(x, y);

全部代码:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432
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";

//数量

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 };

//截屏中游戏分数显示区域最下方的Y坐标,300是 1920x1080的值,根据实际情况修改

private final int gameScoreBottomY = 300;

//按压的时间系数,可根据具体情况适当调节

private final double pressTimeCoefficient = 2.05;

//按压的起始点坐标,也是再来一局的起始点坐标

private final int swipeX = 280;

private final int swipeY = 600;

//二分之一的棋子底座高度

private final int halfBaseBoardHeight = 20;

//棋子的宽度,从截屏中量取,自行调节

private final int halmaBodyWidth = 74;

//游戏截屏里的两个跳板的中点坐标,主要用来计算角度,可依据实际的截屏计算,计算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;

//从截屏从上往下逐行遍历像素点,以棋子颜色作为位置识别的依据,最终取出棋子颜色最低行所有像素点的平均值,即计算出棋子所在的坐标

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();

//根据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;

}

/**

* 执行命令

*

* @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);

//计算按压时间,最小200毫秒

int pressTime = (int) Math.max(distance * pressTimeCoefficient, 200);

System.out.println("pressTime: " + pressTime);

//执行按压操作

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)

{

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("创建图片存储目录失败");

return;

}

}

//执行次数

int executeCount = 0;

for (;;)

{

//执行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 + "次执行!");

//获取跳棋和底板的中心坐标

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])

{

//此时表示已经连续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);

//转换为RGB数字

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;

}

}

}

当然,现在刷了一会就被清空成绩,但作为一个程序员知道还是好的。从一开始的post提交漏洞,让电脑作为代理抓包修改数据,现在代码模拟点击(虽然不会生效。)

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

原文链接:http://blog.csdn.net/lw18751836671/article/details/78981527

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 微信跳一跳刷分java代码实现 https://www.kuaiidc.com/113077.html

相关文章

发表评论
暂无评论