【演算法】游戲中的學習,使用c#面向對象特性控制游戲角色移動

来源:https://www.cnblogs.com/lan80/archive/2023/10/12/17758226.html
-Advertisement-
Play Games

<工作記錄——Report> 報表前的數據獲取操作是高重覆性的,今天差不多完成了腳本,下述是代碼: 1 // See https://aka.ms/new-console-template for more information 2 using System.IO; 3 using System. ...


最近,小悅的生活像是一首繁忙的交響曲,每天忙得團團轉,雖然她的日程安排得滿滿噹噹,但她並未感到充實。相反,她很少有時間陪伴家人,這讓她感到有些遺憾。在周五的午後,小悅的哥哥突然打來電話,他的聲音里充滿了焦慮。

“小悅,我有個事情想拜托你。”哥哥的聲音傳來。

小悅不禁有些疑惑,哥哥有什麼事情需要她幫忙呢?她忍不住問:“哥哥,有什麼需要我幫忙的嗎?”

哥哥解釋說:“我最近要出差一段時間,大概一個星期左右。而我的妻子目前正在照顧住院的父母,沒有時間照顧小明。我想請你幫忙照顧小明一段時間。”

小悅愣住了,沒想到哥哥會把這個重任托付給她。這是一個不小的挑戰,她有些擔心自己無法勝任。但是,她知道她不能讓自己的感情影響到哥哥的決定。於是她堅定地回答:“好的,哥哥,我會照顧好小明的。你放心去出差吧。”

電話那頭的哥哥鬆了一口氣,感激地說:“謝謝你,小悅。我相信你會照顧好小明的。我會儘快回來的。”

就這樣,小悅接下了照顧小明的重任。雖然她很忙,但是她覺得為了哥哥和小明,她要付出更多的努力和時間。接下來的幾天,小悅事無巨細地照顧著小明,給他做飯、洗衣、輔導作業,盡職盡責地扮演著一個姑姑的角色。

在周末的下午,小悅坐在電腦前,專註地處理著工作。她穿著舒適的衣褲,一頭長髮隨意扎起,給人一種親切自然的感覺。突然,門口傳來了敲門聲,小悅放下手中的工作,打開門一看,原來是她的侄兒小明。

小明是個活潑好動的孩子,二年級的他還保留著童年的純真和好奇。他瞪大了眼睛,好奇地看著小悅的電腦屏幕:“姐姐,你在乾什麼呀?”小悅微微一笑,糾正道:“我是姑姑,不是姐姐。”小明尷尬地撓了撓頭,趕緊改口:“姑姑,你在乾什麼呀?”

小悅笑著回答:“我在寫程式呀。”

“程式?可以教我嗎?”小明充滿期待地問。

“當然可以,”小悅點點頭,她向小明介紹了一下編程的基本知識和規則,然後開始手把手地教他如何編寫簡單的游戲程式。

小悅耐心地教導小明如何設計坦克模擬游戲。她先向他介紹了游戲的基本規則,然後手把手地教他如何用程式操作鍵盤上的十字鍵來控制屏幕中的坦克移動。在這個過程中,小悅始終保持著微笑,她溫柔的話語和細心的指導讓小明倍感親切。

時間在不知不覺中流逝,小悅的心裡也漸漸感到了疲憊。但每當看到小明在編程的世界中自由翱翔的時候,她的心裡就充滿了欣慰和自豪。小明也漸漸地開始明白了編程的奧秘,他的興趣被極大地激發了出來,每天都充滿了新的期待和挑戰。儘管這段日子很累很忙,但小悅覺得很有意義。因為她知道這段時間對小明來說是寶貴的,而她也有幸參與其中,這讓她感到無比的滿足和幸福。


 小悅使用面向對象的思想,設計了一個名為PlayerMovement的類,用於實時控制游戲中玩家的移動。該類包含一個directions列表,用於存儲當前按下的方向鍵。Position屬性表示當前玩家的位置,Direction屬性表示當前玩家的方向。

