【唐老獅】Unity系列之C#四部曲—C#基礎(chǔ)

復(fù)雜數(shù)據(jù)類型(枚舉、數(shù)組、結(jié)構(gòu)體)
值和引用的區(qū)別
函數(shù)相關(guān)
排序初探
----------------------------------------------------------
復(fù)雜數(shù)據(jù)類型概述
- 枚舉:整形常量的集合,可以自定義
- 數(shù)組:任意變量類型順序存儲(chǔ)的數(shù)據(jù)
- 結(jié)構(gòu)體:任意變量的數(shù)據(jù)集合,可以自定義
----------------------------------------------------------
枚舉
枚舉:被命名的整形常量的集合
- 申明枚舉:創(chuàng)建一個(gè)自定義的枚舉類型
- 申明枚舉變量:使用申明的自定義枚舉類型,創(chuàng)建一個(gè)枚舉變量
申明枚舉語(yǔ)法:以E或者E_開頭
格式:
enum E_自定義枚舉名
{
自定義枚舉項(xiàng)名字,// 默認(rèn)值是0
自定義枚舉項(xiàng)名字,// 變成1
}
示例:
enum E_PlayerType
{
Main,// 默認(rèn)值是0
Other,// 自動(dòng)變成1
Other1 = 100, // 變成100
Other2 = // 自動(dòng)變成101
}
--------------------
- 在namespace語(yǔ)句塊中申明
- 也可以在class語(yǔ)句塊中和結(jié)構(gòu)體中
- 但不能在函數(shù)語(yǔ)句塊中申明,包括循環(huán)和分支語(yǔ)句中
--------------------
申明枚舉變量:
E_PlayerType playerType = E_PlayerType.Main;
配合【貫穿】使用
--------------------
- 枚舉和int互轉(zhuǎn):強(qiáng)制類型轉(zhuǎn)換
int i = (int)playerType;
- 枚舉和string相互轉(zhuǎn)換:
string str = playerType.ToString() ;// 將名字轉(zhuǎn)換成string
格式: (強(qiáng)制轉(zhuǎn)換類型)Enum.Parse(typeof(轉(zhuǎn)換的類型), 用于轉(zhuǎn)換的對(duì)應(yīng)的枚舉項(xiàng))
備注:轉(zhuǎn)換完畢后,是一個(gè)通用類型,我們需要用括號(hào)強(qiáng)轉(zhuǎn)成我們想要的目標(biāo)枚舉類型
playerType = (E_PlayerType)Enum.Parse(typeof(E_PlayerType), 'Other') ;
--------------------
在游戲開發(fā)中,對(duì)象很多時(shí)候有很多狀態(tài)
枚舉可以幫我們分清狀態(tài)的含義
----------------------------------------------------------
一維數(shù)組
儲(chǔ)存相同類型數(shù)據(jù)的集合,一維數(shù)組簡(jiǎn)稱為數(shù)組
- 1.變量類型[] 數(shù)組名;
只是申明,沒(méi)有初始化
變量類型:int 等 c#規(guī)定的變量類型
- 2.變量類型[] 數(shù)組名 = new 變量類型[數(shù)組的長(zhǎng)度];
規(guī)定數(shù)組的長(zhǎng)度,但沒(méi)有指定數(shù)組內(nèi)容
默認(rèn)值是0,示例:int[] arr2 = new int[5];
- 3.變量類型[] 數(shù)組名 = new 變量類型[數(shù)組的長(zhǎng)度]{內(nèi)容1,內(nèi)容2,..};
指定數(shù)組內(nèi)容
示例:int[] arr2 = new int[5]{1,2,3,4,5};
- 4.變量類型[] 數(shù)組名 = new 變量類型[]{內(nèi)容1,內(nèi)容2,..};
不寫長(zhǎng)度,只寫內(nèi)容,內(nèi)容長(zhǎng)度決定數(shù)組長(zhǎng)度
- 5.變量類型[] 數(shù)組名 = {內(nèi)容1,內(nèi)容2,..};
與上面同理
注意:申明的數(shù)組是什么類型,后面內(nèi)容必須是相同數(shù)據(jù)類型的數(shù)據(jù)
- 數(shù)組長(zhǎng)度:數(shù)組名. Length
- 獲取數(shù)組中的元素:索引從0開始,數(shù)組名[索引]
- 修改數(shù)組中的元素:array[0] = 99
- 遍歷元素:for (int i = 0; i < array.Length; i++){}
- 增加數(shù)組元素:數(shù)組初始化后,不能直接添加新的元素;只能拷貝到一個(gè)更大的數(shù)組中,然后將新數(shù)組的地址賦值給原數(shù)組
- 同理,也不能刪除元素
- 查找數(shù)組中的元素:遍歷依次查找
用來(lái)批量?jī)?chǔ)存游戲中的同一類型的對(duì)象的容器,比如所有怪物
----------------------------------------------------------
二維數(shù)組
兩個(gè)下標(biāo)來(lái)確定元素的數(shù)組,在內(nèi)存中以【行優(yōu)先】方式存儲(chǔ)
- 變量類型[ , ] 變量名;
- 變量類型[ , ] 變量名 = new 變量類型 [行數(shù),列數(shù)];
- 變量類型[ , ] 變量名 = new 變量類型 [行數(shù),列數(shù)]{ {0行內(nèi)容}, {1行內(nèi)容}};
- 變量類型[ , ] 變量名 = new 變量類型 [,] {{0行內(nèi)容}, {1行內(nèi)容}};
- 變量類型[ , ] 變量名 = {{0行內(nèi)容}, {1行內(nèi)容}};
- 數(shù)組名.GetLength(0); 行數(shù)
- 數(shù)組名.GetLength(1); 列數(shù)
- 元素:array[0, 1]
----------------------------------------------------------
交錯(cuò)數(shù)組
數(shù)組的數(shù)組,每個(gè)維度的數(shù)量可以不同
每個(gè)行儲(chǔ)存一個(gè)一維數(shù)組
--------------------
int[][] arr;
int[][] arr = new int[行數(shù)][];
int[][] arr = new int[行數(shù)][]{ new int[] {1, 2, 3},
new int[] {1, 2},
new int[] {1}, };
int[][] arr = new int[][]{ ... };
int[][] arr = { ... };
--------------------
- 數(shù)組名.GetLength(0); 行數(shù)
- 數(shù)組名[ 某個(gè)行號(hào) ].Length;
- 元素:array[0][1] 對(duì)比二維數(shù)組,不是array[0, 1]
----------------------------------------------------------
值類型和引用類型
變量類型:
- 無(wú)符號(hào)整形:byte,ushort,uint,ulong
- 有符號(hào)整型: sbyte,short,int,long
- 浮點(diǎn)數(shù): float,double,decimal
- 特殊類型:char,string,bool
- 復(fù)雜類型:enum,數(shù)組
引用類型:string、數(shù)組、類
值類型:其他,結(jié)構(gòu)體
--------------------
int a = 10;
int[] arr = new int[]{ 1,2,3,4}
int b = a;
int[] arr2 = arr;
值類型在相互賦值時(shí),把內(nèi)容拷貝給了對(duì)方,它變我不變
引用類型的相互賦值,是讓兩者指向同一個(gè)內(nèi)存空間,它變我也變
值類型 和 引用類型 存儲(chǔ)在內(nèi)存區(qū)域 是不同的,存儲(chǔ)方式是不同的
值類型存儲(chǔ)在棧空間(系統(tǒng)分配的空間,自動(dòng)回收,小而快)
引用類型存儲(chǔ)在堆空間(手動(dòng)申請(qǐng)和釋放,大而慢)
引用類型儲(chǔ)存【在棧中】?jī)?chǔ)存的只是一個(gè)【指向堆中】的地址
--------------------
int[] arr = new int[]{ 1,2,3,4};
int[] arr2 = arr1;
arr2 = new int[] {99,2,3,4};
arr2在地址中開辟新的空間,與arr1沒(méi)有關(guān)系了
----------------------------------------------------------
特殊引用類型string
string str1 = '123';
string str2 = str1;
str2 = "321" // 但str1不會(huì)變,c#對(duì)string進(jìn)行了特殊處理
重新賦值時(shí),會(huì)在堆中重新分配一個(gè)空間
但頻繁重新賦值會(huì)產(chǎn)生內(nèi)存垃圾
--------------------
通過(guò)斷點(diǎn)調(diào)試 在監(jiān)視窗口中查看 內(nèi)存信息
----------------------------------------------------------
函數(shù)基礎(chǔ)
本質(zhì):具有名稱的代碼塊
作用:抽象行為
選中函數(shù),f11轉(zhuǎn)到函數(shù)內(nèi)部
--------------------
class語(yǔ)句塊/struct語(yǔ)句塊中
--------------------
static 返回類型 函數(shù)名 (參數(shù)類型 參數(shù)名1,參數(shù)類型 參數(shù)名2,...,)
{
函數(shù)語(yǔ)句塊
return 返回值;// 如果函數(shù)開頭有返回類型時(shí)才返回
}
注意事項(xiàng):
- static不是必須的
- 返回類型是 void 時(shí),表示函數(shù)沒(méi)有返回值
- 返回類型可以寫任意變量類型
- 函數(shù)命名用帕斯卡命名法命名
- 參數(shù)不是必須的,參數(shù)類型可以是任意類型
- 返回值不是void時(shí),必須通過(guò)return返回對(duì)應(yīng)類型內(nèi)容
--------------------
函數(shù)返回值只能是一個(gè)數(shù)據(jù)類型,只能是一個(gè)內(nèi)容
--------------------
即使沒(méi)有返回值,也可以使用return來(lái)終止函數(shù)運(yùn)行
----------------------------------------------------------
ref和out
在函數(shù)內(nèi)部改變外部傳入的內(nèi)容,里面變了,外面也要變
值類型和引用類型作為參數(shù)的傳參過(guò)程
如果函數(shù)接收一個(gè)數(shù)組,并在函數(shù)內(nèi)部對(duì)接受的數(shù)組重新賦予了一個(gè)新的數(shù)組地址,那么這種改變是無(wú)法施加到傳入的數(shù)組上的。
--------------------
目標(biāo):當(dāng)傳入的值類型參數(shù)在內(nèi)部修改時(shí),或者引用類型參數(shù)在內(nèi)部重新申明時(shí),外部值會(huì)發(fā)生相應(yīng)的變化(變化能傳遞出函數(shù))
ref/out:綁定這些參數(shù)在棧中的地址
--------------------
ref傳入的變量必須初始化,但out不用
out傳入的變量必須在內(nèi)部賦值,ref不用
// ref傳入的變量必須初始化,在內(nèi)部可改可不該
// out傳入的變量不用初始化,在內(nèi)部,必須修改該值
----------------------------------------------------------
變長(zhǎng)參數(shù)和參數(shù)默認(rèn)值
--------------------
關(guān)鍵字:params
static int Sum(params int[] arr){}
注意點(diǎn):
- params關(guān)鍵字后面必為數(shù)組
- 數(shù)組類型可以是任意類型
- 函數(shù)參數(shù)可以有別的參數(shù)和params關(guān)鍵字修飾的參數(shù)
- 函數(shù)參數(shù)中只能最多出現(xiàn)一個(gè)params關(guān)鍵字,并且一定是在最后一組參數(shù),前面可以有n個(gè)其他參數(shù)
--------------------
有參數(shù)默認(rèn)值的參數(shù)被稱為可選參數(shù)
作用是當(dāng)調(diào)用函數(shù)時(shí)可以不傳入?yún)?shù),不傳就會(huì)使用默認(rèn)值作為參數(shù)的值
注意點(diǎn):
- 支持多參數(shù)默認(rèn)值,每個(gè)參數(shù)都可以有默認(rèn)值
- 如果要混用可選參數(shù),必須寫在普通參數(shù)后面
----------------------------------------------------------
函數(shù)重載
同一語(yǔ)句塊中(class 或 struct)函數(shù)名相同,參數(shù)的數(shù)量不同
或者:參數(shù)的數(shù)量相同,但參數(shù)的類型或者順序不同
作用:命名一組功能相似的函數(shù),減少函數(shù)名的數(shù)量,避免命名空間的污染
--------------------
注意點(diǎn):
- 重載和返回值類型無(wú)關(guān),之和參數(shù)類型、個(gè)數(shù)、順序有關(guān)
- 調(diào)用時(shí),程序會(huì)自己根據(jù)傳入的參數(shù)類型判斷使用哪一個(gè)重載
ref和out可以看作新的參數(shù)類型
但ref和out不能同時(shí)修飾
----------------------------------------------------------
遞歸函數(shù)
讓函數(shù)自己調(diào)用自己
正確的遞歸函數(shù):
- 終止條件,且確保終止條件可以被觸發(fā)
- 遞歸代碼
static void Fun(int a){ //打印從0到10
Console.WriteLine(a);
if(a == 10){ return }
Fun(a+1);
}
----------------------------------------------------------
結(jié)構(gòu)體
- 自定義變量類型,類似枚舉需要自己定義
- 是數(shù)據(jù)和函數(shù)的集合
- 在結(jié)構(gòu)體中,可以申明各種變量和方法
- 用來(lái)表現(xiàn)存在關(guān)系的數(shù)據(jù)集集合
--------------------
- 一般寫在namespace語(yǔ)句塊中
- 關(guān)鍵字:struct
struct 自定義結(jié)構(gòu)體名
{
// 第一部分:變量
//第二部分:構(gòu)造函數(shù)(可選)
//第三部分:函數(shù)
}
注意點(diǎn):結(jié)構(gòu)體名字用帕斯卡命名法
--------------------
變量:這個(gè)數(shù)據(jù)結(jié)構(gòu)的屬性
- 結(jié)構(gòu)體申明的變量,不能直接初始化
- 變量類型可以寫任意類型,包括結(jié)構(gòu)體,但不能申明和自己一樣的結(jié)構(gòu)體對(duì)象
函數(shù)方法:表現(xiàn)這個(gè)數(shù)據(jù)結(jié)構(gòu)的行為
- 在結(jié)構(gòu)體中的方法,目前不需要加static關(guān)鍵字
- 在函數(shù)中,可以直接使用結(jié)構(gòu)體內(nèi)部申明的變量
--------------------
--------------------
修飾結(jié)構(gòu)體中的變量和方法,是否能被外部使用
- public:公共的,可以被外部訪問(wèn),被修改,外部調(diào)用形式:【結(jié)構(gòu)體實(shí)例.變量 = value】
- private:私有的,默認(rèn)類型,只能在定義結(jié)構(gòu)體的代碼內(nèi)部被調(diào)用
--------------------
概念:
- 沒(méi)有返回值
- 函數(shù)名必須和結(jié)構(gòu)體名相同
- 必須有參數(shù)
- 如果申明了構(gòu)造函數(shù),那么必須在其中對(duì)所有變量數(shù)據(jù)初始化
相當(dāng)于python的self關(guān)鍵字,用以區(qū)分是否是本結(jié)構(gòu)體的變量或函數(shù)
每個(gè)結(jié)構(gòu)體默認(rèn)自帶一個(gè)沒(méi)有任何參數(shù)的構(gòu)造函數(shù);
手動(dòng)寫構(gòu)造函數(shù)并加入?yún)?shù)時(shí),相當(dāng)于重載構(gòu)造函數(shù);
--------------------
概念:變量和函數(shù)的集合,用來(lái)表示特定的數(shù)據(jù)集合
訪問(wèn)修飾符:public和private
構(gòu)造函數(shù):初始化結(jié)構(gòu)體對(duì)象
this修飾符:區(qū)分所屬關(guān)系
注意:
- 結(jié)構(gòu)體中申明的變量不能初始化,只能在外部或函數(shù)中初始化
- 在結(jié)構(gòu)體中申明的函數(shù)不用加static
----------------------------------------------------------
冒泡排序
兩兩相鄰,不停比較,不停交換,比較n輪。
冒泡排序是一種簡(jiǎn)單的排序算法,它重復(fù)地遍歷待排序的序列,一次比較兩個(gè)元素,如果它們的順序錯(cuò)誤就交換過(guò)來(lái)。遍歷所有元素的過(guò)程會(huì)重復(fù)進(jìn)行,直到?jīng)]有再需要交換,也就是該序列已經(jīng)排序完成。冒泡排序的名稱來(lái)自于較大的元素會(huì)經(jīng)由交換慢慢“浮”到數(shù)列的頂端,就像泡泡一樣。
public void BubbleSort(int[] arr)
{
??int n = arr.Length;
??for (int i = 0; i < n - 1; i++)
??{
????for (int j = 0; j < n - i - 1; j++)
????{
??????if (arr[j] > arr[j + 1])
??????{// Swap arr[j] and arr[j + 1]
????????int temp = arr[j];
????????arr[j] = arr[j + 1];
????????arr[j + 1] = temp;
??????}
????}
??}
}
如果遍歷過(guò)程發(fā)現(xiàn)一次交換都沒(méi)有進(jìn)行過(guò),那么程序就可以提前結(jié)束了
public void BubbleSort(int[] arr)
{
??int n = arr.Length;
bool isSort = false;
??for (int i = 0; i < n - 1; i++)
??{
????for (int j = 0; j < n - i - 1; j++)
????{
??????if (arr[j] > arr[j + 1])
??????{// Swap arr[j] and arr[j + 1]
????????int temp = arr[j];
????????arr[j] = arr[j + 1];
????????arr[j + 1] = temp;
??????}
if(!isSort){
break;
}
????}
??}
}
--------------------
選擇排序