ฉันโพสต์ผลการกระโดดของฉันในแวดวงเพื่อนของฉันมานานแล้ว วันนี้ฉันเห็นวิดีโอของเพื่อนร่วมงานที่ใช้รหัสเพื่อทำคะแนน ฉันไปที่ Baidu และเห็นรหัส (รหัสจบลง) หลังจากการบิดและเปลี่ยนหลายครั้งในที่สุดฉันก็วิ่งได้สำเร็จและทำคะแนนได้เล็กน้อย
ก่อนอื่นมาพูดคุยสั้น ๆ เกี่ยวกับขั้นตอน:
1. รหัสคะแนนการดาวน์โหลด baidu
2. ติดตั้ง ADB
3. ค้นหาโทรศัพท์เพื่อเชื่อมต่อกับคอมพิวเตอร์โดยใช้โหมดการดีบัก USB
4. เริ่มโปรแกรม WeChat Mini
5. เรียกใช้รหัสใน Eclipse (ที่นี่เราจำเป็นต้องทำการดีบักและแก้ไขพารามิเตอร์อย่างต่อเนื่องตามขนาดของหน้าจอโทรศัพท์มือถือ)
ผลลัพธ์คือหน้าจอโทรศัพท์ของคุณจะกดโดยอัตโนมัติและปล่อยให้ชิ้นหมากรุกกระโดด
พูดคุยเกี่ยวกับคำถาม:
1. ติดตั้งชุดปัญหา ADB:
ดาวน์โหลดที่อยู่เครื่องมือ ADB
ในตัวจัดการอุปกรณ์ที่นี่หากไม่ได้ติดตั้งบนอุปกรณ์อื่น ADB เป็นจุดอัศเจรีย์ หลังจากการติดตั้งดังที่แสดงในรูปอุปกรณ์ Android Line จะปรากฏขึ้น
หากคุณติดตั้งให้คลิกขวาในคอลัมน์ ADB เพื่อเลือกคุณสมบัติและอินเทอร์เฟซต่อไปนี้จะปรากฏขึ้นคลิกไดรเวอร์อัปเดตเลือกเรียกดูคอมพิวเตอร์และเลือกโปรแกรม (นั่นคือตัวเลือกที่สอง) ในเวลานี้ตัวเลือกไดรเวอร์เรียกดูบนคอมพิวเตอร์จะปรากฏขึ้นเลือกตำแหน่งของแพ็คเกจการติดตั้งจากนั้นทุกอย่างจะถูกปล่อยให้ติดตั้ง
คำถามคือ:
หลังจากการติดตั้งคุณสามารถใช้ ADB ภายใต้หน้าต่างคำสั่ง CMD แต่การเรียกใช้รหัสใน Eclipse ไม่มีผลเลย (โปรแกรมไม่ได้รายงานข้อผิดพลาดและไม่มีภาพหน้าจอบนโทรศัพท์) จากนั้นคอนโซล Eclipse แสดงว่าภาพไม่มีอยู่
ในเวลานี้คุณจะต้องคัดลอกไลบรารีลิงก์แบบไดนามิกสองตัวที่คุณติดตั้งไว้ในไดเรกทอรีสองไดเรกทอรีต่อไปนี้: (หากคุณไม่พบพวกเขาให้ค้นหาทั่วโลกบนไดรฟ์ C)
adb.exe
adbwinapi.dll
adbwinusbapi.dll
C:/Windows/System32
C:/windows/syswow64
ในเวลานี้จะต้องอยู่ภายใต้ Syswow64 ฉันเป็น win7 64 บิตดังนั้นจึงมีไดเรกทอรีนี้ (คนอื่น ๆ บนอินเทอร์เน็ตบอกว่า Win32 ไม่จำเป็นต้องใส่สิ่งนี้ฉันยังไม่ได้ลอง)
หากไม่ได้วางไดเรกทอรี syswow64 การดำเนินการ eclipse ยังคงไม่มีผลในเวลานี้: แต่ถ้าคุณเรียกใช้ adb shell screencap -p /sdcard/tencent/customerpic/current.png ใน CMD คุณจะพบว่า
ฉันพบว่าฉันใช้ซีดีไปยัง System32 และภายใต้ไดเรกทอรีการติดตั้ง (C:/ไฟล์โปรแกรม (x86)/Thunder Network/Thunder/Program) ฉันได้รันคำสั่งด้านบนในโปรแกรมสำเร็จและรายงานข้อผิดพลาดใน System32:
-
โปรแกรมนี้ไม่สามารถเริ่มต้นได้เนื่องจาก Adbwinapi.dll หายไปจากคอมพิวเตอร์ ลองติดตั้งโปรแกรมใหม่เพื่อแก้ไขปัญหานี้
-
แน่นอน
-
ตกลงนี่หมายความว่า ADB ใน System32 ไม่สามารถค้นหาไฟล์ Adbwinapi.dll Dynamic Link แต่เห็นได้ชัดว่าโดยบังเอิญฉันเห็นไดเรกทอรี syswow64 แล้วไดเรกทอรีนี้มีความหมายอย่างไรและหมายความว่าอย่างไร? ตกลงคัดลอกสามไฟล์ที่คัดลอกไปยังไดเรกทอรี System32 แล้วคัดลอกไปยังไดเรกทอรีนี้ Syswow64 และทำเสร็จ
คำถามที่ 2: อุปกรณ์ออฟไลน์
การรันเชลล์ ADB ในหน้าต่างคำสั่ง CMD ส่งผลให้อุปกรณ์ข้อผิดพลาดออฟไลน์ ฉันคิดว่ามีบางอย่างผิดปกติกับการติดตั้ง ADB ของฉัน ฉันมี Baidu มากมาย ฉันลอง Adb Kill Server, ADB Remount และคำสั่งอื่น ๆ แต่ฉันพบว่ารหัสนั้นเป็น /sdcard / ฉันเห็นว่านี่ควรเป็นการ์ด SD ภายนอก เส้นทางผิด? (ฉันใช้ Vivo X9 และโทรศัพท์นี้ไม่มีตัวเลือกการ์ด SD ภายนอก) หลังจากเปลี่ยนเป็นโทรศัพท์รุ่นเก่า (Vivo Y27) ฉันสามารถเรียกใช้ ADB Shell ได้ แต่ /SDCARD ไม่ใช่เส้นทางการ์ด SD ภายนอก แต่เส้นทางดิสก์ U ของโทรศัพท์
นั่นหมายความว่าไม่ควรเป็นปัญหาเส้นทางรหัส ฉันได้รับแจ้งว่าเครื่องมือ ADB นั้นเก่าเกินไปและรุ่น ADB มีเวอร์ชัน 1.0.26 ฉันขี้เกียจเกินไปที่จะหา ADB เวอร์ชันใหม่ ฉันดีบักกับ Vivo Y27 เก่าและสามารถฉายได้
ให้ฉันแสดงรายการสิ่งที่ฉันได้เรียนรู้:
1. ฉันรู้ว่ามี ADB และฉันก็รู้ด้วยว่าการใช้ ADB Shell สามารถรับเซสชัน Bash ของโทรศัพท์ได้ คุณสามารถถ่ายภาพหน้าจอและการใช้ ADB Pull สามารถรับไฟล์จากโทรศัพท์ได้ หากมีคำสั่งเพิ่มเติมในเว็บไซต์อย่างเป็นทางการฉันจำไม่ได้แม้ว่าฉันจะอ่านมันมากเกินไป
2. รู้ว่า java ใช้ runtime.getRuntime (). exec () ในรหัสต้นฉบับเพื่อเรียกคำสั่งระบบใน Windows:
กระบวนการ = runtime.getRuntime (). exec (คำสั่ง); System.out.println ("คำสั่งเริ่มต้น:" + คำสั่ง); process.waitfor (); process.getInputStream (); bufferedReader bufferedReader = ใหม่ bufferedReader (ใหม่ inputStreamReader (process.getErrorStream ())); สตริงบรรทัด = bufferedReader.readline (); 3. เข้าใจว่าในรหัสวิเคราะห์ภาพโดยการคำนวณค่าสี RGB ของภาพหน้าจอ ฯลฯ , int pixel = bufferedimage.getRgb (x, y);
รหัสทั้งหมด:
แพ็คเกจ com.lw.test; นำเข้า java.awt.image.bufferedimage; นำเข้า java.io.bufferedreader; นำเข้า Java.io.File; นำเข้า java.io.ioException; นำเข้า Java.io.InputStreamReader; นำเข้า Java.util.Arrays; นำเข้า java.util.concurrent.timeUnit; นำเข้า Javax.imageio.imageio; /** * อ้างอิง zhihu * * @link <a href = "https://zhuanlan.zhihu.com/p/32452473" rel = "external nofollow" เป้าหมาย = "_blank"> https://zhuanlan.zhihu.com/p/324 */ คลาสสาธารณะ jumpjumphelper {สตริงคงสุดท้ายส่วนตัว image_name = "current.png"; สตริงสุดท้ายคงที่ส่วนตัว store_dir = "d:/jump_screencapture"; // ปริมาณส่วนตัวคงสุดท้าย ImageLengthLength = 5; // ขนาดของภาพส่วนตัวคงสุดท้ายยาว [] imageLength = ใหม่ยาว [imageLengthLength]; ส่วนตัว RGBINFO RGBINFO = ใหม่ RGBINFO (); Private Final String Path = "/SDCARD/TENCENT/CUSTERVERPIC/"; สตริงสุดท้ายส่วนตัว [] ADB_SCREEN_CAPTURE_CMDS = {"ADB Shell Screencap -p"+Path+Image_name, "ADB PULL"+PATH+"current.png"+store_dir}; // พิกัด Y ที่ด้านล่างของพื้นที่แสดงคะแนนเกมในภาพหน้าจอ 300 คือค่า 1920x1080 ปรับเปลี่ยน GamescoreBottomy INT สุดท้ายส่วนตัว = 300 ตามสถานการณ์จริง // ค่าสัมประสิทธิ์เวลากดสามารถปรับได้อย่างเหมาะสมตามสถานการณ์เฉพาะ Private Final Double PressTimecoefficient = 2.05; // จุดเริ่มต้นพิกัดของการกดเป็นจุดเริ่มต้นของเกมถัดไปของเกมถัดไป int swipex = 280; Swipey int สุดท้ายส่วนตัว = 600; // ความสูงของฐานของชิ้นหมากรุกเป็นส่วนตัวสุดท้าย int halfbaseboardheight = 20; // ความกว้างของชิ้นหมากรุกนำมาจากภาพหน้าจอและปรับ INT สุดท้ายของตัวเองด้วยตัวเอง Halmabodywidth = 74; // พิกัดจุดกึ่งกลางของสปริงบอร์ดทั้งสองในสกรีนช็อตเกมส่วนใหญ่จะใช้ในการคำนวณมุม สัดส่วนของ XY สามารถคำนวณได้ตามภาพหน้าจอจริง INT สุดท้ายส่วนตัว boardx1 = 813; INT สุดท้ายส่วนตัว Boardy1 = 1122; INT สุดท้ายส่วนตัว BOINDX2 = 310; INT สุดท้ายส่วนตัว Boardy2 = 813; / ** * รับหมากฮอสและพิกัดกลางของสปริงบอร์ดถัดไป * * @return * @author leeho * @throws ioexception * @update 31 ธันวาคม 2017 เวลา 12:18:22 น. */ ส่วนตัว ความกว้าง int = bufferedImage.getWidth (); ความสูง int = bufferedImage.getheight (); System.out.println ("ความกว้าง:" + width + ", ความสูง:" + ความสูง); int halmaxsum = 0; int halmaxCount = 0; int halmaymax = 0; int boardx = 0; int boardy = 0; // ถ่ายโอนคะแนนพิกเซลจากภาพหน้าจอจากบนลงล่างและใช้สีของชิ้นหมากรุกเป็นพื้นฐานสำหรับการจดจำตำแหน่ง ในที่สุดค่าเฉลี่ยของพิกเซลทั้งหมดในแถวต่ำสุดของสีชิ้นหมากรุกจะถูกนำออกมานั่นคือคำนวณพิกัดของชิ้นหมากรุกสำหรับ (int y = gamescorebottomy; y <ความสูง; y ++) {สำหรับ (int x = 0; x <width; x ++) {processrgbinfo int rvalue = this.rgbinfo.getRvalue (); int gvalue = this.rgbinfo.getGvalue (); int bvalue = this.rgbinfo.getBvalue (); // ระบุตำแหน่งของชิ้นหมากรุกตามสีของ RGB ถ้า (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 int halmax = halmaxsum /halmaxcount; // ย้ายครึ่งหนึ่งของแชสซีชิ้นหมากรุกสูงขึ้น int halmay = halmaymax - halfbaseboardheight; // เริ่มจาก gamescoreBottomy สำหรับ (int y = gamescoreBottomy; y <ความสูง; 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; สำหรับ (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 (); // ฝึกอบรมกรณีที่หัวของชิ้นหมากรุกสูงกว่ากระดานกระโดดถัดไปถ้า (math.abs (x - halmax) <halmabodywidth) {ดำเนินการต่อ; } // สแกนจากบนลงล่างไปยังตำแหน่งจุดสุดยอดของสปริงกระดานถัดไป กระดานกระโดดน้ำถัดไปอาจเป็นวงกลมหรือกล่อง ใช้หลายคะแนนและค้นหาค่าเฉลี่ย if ((math.abs (Pixelr - lastpixelr) + Math.Abs (Pixelg - LastPixelg) + Math.Abs (Pixelb - LastPixelb))> 10) {boardxsum + = x; BoardxCount ++; }} if (boardxsum> 0) {boardx = boardxsum / boardxcount; }} // จากมุมจริงค้นหาพิกัดใกล้กับศูนย์กลางของบอร์ดถัดไป 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 [0] = Halmax; // ผลพิกัด y [1] = Halmay; // ผลการประสานงาน x [2] = boardx; // ผลพิกัด y [3] = boardy; ผลการกลับมา; }} return null; } / ** * เรียกใช้คำสั่ง * * @param คำสั่ง * @author leeho * @update 31 ธันวาคม 2017 เวลา 12:13:39 น ลอง {process = runtime.getRuntime (). exec (คำสั่ง); System.out.println ("คำสั่งเริ่มต้น:" + คำสั่ง); process.waitfor (); process.getInputStream (); bufferedReader bufferedReader = ใหม่ bufferedReader (ใหม่ inputStreamReader (process.getErrorStream ())); สตริงบรรทัด = bufferedReader.readline (); if (line! = null) {system.out.println (บรรทัด); } bufferedReader = ใหม่ bufferedReader (ใหม่ inputStreamReader (process.getInputStream ())); String line02 = bufferedreader.readline (); if (line02! = null) {system.out.println (line02); } system.out.println ("คำสั่ง exec end:" + คำสั่ง); } catch (exception e) {e.printstacktrace (); } ในที่สุด {ถ้า (กระบวนการ! = null) {process.destroy (); }}} / ** * ADB ได้รับภาพหน้าจอ Android * * @author leeho * @update 31 ธันวาคม 2017 12:11:42 PM * / โมฆะส่วนตัว ExecuteadBcaptureCommands () {สำหรับ (สตริงคำสั่ง: ADB_SCREEN_CAPTURE_CMDS) }} / ** * กระโดด * * @param ระยะทาง * @author leeho * @update 31 ธันวาคม 2017 เวลา 12:23:19 น. * / โมฆะส่วนตัว Dojump (ระยะทางสองเท่า) {System.out.println ("ระยะทาง:" + ระยะทาง); // คำนวณเวลากด, ขั้นต่ำ 200ms int press = (int) math.max (ระยะทาง * presstimecoefficient, 200); System.out.println ("Presstime:" + PressTime); // ดำเนินการกดสตริงการดำเนินการ = string.format ("ADB เชลล์อินพุต swipe %s %s %s %s %s", swipex, swipey, swipex, swipey, presstime); System.out.println (คำสั่ง); ExecuteCommand (คำสั่ง); } / ** * เกมอื่น * * @author leeho * @update 31 ธันวาคม 2017 เวลา 12:47:06 น. * / โมฆะส่วนตัว replayGame () {สตริง Command = String.format ("ADB เชลล์อินพุตแตะ %S %S", Swipex, Swipey); ExecuteCommand (คำสั่ง); } / ** * คำนวณระยะทางของการกระโดดนั่นคือระยะทางระหว่างสองจุด * * @param halmax * @param halmay * @param boardx * @param boardy * @return * @author leho * @update 31 ธันวาคม 2017 เวลา 12:27:30 น. Math.sqrt (Math.pow (Math.Abs (BoardX - Halmax), 2) + Math.pow (Math.Abs (Boardy - Halmay), 2)); } โมฆะคงที่สาธารณะหลัก (สตริง [] args) {jumpjumphelper jumpjumphelper = neumpjumphelper ใหม่ (); // string command = "adb shell screencap -p" + jumpjumphelper.path + image_name; //// command = "อุปกรณ์ ADB"; // jumpjumphelper.executecommand (คำสั่ง); // // ถ้า (จริง) {return;} ลอง {ไฟล์ retoredir = ไฟล์ใหม่ (store_dir); ถ้า (! if (! flag) {system.err.println ("สร้างไดเรกทอรีการจัดเก็บภาพล้มเหลว"); กลับ; }} // จำนวนการดำเนินการ int executeCount = 0; สำหรับ (;;) {// เรียกใช้คำสั่ง ADB เพื่อรับ Android Screenshot jumpjumphelper.executeadbcaptureCommands (); ไฟล์ currentImage = ไฟล์ใหม่ (store_dir, image_name); if (! currentImage.exists ()) {system.out.println ("ภาพไม่มีอยู่"); ดำเนินการต่อ; } ความยาวยาว = currentImage.length (); imageLength [executeCount % imageLength ความยาว] = ความยาว; // ตรวจสอบว่าคุณจำเป็นต้องเริ่มต้น jumpjumphelper.checkdoreplay (); ExecuteCount ++; System.out.println ("currentth" + executeCount + "การดำเนินการ!"); // รับพิกัดตรงกลางของหมากรุกและแผ่นฐาน int [] ผลลัพธ์ = jumpjumphelper.gethalmaandboardxyvalue (currentImage); if (result == null) {system.out.println ("ผลลัพธ์ของวิธีการ gethalmaandboardxyvalue เป็นโมฆะ!"); ดำเนินการต่อ; } int halmax = ผลลัพธ์ [0]; int halmay = ผลลัพธ์ [1]; int boardx = ผลลัพธ์ [2]; int boardy = ผลลัพธ์ [3]; System.out.println ("Halmax:" + Halmax + ", Halmay:" + Halmay + ", boardx:" + boardx + ", boardy:" + boardy); // คำนวณระยะทางของการกระโดดสองครั้ง jumpdistance = jumpjumphelper.computejumpdistance (Halmax, Halmay, BoardX, Boardy); jumpjumphelper.dojump (jumpdistance); // อยู่ที่ 2.5 วินาทีในแต่ละเวลา TimeUnit.milliseconds.sleep (2,500); }} catch (exception e) {e.printstacktrace (); }} / ** * ตรวจสอบว่าคุณจำเป็นต้องรีสตาร์ท * * @author leeho * @update 31 ธันวาคม 2017 1:39:18 PM * / โมฆะส่วนตัว checkdorePlay () {ถ้า (imageLength [0]> 0 && imageLength [0] == imageLength [1] && imageLength [3] == imageLength [4]) {// ซึ่งหมายความว่าขนาดภาพเหมือนกันเป็นเวลา 5 ครั้งติดต่อกัน คุณสามารถรู้ได้ว่าหน้าจอปัจจุบันอยู่ในอาร์เรย์อีกรอบการเติม (imageLength, 0); // จำลองและคลิกปุ่มเพื่อเริ่มเกม replayGame อีกครั้ง (); }} / ** * รับค่า RGB ของพิกัดที่ระบุ * * @param bufferedImage * @param x * @param y * @author leeho * @update 2017-02-31 12:12:43 PM * / processrgbinfo int pixel = bufferedimage.getRgb (x, y); // แปลงเป็น rgb digit this.rgbinfo.setrvalue ((พิกเซล & 0xff0000) >> 16); this.rgbinfo.setGvalue ((Pixel & 0xff000) >> 8); this.rgbinfo.setBvalue ((Pixel & 0xff)); } คลาส rgbinfo {private int rvalue; ส่วนตัว int gvalue; ส่วนตัว int bvalue; สาธารณะ int getRvalue () {return rvalue; } โมฆะสาธารณะ setrvalue (int rvalue) {rvalue = rvalue; } public int getGvalue () {return gvalue; } โมฆะสาธารณะ setGvalue (int gvalue) {gvalue = gvalue; } public int getBvalue () {return bvalue; } โมฆะสาธารณะ setBvalue (int bvalue) {bvalue = bvalue; } โมฆะสาธารณะรีเซ็ต () {this.rvalue = 0; this.gvalue = 0; this.bvalue = 0; -แน่นอนว่าผลลัพธ์จะถูกล้างหลังจากผ่านไประยะหนึ่ง แต่ในฐานะโปรแกรมเมอร์มันก็ยังดีอยู่ จากช่องโหว่การส่งโพสต์เริ่มต้นคอมพิวเตอร์ถูกขอให้คว้าแพ็กเก็ตและแก้ไขข้อมูลเป็นตัวแทน ตอนนี้รหัสจำลองการคลิก (แม้ว่ามันจะไม่มีผล)
สำหรับเนื้อหาเพิ่มเติมคุณสามารถอ้างถึงหัวข้อพิเศษ "Jump on WeChat" เพื่อเรียนรู้
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น