演算法實現1:

 1  public enum Direction { Up = 8, Down = 2, Left = 4, Right = 6 }
 2   
 3   public struct Tile
 4   {
 5       public int X { get; }
 6       public int Y { get; }
 7       
 8       public Tile(int x, int y);
 9   }
10   
11   public static class Input
12   {
13       // pressed = true, released = false
14       public static bool GetState(Direction direction);
15   }
 1 public class PlayerMovement
 2 {
 3     private List<Direction> directions = new List<Direction>();
 4 
 5     public Tile Position { get; private set; }
 6     public Direction Direction { get; private set; }
 7 
 8     public PlayerMovement(int x, int y)
 9     {
10         // 初始化玩家位置
11         this.Position = new Tile(x, y);
12     }
13 
14     public void Update()
15     {
16         // 獲取新的方向
17         this.directions = GetNewDirections(this.directions);
18         if (!this.directions.Any()) return;
19 
20         var currentDirection = this.directions.Last();
21         if (this.Direction != currentDirection)
22         {
23             // 更新玩家方向
24             this.Direction = currentDirection;
25         }
26         else
27         {
28             // 獲取新的位置
29             this.Position = GetNewPosition(this.Position, this.Direction);
30         }
31     }
32 
33     private static List<Direction> GetNewDirections(IEnumerable<Direction> current)
34     {
35         var newState = current.ToList();
36 
37         var currentDirections = GetCurrentDirections().ToList();
38 
39         var directionsToRemove = newState.Except(currentDirections).ToList();
40         directionsToRemove.ForEach(d => newState.Remove(d));
41 
42         var directionsToAdd = currentDirections.Except(newState).ToList();
43         directionsToAdd.ForEach(d => newState.Add(d));
44 
45         return newState;
46     }
47 
48     private static Tile GetNewPosition(Tile pos, Direction dir)
49     {
50         var newX = pos.X;
51         var newY = pos.Y;
52 
53         switch (dir)
54         {
55             case Direction.Left:
56                 newX--;
57                 break;
58             case Direction.Right:
59                 newX++;
60                 break;
61             case Direction.Down:
62                 newY--;
63                 break;
64             case Direction.Up:
65                 newY++;
66                 break;
67         }
68 
69         return new Tile(newX, newY);
70     }
71 
72     private static IEnumerable<Direction> GetCurrentDirections()
73     {
74         // 通過yield return獲取當前按鍵狀態並返回對應的方向
75         if (Input.GetState(Direction.Right)) yield return Direction.Right;
76         if (Input.GetState(Direction.Left)) yield return Direction.Left;
77         if (Input.GetState(Direction.Down)) yield return Direction.Down;
78         if (Input.GetState(Direction.Up)) yield return Direction.Up;
79     }
80 }

通過測試用例解釋運行過程:

 1       private PlayerMovement _player;
 2   
 3       private void TestEquality(Direction direction, int x, int y)
 4       {
 5           _player.Update();
 6   
 7           Assert.AreEqual(direction, _player.Direction);
 8           Assert.AreEqual(new Tile(x, y), _player.Position);
 9       }
10   
11       [Test(Description = "Basic Test 1")]
12       public void BasicTest1()
13       {
14           _player = new PlayerMovement(0, 0);
15           Input.Clear();
16 
17           Press(Direction.Down);
18 
19           TestEquality(Direction.Down, 0, 0);
20           TestEquality(Direction.Down, 0, -1);
21           TestEquality(Direction.Down, 0, -2);
22 
23           Press(Direction.Left);
24           Press(Direction.Right);
25 
26           TestEquality(Direction.Left, 0, -2);
27           TestEquality(Direction.Left, -1, -2);
28 
29           Release(Direction.Left);
30 
31           TestEquality(Direction.Right, -1, -2);
32 
33           Release(Direction.Right);
34 
35           TestEquality(Direction.Down, -1, -2);
36           TestEquality(Direction.Down, -1, -3);
37 
38           Release(Direction.Down);
39 
40           TestEquality(Direction.Down, -1, -3);
41       }

