【趣味分享】C#實現回味童年的24點演算法游戲

来源:http://www.cnblogs.com/SeeYouBug/archive/2016/12/26/6218700.html
-Advertisement-
Play Games

一、24點游戲玩法規則效果展示 1、初始化界面 2、開始游戲界面 3、游戲超時界面 4、查看答案界面 5、答對界面 6、答錯界面 7、計算表達式的驗證界面 8、一副牌算完開始新一副牌界面 到這裡24點演算法基本操作圖就結束了,下麵來看看示例代碼吧。 二、完整代碼演示 關於代碼解釋,為了方便讀者瀏覽時更 ...


 一、24點游戲玩法規則效果展示

1、初始化界面

2、開始游戲界面

3、游戲超時界面

 

4、查看答案界面

 

5、答對界面

6、答錯界面

7、計算表達式的驗證界面

 

8、一副牌算完開始新一副牌界面

 到這裡24點演算法基本操作圖就結束了,下麵來看看示例代碼吧。

二、完整代碼演示

 關於代碼解釋,為了方便讀者瀏覽時更好理解代碼的含義,我把註釋都寫在代碼裡面了。因為一開始我只考慮到功能上的實現並沒有考慮代碼的優化所以代碼我就全寫在一個頁面了。至於那些生成撲克牌類、計算類等代碼優化方面的內容就留給想要實現這個24點演算法游戲的讀者自己去完善吧。

  1 using System;
  2 using System.Collections;
  3 using System.Collections.Generic;
  4 using System.ComponentModel;
  5 using System.Data;
  6 using System.Drawing;
  7 using System.IO;
  8 using System.Linq;
  9 using System.Text;
 10 using System.Threading.Tasks;
 11 using System.Windows.Forms;
 12 
 13 namespace XF_24Point
 14 {
 15     public partial class frnMain : Form
 16     {
 17         private int A, B, C, D;//牌面大小對應的數字大小也用於交換數字的位置
 18         private int NumberA, NumberB, NumberC, NumberD;//牌面大小對應的數字大小
 19         private int topCard;//顯示在窗體四張牌中撲克牌的編號(1-52)
 20         DateTime beginTime;//記錄開始時間
 21       
 22         #region 一副牌的生成
 23         //結構: 值得一提的是,在C++中,struct的功能得到了強化,struct不僅可以添加成員變數,還可以添加成員函數,和class類似。
 24         struct card
 25         {
 26             public int face;//牌面大小,數字大小
 27             public int suit;//牌面花色,如梅花、黑桃、紅心、方塊,只能有四張
 28             public int count;//牌面點數,牌面上的的圖案點數
 29             public bool faceup;//牌面是否向上
 30         }
 31         private card[] PlayingCards;//一副牌
 32 
 33         //生成一副牌
 34         private void GetPlayingCareds()
 35         {
 36             PlayingCards = new card[53];
 37             int i;//牌面大小
 38             int j;//牌面花色
 39             for (i = 0; i < 13; i++)
 40             {
 41                 for (j = 1; j <= 4; j++)
 42                 {
 43                     PlayingCards[j + i * 4].face = i + 1;//PlayingCards[j + i * 4]:指的是:j + i * 4  =>獲取文件圖片撲克牌的序號
 44                     PlayingCards[j + i * 4].suit = j;//牌面花色,如梅花、黑桃、紅心、方塊,只能有四張
 45                     if (i < 10)
 46                     {
 47                         PlayingCards[j + i * 4].count = i + 1;//牌面點數,牌面上的的圖案點數
 48                     }
 49                     else
 50                     {
 51                         PlayingCards[j + i * 4].count = 10;
 52                     }
 53                     PlayingCards[j + i * 4].faceup = false;
 54                 }
 55             }
 56         }
 57         //洗牌 :Shuffle
 58         private void Shuffle()
 59         {
 60             Random random = new Random((int)DateTime.Now.Ticks);
 61             card middleCard;//作為臨時交換牌順序的變數
 62             int j, k;
 63             for (int i = 0; i < 1000; i++)
 64             {
 65                 j = (int)random.Next(1, 52);
 66                 k = (int)random.Next(1, 52);
 67                 //打亂牌的順序(隨機交換牌的順序)
 68                 middleCard = PlayingCards[j];
 69                 PlayingCards[j] = PlayingCards[k];
 70                 PlayingCards[k] = middleCard;
 71             }
 72         }
 73         //開始游戲的時候發四張牌
 74         private void btnStart_Click(object sender, EventArgs e)
 75         {
 76             lblInput.Text = "";
 77             GetPlayingCareds();//生成一副牌
 78             Shuffle();//洗牌
 79             topCard = 0;//顯示在窗體四張牌中撲克牌的編號(1-52)
 80             int imageNum;//文件夾中撲克牌圖片的編號(文件名)
 81             string path;
 82             //畫第一張牌
 83             topCard = topCard = 1;
 84             pictureBox1.Visible = true;
 85             //獲得文件中某張牌並且知道是什麼花色對應的編號計算公式:
 86             //牌面花色(1、2、3、4):要獲得某張牌的的花色
 87             //(牌面數字大小-1)*4:要獲得的某張牌的前一個牌面大小如:要獲得的牌是10,前一個牌面就是9
 88             //牌面花色(1、2、3、4)+(牌面數字大小-1)*4
 89             imageNum = PlayingCards[topCard].suit + (PlayingCards[topCard].face - 1) * 4;//文件圖片編號
 90             path = Directory.GetCurrentDirectory() + @"\images\" + imageNum.ToString() + ".bmp";
 91             pictureBox1.Image = Image.FromFile(path);
 92             NumberA = Convert.ToInt32(PlayingCards[topCard].face);//牌面大小對應的數字大小
 93             btnNumber1.Text = NumberA.ToString();
 94             //畫第二張牌
 95             topCard = topCard + 1;
 96             pictureBox2.Visible = true;
 97             imageNum = PlayingCards[topCard].suit + (PlayingCards[topCard].face - 1) * 4;
 98             path = Directory.GetCurrentDirectory() + @"\images\" + imageNum.ToString() + ".bmp";
 99             pictureBox2.Image = Image.FromFile(path);
100             NumberB = Convert.ToInt32(PlayingCards[topCard].face);
101             btnNumber2.Text = NumberB.ToString();
102             //畫第三張牌
103             topCard = topCard + 1;
104             pictureBox3.Visible = true;
105             imageNum = PlayingCards[topCard].suit + (PlayingCards[topCard].face - 1) * 4;
106             path = Directory.GetCurrentDirectory() + @"\images\" + imageNum.ToString() + ".bmp";
107             pictureBox3.Image = Image.FromFile(path);
108             NumberC = Convert.ToInt32(PlayingCards[topCard].face);
109             btnNumber3.Text = NumberC.ToString();
110             //畫第四張牌
111             topCard = topCard + 1;
112             pictureBox4.Visible = true;
113             imageNum = PlayingCards[topCard].suit + (PlayingCards[topCard].face - 1) * 4;
114             path = Directory.GetCurrentDirectory() + @"\images\" + imageNum.ToString() + ".bmp";
115             pictureBox4.Image = Image.FromFile(path);
116             NumberD = Convert.ToInt32(PlayingCards[topCard].face);
117             btnNumber4.Text = NumberD.ToString();
118             //初始化界面控制項
119             btnStart.Visible = false;//開始游戲
120             groupBox1.Visible = true;//計算表達式
121             groupBox2.Visible = true;//查看答案
122             groupBox3.Visible = true;//游戲規則
123             lblShowTime.Visible = true;//顯示時間
124             timer1.Enabled = true;//啟用時鐘
125             beginTime = DateTime.Now;
126         }
127         #endregion
128 
129         public frnMain()
130         {
131             InitializeComponent();
132             Initialize();//初始化窗體上的控制項的方法
133         }
134 
135         //初始化窗體上的控制項的方法,一開始隱藏
136         private void Initialize()
137         {
138             pictureBox1.Visible = false;
139             pictureBox2.Visible = false;
140             pictureBox3.Visible = false;
141             pictureBox4.Visible = false;
142             groupBox1.Visible = false;
143             groupBox2.Visible = false;
144             groupBox3.Visible = false;
145             lblResult.Visible = false;
146             lblShowTime.Visible = false;
147         }
148 
149         #region 計算表達式的輸入
150         //第一張牌
151         private void btnNumber1_Click(object sender, EventArgs e)
152         {
153             lblInput.Text = lblInput.Text + btnNumber1.Text.Trim();
154         }
155         //第二張牌
156         private void btnNumber2_Click(object sender, EventArgs e)
157         {
158             lblInput.Text = lblInput.Text + btnNumber2.Text.Trim();
159         }
160         //第三張牌
161         private void btnNumber3_Click(object sender, EventArgs e)
162         {
163             lblInput.Text = lblInput.Text + btnNumber3.Text.Trim();
164         }
165         //第四章牌
166         private void btnNumber4_Click(object sender, EventArgs e)
167         {
168             lblInput.Text = lblInput.Text + btnNumber4.Text.Trim();
169         }
170         //加號
171         private void btnAdd_Click(object sender, EventArgs e)
172         {
173             lblInput.Text = lblInput.Text + btnAdd.Text.Trim();
174         }
175         //減號
176         private void btnMinus_Click(object sender, EventArgs e)
177         {
178             lblInput.Text = lblInput.Text + btnMinus.Text.Trim();
179         }
180         //乘號
181         private void btnMulti_Click(object sender, EventArgs e)
182         {
183             lblInput.Text = lblInput.Text + btnMulti.Text.Trim();
184         }
185         //除號
186         private void btnDivide_Click(object sender, EventArgs e)
187         {
188             lblInput.Text = lblInput.Text + btnDivide.Text.Trim();
189         }
190         //左括弧
191         private void btnLeft_Click(object sender, EventArgs e)
192         {
193             lblInput.Text = lblInput.Text + btnLeft.Text.Trim();
194         }
195         //右括弧
196         private void btnRight_Click(object sender, EventArgs e)
197         {
198             lblInput.Text = lblInput.Text + btnRight.Text.Trim();
199         }
200         //刪除最後一個字元
201         private void btnDelete_Click(object sender, EventArgs e)
202         {
203             string input = lblInput.Text.Trim();
204             lblInput.Text = input.Substring(0, input.Length - 1);
205         }
206         //清除所有字元
207         private void btnClear_Click(object sender, EventArgs e)
208         {
209             lblInput.Text = "";
210         }
211 
212         #endregion
213 
214         //確定按鈕
215         private void btnEnter_Click(object sender, EventArgs e)
216         {
217             if (lblInput.Text.Trim()== "")
218             {
219                 MessageBox.Show("計算表達式不能為空!");
220                 return;
221             }
222             if (CheckForNumber(lblInput.Text.Trim()))//檢查輸入表達式中輸入的數字是否匹配
223             {
224                 //計算表達式的結果第一層
225                 int result = Deal(lblInput.Text.Trim());//調用Deal()處理方法,對用戶輸入的表達式做一系列判斷計算,返回最終的結果
226                 lblResult.Visible = true;
227                 if (result == 24)
228                 {
229                     lblResult.Text = "<<---恭喜您,答對了!--->>";
230                     timer1.Enabled = false;//暫停時鐘
231                 }
232                 else
233                 {
234                     lblResult.Text = "<<--抱歉,您的回答有誤!-->>";
235                 }
236             }
237         }
238 
239         #region 驗證確定按鈕包含的一系列方法:檢查計算用戶輸入表達式結果是否正確
240         //處理Deal謂詞表達式中的括弧
241         private int Deal(string InputExp)
242         {
243             int result = 0;
244             while (InputExp.IndexOf(')') != -1)//判斷是否存在括弧 input.IndexOf(')') !=-1,表明存在括弧
245             {
246                 //3*8÷(9-8)=24、(10+2)*(3-1)=24
247                 int rightLoc = InputExp.IndexOf(')');//右括弧的位置
248                 string temp = InputExp.Substring(0, rightLoc);//從0(開始位置)到右括弧的位置,不包括右括弧(10+2
249                 int leftLoc = temp.LastIndexOf('(');//左括弧的位置0
250                 string first = InputExp.Substring(0, leftLoc);//從0到左括弧的位置,空
251                 string middle = InputExp.Substring(leftLoc + 1, rightLoc - leftLoc - 1);//括弧中間的部分10+2
252                 string last = InputExp.Substring(rightLoc + 1);//右括弧後面的部分*(3-1)
253                 //計算表達式的結果第二層
254                 InputExp = first + Formula(middle) + last; //""+10+2+*(3-1)註意:+表示連接,連接兩個字元串
255             }
256             //計算表達式的結果第二層
257             result = Formula(InputExp);//調用用戶輸入表達式檢查、計算方法,返回用戶輸入表達式的結果Formula:公式
258             return result;
259         }
260 
261         //最簡式運算 Formula:公式
262         private int Formula(string InputExp)
263         {
264             int length = InputExp.Length;//驗證表達式的長度
265             ArrayList OpeLoc = new ArrayList();//記錄運算操作符位置   
266             ArrayList Ope = new ArrayList();//記錄運算操作符 
267             ArrayList Value = new ArrayList();//記錄數值內容 ,也就是記錄輸入表達式的數字的值
268             int i;//全局變數i,運用於方法體內每個迴圈
269             for (i = 0; i < length; i++)
270             {
271                 if (IsOperator(InputExp[i]))//檢查獲判斷一個符號是否是基本算符 
272                 {
273                     OpeLoc.Add(i);//記錄並添加運算操作符位置x
274                     Ope.Add(InputExp[i]);//記錄並添加運算操作符  
275                 }
276             }
277             if (OpeLoc.Count == 0)
278             {
279                 return int.Parse(InputExp);//處理無運算符的情況
280             }
281             //計算表達式的結果第三層
282             RebuildOperator(ref OpeLoc, ref Ope);//對運算符進行重新組合,把負號和減號區分開來
283             if (!CheckFunction(OpeLoc, length))
284             {
285                 return 0;//檢查功能,判斷運算符組是否合法  ,也就是運算符位置是否正確
286             }
287             int j = 0;
288             for (i = 0; i < OpeLoc.Count; i++)
289             {
290                 Value.Add(int.Parse(InputExp.Substring(j, Convert.ToInt32(OpeLoc[i]) - j)));
291                 j = Convert.ToInt32(OpeLoc[i]) + 1;//最後一個數值的索引
292             }
293             //substring(開始索引,字元長度)
294             Value.Add(int.Parse(InputExp.Substring(j, length - j)));//處理最後一個數值的添加
295             //計算表達式的結果第四層
296             return Calculate(Ope, Value);//調用用戶輸入表達式的計算方法,參數1:運算符,參數2:數值
297         }
298 
299         //處理四則混合運算等基礎運算(+-*/)
300         private int Calculate(ArrayList Ope, ArrayList Values)
301         {
302             int i;//全局變數i,運用於方法體內每個迴圈
303             for (i = 0; i < Ope.Count; i++)//處理乘法、除法 
304             {
305                 switch (Convert.ToChar(Ope[i]))
306                 {
307                     case '*':
308                         Values[i] = Convert.ToInt32(Values[i]) * Convert.ToInt32(Values[i + 1]);
309                         Values.RemoveAt(i + 1);
310                         Ope.RemoveAt(i);
311                         i--;
312                         break;
313                     case '/':
314                         Values[i] = Convert.ToInt32(Values[i]) * Convert.ToInt32(Values[i + 1]);
315                         Values.RemoveAt(i + 1);
316                         Ope.RemoveAt(i);
317                         i--;
318                         break;
319                 }
320             }
321             for (i = 0; i < Ope.Count; i++)//處理加法和減法 
322             {
323                 switch ((char)Ope[i])
324                 {
325                     case '+':
326                         Values[i] = Convert.ToInt32(Values[i]) + Convert.ToInt32(Values[i + 1]);
327                         Values.RemoveAt(i + 1);
328                         Ope.RemoveAt(i);
329                         i--;
330                         break;
331                     case '-':
332                         Values[i] = Convert.ToInt32(Values[i]) - Convert.ToInt32(Values[i + 1]); ;
333                         Values.RemoveAt(i + 1);
334                         Ope.RemoveAt(i);
335                         i--;
336                         break;
337                 }
338             }
339             return Convert.ToInt32(Values[0].ToString());
340         }
341 
342         //判斷運算符組是否合法
343         private bool CheckFunction(ArrayList OpeLoc, int length)
344         {
345             if (Convert.ToInt32(OpeLoc[0]) == 0)//判斷第一個運算符的的索引是否為0,也就是運算符排在表達式第一個
346                 return false;
347             int i;
348             for (i = 1; i < OpeLoc.Count; i++)
349             {
350                 if (Convert.ToInt32(OpeLoc[i]) - Convert.ToInt32(OpeLoc[i - 1]) == 1)//檢查判斷兩個運算符是否連續
351                     return false;
352             }
353             //判斷最後一個運算符的的索引是否等於表達式索引的,也就是該運算符排在表達式末尾
354             if (Convert.ToInt32(OpeLoc[OpeLoc.Count - 1]) == length - 1)
355                 return false;
356             return true;
357         }
358         //對負號的處理和重構
359         private void RebuildOperator(ref ArrayList OpeLoc, ref ArrayList Ope)
360         {
361             ArrayList DelItem = new ArrayList();
362             if (Convert.ToInt32(OpeLoc[0].ToString()) == 0 && Convert.ToChar(Ope[0]) == '-')//判斷第一個符號是否是負號  ,索引為0的符號
363             {
364                 DelItem.Add(0);
365             }
366             int i;
367             for (i = 1; i < OpeLoc.Count; i++)
368             {
369                 //判斷是否有相鄰的算符且後一個是負號,且後一個運算符-前一個運算符==1
370                 if (Convert.ToChar(Ope[i]) == '-' && Convert.ToChar(Ope[i - 1]) != '-' && (Convert.ToInt32(OpeLoc[i]) - Convert.ToInt32(OpeLoc[i - 1])) != 1)
371                 {
372                     DelItem.Add(i);
373                 }
374             }
375             for (i = DelItem.Count - 1; i > 0; i--)//將負號和減號分開處理  
376             {
377                 //移除運算符和所在運算符所在位置
378                 Ope.RemoveAt(Convert.ToInt32(DelItem[i]));
379                 OpeLoc.RemoveAt(Convert.ToInt32(DelItem[i]));
380 	   

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

-Advertisement-
Play Games
更多相關文章
  • 本文出處:http://www.cnblogs.com/wy123/p/6217772.html 字元串自身相加, 雖然賦值給了varchar(max)類型的變了,在某些特殊情況下仍然會被“截斷”,這到底是varchar(max)長度的問題還是操作的問題? 1,兩個不超過8000長度的字元串自身相加 ...
  • 隔離級別定義事務操作資源和更新數據的隔離程度,在SQL Server中,隔離級別隻會影響讀操作申請的共用鎖,而不會影響寫操作申請的互斥鎖。隔離級別控制事務在執行讀操作時: 在讀數據時是否使用共用鎖,申請何種類型的隔離級別; 事務持有讀鎖的時間 讀操作引用其他事務更新的數據行時,控制讀操作的行為: 被 ...
  • Linux環境下寫代碼雖然沒有IDE,但通過給vim配置幾個插件也足夠好用。一般常用的插件主要包括幾類,查找文件,查找符號的定義或者聲明(函數,變數等)以及自動補全功能。一般流程都是下載需要的工具,然後在vimrc文件中配置載入工具選項,一直這麼用也沒覺得啥。但最近發現通過vundle工具可以很方便 ...
  • TCP/IP之Nagle演算法與40ms延遲提到了Nagle 演算法。這樣雖然提高了網路吞吐量,但是實時性卻降低了,在一些交互性很強的應用程式來說是不允許的,使用TCP_NODELAY選項可以禁止Nagle 演算法。禁止Nagle後應用程式向內核遞交的每個數據包都會立即發送出去。但是禁止Nagle,網路傳 ...
  • Nagle演算法是針對網路上存在的微小分組可能會在廣域網上造成擁塞而設計的。該演算法要求一個TCP連接上最多只能有一個未被確認的未完成的小分組,在該分組確認到達之前不能發送其他的小分組。同時,TCP收集這些少量的分組,併在確認到來時以一個分組發出去。它的設計規則如下: (1)如果包長度達到最大報文長度( ...
  • 1.1在這之前,我們需要瞭解程式的編譯過程 a.預處理:檢查語法錯誤,展開巨集,包含頭文件等 b.編譯:*.c-->*.S c.彙編:*.S-->*.o d.鏈接:.o +庫文件=*.exe 1.2體驗在VC下程式的編譯 a.先編譯,在鏈接 b.修改了哪個文件,就單獨編譯此文件,在鏈接 c.修改了哪個 ...
  • 既然瞭解了IL的介面和動態類之間的知識,何不使用進來項目實驗一下呢?而第一反應就是想到了平時經常說的IOC容器,在園子里搜索了一下也有這類型的文章http://www.cnblogs.com/kklldog/p/3395641.html,借鑒一下前人的知識就來實現一下吧。IOC的概念就不介紹了,想了 ...
  • 一.前言 許可權驗證在開發中是經常遇到的,通常也是封裝好的模塊,如果我們是使用者,通常指需要一個標記特性或者配置一下就可以完成,但實際裡面還是有許多東西值得我們去探究。有時候我們也會用一些開源的許可權驗證框架,不過能自己實現一遍就更好,自己開發的東西成就感(逼格)會更高一些。進入主題,本篇主要是介紹介面 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...