激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C# - 跳一跳自動跳躍C#代碼實現

跳一跳自動跳躍C#代碼實現

2022-02-19 15:21iaplayer C#

這篇文章主要為大家詳細介紹了跳一跳自動跳躍C#代碼實現,具有一定的參考價值,感興趣的小伙伴們可以參考一下

      最近這款“跳一跳”很火,在段子里面看到有人才放了張畫著坐標的紙在手機上,說根據距離確定摁的“嘟”的次數,還有通過程序來實現自動計算的。看得心血來潮忍不住來試一試?話不多說,先上圖。

跳一跳自動跳躍C#代碼實現跳一跳自動跳躍C#代碼實現

       因為比較急著做出成品,所以細節上沒多細摳。感覺設置的跳躍速度稍快了一點,有興趣的同學可以實測一下。也有一個因素是測試時后臺程序比較多,影響了結果。
       原理其實也是跟大家想的一樣很簡單,無非就是三個要素:距離、速度、時間。就是通過當前小藍人腳底所在的像素坐標和目標平臺中心像素的坐標計算距離,除以事先通過測試得出的速度,得出觸摸屏幕時間,由程序發出“觸摸”指令,實現定點跳躍。不過在做自動計算跳躍所需觸摸時間之前還是要做一些準備功夫的。下面直接說一下詳細的過程吧。

準備工作:

1、通過ps等工具獲取①小藍人最底下一行(作為當前位置y坐標)和最左邊一列(作為當前位置x坐標)的像素rgb,實測在本機基本都是一樣的x(54,63, 102),y(43, 43, 73)。圖片左上角、右下角坐標分別為[0,0][xmax,ymax]。②獲取小藍人的頭的寬度(所占像素點)。③獲取左上角分數最底下一行的像素y坐標。

2、通過指令

?
1
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、手機開啟調試模式,連接電腦,打開“跳一跳” 

過程:

一、獲取設備號(獲取序列號,或者直接查看手機信息),指令:

?
1
adb devices

二、截取手機當前畫面到sd卡(本機存儲格式為png,實測手機按鍵截屏為jpg(失真)),指令:

?
1
adb -s 設備號 shell screencap -p /sdcard/temp.png

三、復制文件到電腦,指令:

?
1
adb -s 設備號 pull /sdcard/temp.png 保存路徑

四、刪除文件,指令:

?
1
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、那就用我們的勾三股四弦五定理再開根求出距離。距離除以速度得出時間。

六、發送觸摸指令實現定時跳躍,指令:

?
1
adb shell input touchscreen swipe x y x y延時(ms)

       這里不得不說一下,當時找半天找不到定時觸摸的指令,網上有個用6個指令組合實現定時觸摸屏幕的方法,但實測無效,而且也怕指令這么多,延時還是分開控制,肯定會對跳躍結果有很大影響。后面看到一條利用swipe指令實現的評論,真是醒目。swipe雖然是滑動指令,但如果設置起止坐標都是同一個坐標不就相當于實現了定點定時觸摸了嗎。

七、七就是一直重復二~六的步驟就是了。

       本次測試很東西都是急著做,沒仔細研究,例如獲取跳躍速度這個就是傻瓜式的通過手動發送跳躍指令、截圖用ps手動計算出來的。大家可以用代碼實現一下。希望大家指正可以改進的地方。

c#源碼如下

cmd類,實現cmd執行命令

?
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
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字節

?
1
2
3
4
5
6
7
8
class pixel
 {
 public byte[] pixel = new byte[3];
 public pixel()
 {
 
 }
 }

playjumpjump類,實現主要分析計算和跳躍操作

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

測試:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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();
 }
 }

更多內容大家可以參考專題《微信跳一跳》進行學習。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://blog.csdn.net/iaplayer/article/details/79008711

延伸 · 閱讀

精彩推薦
  • C#WPF 自定義雷達圖開發實例教程

    WPF 自定義雷達圖開發實例教程

    這篇文章主要介紹了WPF 自定義雷達圖開發實例教程,本文介紹的非常詳細,具有參考借鑒價值,需要的朋友可以參考下...

    WinterFish13112021-12-06
  • C#C#通過KD樹進行距離最近點的查找

    C#通過KD樹進行距離最近點的查找

    這篇文章主要為大家詳細介紹了C#通過KD樹進行距離最近點的查找,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    帆帆帆6112022-01-22
  • C#C#實現XML文件讀取

    C#實現XML文件讀取

    這篇文章主要為大家詳細介紹了C#實現XML文件讀取的相關代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    Just_for_Myself6702022-02-22
  • C#C#裁剪,縮放,清晰度,水印處理操作示例

    C#裁剪,縮放,清晰度,水印處理操作示例

    這篇文章主要為大家詳細介紹了C#裁剪,縮放,清晰度,水印處理操作示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    吳 劍8332021-12-08
  • C#C# 實現對PPT文檔加密、解密及重置密碼的操作方法

    C# 實現對PPT文檔加密、解密及重置密碼的操作方法

    這篇文章主要介紹了C# 實現對PPT文檔加密、解密及重置密碼的操作方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下...

    E-iceblue5012022-02-12
  • C#深入解析C#中的交錯數組與隱式類型的數組

    深入解析C#中的交錯數組與隱式類型的數組

    這篇文章主要介紹了深入解析C#中的交錯數組與隱式類型的數組,隱式類型的數組通常與匿名類型以及對象初始值設定項和集合初始值設定項一起使用,需要的...

    C#教程網6172021-11-09
  • C#C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題實例

    C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題實例

    這篇文章主要介紹了C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題,簡單描述了訪問者模式的定義并結合具體實例形式分析了C#使用訪問者模式解決長...

    GhostRider9502022-01-21
  • C#Unity3D實現虛擬按鈕控制人物移動效果

    Unity3D實現虛擬按鈕控制人物移動效果

    這篇文章主要為大家詳細介紹了Unity3D實現虛擬按鈕控制人物移動效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一...

    shenqingyu060520232410972022-03-11
主站蜘蛛池模板: 国产一区二区二 | 九九热精| 亚洲男人的天堂在线视频 | 国产小视频在线观看 | 黄视频免费在线观看 | 91看片在线观看视频 | 成人三级黄色片 | 黄视频免费在线 | 九九热免费精品视频 | 成人毛片在线免费观看 | 国产一区二区免费看 | 91 视频网站 | 欧美一级高清片在线 | 国产免费网站视频 | www.guochanav.com| 免费视频观看 | 欧美一区二区精品夜夜嗨 | 久久精品污 | 一区二区三区四区五区中文字幕 | 大号bbwassbigav头交| 99影视在线视频免费观看 | 精品国产亚洲人成在线 | 中文字幕在线永久 | 国产亚洲精品久久久久婷婷瑜伽 | 久久国产综合视频 | 色97在线 | 亚洲二区三区在线 | 91精品老司机 | 亚洲人成在线播放 | 黄色网址www | www.777含羞草 | 精品国产一区二区三区久久久蜜月 | 宅男噜噜噜66国产免费观看 | 国产成人高清成人av片在线看 | 国产在线欧美日韩 | 欧美a∨一区二区三区久久黄 | 国产高潮好爽好大受不了了 | 一区二区三区日韩在线 | 三人弄娇妻高潮3p视频 | 手机黄色小视频 | 高清国产福利 |