首先,我們創建了一個名為_playerPlayerMovement對象,並將其初始位置設置為(0, 0)。然後,我們清除了輸入狀態。

接下來,我們按下了向下方向鍵。這將觸發Input.GetState(Direction.Down)返回true,所以GetCurrentDirections函數將返回一個包含Direction.Down的集合。然後,GetNewDirections函數將檢查當前方向列表directions和新的方向集合之間的差異,並更新directions列表。由於directions列表只包含一個元素Direction.Down,所以它不會發生任何變化。

TestEquality方法中,我們首先調用了_player.Update()來更新玩家的狀態。根據當前方向Direction.Down,我們期望玩家的位置為(0, -1)。然後,我們使用Assert.AreEqual方法來檢查玩家的方向和位置是否與預期相符。

接下來,我們再次調用_player.Update()來更新玩家的狀態。根據當前方向Direction.Down,我們期望玩家的位置為(0, -2)。我們再次使用Assert.AreEqual方法來檢查玩家的方向和位置是否與預期相符。

然後,我們按下了向左和向右方向鍵。這將觸發Input.GetState(Direction.Left)Input.GetState(Direction.Right)都返回true,所以GetCurrentDirections函數將返回一個包含Direction.LeftDirection.Right的集合。然後,GetNewDirections函數將檢查當前方向列表directions和新的方向集合之間的差異,並更新directions列表。由於directions列表已經包含了Direction.Down,所以它將保持不變。

TestEquality方法中,我們再次調用了_player.Update()來更新玩家的狀態。根據當前方向Direction.Down,我們期望玩家的位置為(0, -2)。我們再次使用Assert.AreEqual方法來檢查玩家的方向和位置是否與預期相符。

然後,我們再次調用了_player.Update()來更新玩家的狀態。根據當前方向Direction.Left,我們期望玩家的位置為(-1, -2)。我們再次使用Assert.AreEqual方法來檢查玩家的方向和位置是否與預期相符。

接下來,我們釋放了向左方向鍵。這將觸發Input.GetState(Direction.Left)返回false,所以GetCurrentDirections函數將返回一個不包含Direction.Left的集合。然後,GetNewDirections函數將檢查當前方向列表directions和新的方向集合之間的差異,並更新directions列表。由於directions列表已經包含了Direction.DownDirection.Right,所以它將保持不變。

TestEquality方法中,我們再次調用了_player.Update()來更新玩家的狀態。根據當前方向Direction.Right,我們期望玩家的位置為(-1, -2)。我們再次使用Assert.AreEqual方法來檢查玩家的方向和位置是否與預期相符。

然後,我們釋放了向右方向鍵。這將觸發Input.GetState(Direction.Right)返回false,所以GetCurrentDirections函數將返回一個不包含Direction.Right的集合。然後,GetNewDirections函數將檢查當前方向列表directions和新的方向集合之間的差異,並更新directions列表。由於directions列表已經包含了Direction.Down,所以它將保持不變。

TestEquality方法中,我們再次調用了_player.Update()來更新玩家的狀態。根據當前方向Direction.Down,我們期望玩家的位置為(-1, -2)。我們再次使用Assert.AreEqual方法來檢查玩家的方向和位置是否與預期相符。

最後,我們再次調用了_player.Update()來更新玩家的狀態。根據當前方向Direction.Down,我們期望玩家的位置為(-1, -3)。我們再次使用Assert.AreEqual方法來檢查玩家的方向和位置是否與預期相符。


演算法實現2:

 1 public class PlayerMovement
 2 {
 3     public Tile Position { get; private set; }  // 玩家的位置
 4     public Direction Direction { get; private set; }  // 玩家的方向
 5     
 6     // 不同方向對應的坐標變化
 7     private Dictionary<Direction, (int xDelta, int yDelta)> moves = new Dictionary<Direction, (int xDelta, int yDelta)>()
 8     {
 9         { Direction.Up, (0, 1) },
10         { Direction.Down, (0, -1) },
11         { Direction.Left, (-1, 0) },
12         { Direction.Right, (1, 0) }
13     };
14     
15     // 方向的排序順序
16     private Direction[] sortOrder = new[] {Direction.Up, Direction.Down, Direction.Left, Direction.Right};
17     
18     private Stack<Direction> directions = new Stack<Direction>();  // 當前的方向列表
19     
20     public PlayerMovement(int x, int y)
21     {
22         this.Position = new Tile(x, y);  // 初始化玩家的位置
23     }
24     
25     public void Update()
26     {
27         Console.WriteLine("Called update");  // 輸出調試信息
28         
29         // 獲取當前按下的方向鍵
30         var pressedDirections = Enum.GetValues(typeof(Direction)).Cast<Direction>().Where(x => Input.GetState(x));
31         
32         // 清除不再按下的方向鍵
33         while (directions.Count != 0 && !pressedDirections.Contains(directions.Peek())) {
34             directions.Pop();
35         }
36         
37         if (pressedDirections.Count() == 0) {
38             return;  // 如果沒有按下任何方向鍵,則直接返回
39         }
40         
41         // 獲取新按下的方向鍵,並按照排序順序進行排序
42         var newDirections = pressedDirections.Except(directions).OrderBy(x => Array.IndexOf(sortOrder, x)).ToArray();
43         
44         // 將新的方向鍵加入到方向列表中
45         for (int i = newDirections.Length - 1; i >= 0; i -= 1) {
46             directions.Push(newDirections[i]);
47         }
48         
49         Direction directionToMove = directions.Peek();  // 獲取要移動的方向
50         
51         if (directionToMove == this.Direction) {
52             // 如果要移動的方向與當前方向相同,則更新玩家的位置
53             (int xDelta, int yDelta) = moves[directionToMove];
54             this.Position = new Tile(this.Position.X + xDelta, this.Position.Y + yDelta);
55         }
56         else {
57             // 如果要移動的方向與當前方向不同,則更新玩家的方向
58             this.Direction = directionToMove;
59         }
60     }
61 }

演算法2的運行步驟如下:

  1. 獲取當前按下的方向鍵。
  2. 清除不再按下的方向鍵。
  3. 如果沒有按下任何方向鍵,則直接返回。
  4. 獲取新按下的方向鍵,並按照排序順序進行排序。
  5. 將新的方向鍵加入到方向列表中。
  6. 獲取要移動的方向。
  7. 如果要移動的方向與當前方向相同,則更新玩家的位置。
  8. 如果要移動的方向與當前方向不同,則更新玩家的方向。

優點:

  1. 實現簡單,易於理解。
  2. 可以處理多個方向鍵同時按下的情況。

缺點:

  1. 在處理多個方向鍵同時按下的情況時,可能會出現按鍵順序和預期不一致的情況。
  2. 對於複雜的移動邏輯,可能需要添加更多的代碼來處理。

 

總結,這兩個PlayerMovement類都是面向對象的,但是它們的實現方式略有不同:

1. 數據封裝

演算法2類使用屬性來封裝位置和方向,而演算法1類也使用屬性來封裝位置和方向。兩者的數據封裝方式相同。

2. 代碼組織

演算法2類使用一個Update方法來更新玩家位置和方向,而演算法1類也使用一個Update方法來更新玩家位置和方向。兩者的代碼組織方式相同。

3. 代碼復用

演算法2類使用了一個moves字典來存儲方向和移動量的對應關係,而演算法1類則沒有使用字典,而是使用了GetCurrentDirections方法和GetNewPosition方法來計算新的方向和位置。兩者的代碼復用方式略有不同。

4. 可擴展性

演算法2類使用了一個sortOrder數組來定義方向的排序,而演算法1類則沒有使用這種方式。演算法1類使用了GetNewDirections方法,利用yield return特性來計算新的方向,這種方式更加靈活和可擴展。

它們都具有良好的數據封裝和代碼組織,以及可擴展性和代碼復用性。其中,演算法1類更加靈活和可擴展,適用於更加複雜的場景,例如:

  1. 虛擬現實和增強現實應用:在虛擬現實和增強現實應用中,用戶通常需要通過手柄、控制器或手勢來控制虛擬對象的移動。PlayerMovement演算法可以用於處理用戶輸入的方向指令,並更新虛擬對象的位置和方向。

  2. 機器人控制:在機器人控制領域,PlayerMovement演算法可以用於處理機器人的移動指令。例如,將方向鍵映射到機器人的移動方向,並根據按鍵的順序來確定機器人的移動路徑。

  3. 自動駕駛系統:在自動駕駛系統中,PlayerMovement演算法可以用於處理車輛的移動指令。例如,將方向鍵映射到車輛的轉向角度,並根據按鍵的順序來確定車輛的轉向路徑。

  4. 智能家居系統:在智能家居系統中,PlayerMovement演算法可以用於處理家居設備的移動指令。例如,將方向鍵映射到智能燈泡的亮度和顏色,並根據按鍵的順序來調整燈泡的狀態。


測試用例:

  1 using NUnit.Framework;
  2 using System;
  3 using System.Collections.Generic;
  4 using System.Linq;
  5 
  6 namespace TopDownMovement
  7 {
  8   [TestFixture]
  9   public class SolutionTest
 10   {
 11       private PlayerMovement _player;
 12   
 13       private void TestEquality(Direction direction, int x, int y)
 14       {
 15           _player.Update();
 16   
 17           Assert.AreEqual(direction, _player.Direction);
 18           Assert.AreEqual(new Tile(x, y), _player.Position);
 19       }
 20   
 21       [Test(Description = "Basic Test 1")]
 22       public void BasicTest1()
 23       {
 24           _player = new PlayerMovement(0, 0);
 25           Input.Clear();
 26 
 27           Press(Direction.Down);
 28 
 29           TestEquality(Direction.Down, 0, 0);
 30           TestEquality(Direction.Down, 0, -1);
 31           TestEquality(Direction.Down, 0, -2);
 32 
 33           Press(Direction.Left);
 34           Press(Direction.Right);
 35 
 36           TestEquality(Direction.Left, 0, -2);
 37           TestEquality(Direction.Left, -1, -2);
 38 
 39           Release(Direction.Left);
 40 
 41           TestEquality(Direction.Right, -1, -2);
 42 
 43           Release(Direction.Right);
 44 
 45           TestEquality(Direction.Down, -1, -2);
 46           TestEquality(Direction.Down, -1, -3);
 47 
 48           Release(Direction.Down);
 49 
 50           TestEquality(Direction.Down, -1, -3);
 51       }
 52 
 53       [Test(Description = "All keys at once")]
 54       public void BasicTest2()
 55       {
 56           _player = new PlayerMovement(0, 0);
 57           Input.Clear();
 58 
 59           Press(Direction.Down);
 60           Press(Direction.Left);
 61           Press(Direction.Right);
 62           Press(Direction.Up);
 63 
 64           TestEquality(Direction.Up, 0, 0);
 65           TestEquality(Direction.Up, 0, 1);
 66 
 67           Release(Direction.Left);
 68 
 69           TestEquality(Direction.Up, 0, 2);
 70 
 71           Release(Direction.Up);
 72 
 73           TestEquality(Direction.Down, 0, 2);
 74 
 75           Release(Direction.Down);
 76 
 77           TestEquality(Direction.Right, 0, 2);
 78           TestEquality(Direction.Right, 1, 2);
 79           TestEquality(Direction.Right, 2, 2);
 80 
 81           Release(Direction.Right);
 82 
 83           TestEquality(Direction.Right, 2, 2);
 84       }
 85 
 86       [Test(Description = "Random Test")]
 87       public void RandomTest()
 88       {
 89           int x, y;
 90           Random rand = new Random();
 91 
 92           x = rand.Next(200) - 100;
 93           y = rand.Next(200) - 100;
 94 
 95           _player = new PlayerMovement(x, y);
 96           Input.Clear();
 97 
 98           Press(Direction.Down);
 99           Press(Direction.Left);
100           Press(Direction.Right);
101           Press(Direction.Up);
102 
103           TestEquality(Direction.Up, x, y);
104 
105           for (int i = 0; i < rand.Next(20) + 1; i++)
106           {
107               y++;
108               TestEquality(Direction.Up, x, y);
109           }
110 
111           Release(Direction.Left);
112 
113           y++;
114           TestEquality(Direction.Up, x, y);
115 
116           Release(Direction.Up);
117 
118           TestEquality(Direction.Down, x, y);
119 
120           Release(Direction.Down);
121 
122           TestEquality(Direction.Right, x, y);
123           x++;
124           TestEquality(Direction.Right, x, y);
125           x++;
126           TestEquality(Direction.Right, x, y);
127 
128           Release(Direction.Right);
129 
130           TestEquality(Direction.Right, x, y);
131       }
132 
133       private void Press(Direction dir) { Console.WriteLine("Pressed " + dir); Input.Press(dir); }
134       private void Release(Direction dir) { Console.WriteLine("Released " + dir); Input.Release(dir); }
135   }
136 }

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 之前,我們通過一系列文章,介紹瞭如何在Spring Boot中發送郵件: 發送郵件 添加附件 引用靜態資源 郵件模版 已經包含了大部分的應用場景。但最近DD在做YouTube中文配音的時候,碰到一個問題: 如上圖所示,收件人在客戶端收到的時候,顯示的名稱是郵箱的首碼,而不是我們的產品名稱,也就是郵箱 ...
  • 1. 依賴傳遞 在Maven中,依賴是會傳遞的,假如在業務項目中引入了spring-boot-starter-web依賴: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter ...
  • 百分比堆疊式柱狀圖是一種特殊的柱狀圖,它的每根柱子是等長的,總額為100%。柱子內部被分割為多個部分,高度由該部分占總體的百分比決定。 百分比堆疊式柱狀圖不顯示數據的“絕對數值”,而是顯示“相對比例”。但同時,它也仍然具有柱狀圖的固有功能,即“比較”——我們可以通過比較多個柱子的構成,分析數值之間的 ...
  • 基於java流浪動物領養系統設計與實現,可適用於流浪動物救助及領養管理系統,寵物教學、領養寵物、寵物認領、領養申請、動物認領信息,動物申請認領等等,流浪寵物救助系統; ...
  • 但近期部署系統和自己的開發項目時,發現debian系統安裝框架還是非常方便,我就把自己整理的常規部署命令貼出來,希望對大家有用處,基本對.NET CORE的開發者足夠用了 ...
  • 不知道大家有沒有瞭解FreeSSL,我近期發展這個網站 https://freessl.cn,如果你們都是個人站點,對證書沒什麼特別要求,可以考慮用他們家生成的證書,並且能自動續費,完全不用操心。 ...
  • 一 .netframework程式遷移到.netcore5.0對於.netframwork程式想要升級為.netcore5.0的方法,微軟官方也給出了方法見 https://docs.microsoft.com/en-us/dotnet/desktop/winforms/migration/?vie ...
  • C#核心 面向對象--封裝 用程式來抽象現實世界,(萬物皆對象)來編程實現功能。 三大特性:封裝、繼承、多態。 類與對象 聲明位置:namespace中 樣式:class 類名{} 命名:帕斯卡命名法(首字母大寫) 實例化對象:根據類來新建一個對象。Person p=new Person(); 成員 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...