---
# System prepended metadata

title: 第二周【程式課程】第二章 陣列、迴圈與列舉筆記
tags: [程式課程]

---

# 第二周【程式課程】第二章 陣列、迴圈與列舉筆記
###### tags: `程式課程`

講者：錢鼠Coinmouse

## 隱含型別
```cs
var atk = 100; // 攻擊力整數100
var name = "Hero" ; // 名字"Hero"
var posX = 1.0f; //x座標浮點數1.0
var posy = 1.0; //座標雙浮點數1.0
```
* 編譯時根據賦予的初始值決定變數類型
* 不可在無賦值的情況下宣告
* 不容易辨明變數用途的情況下斟酌使用

## 陣列
### 一維陣列
```csharp!
int[] bulletDmgs = new int[] {30,29,42}// 總共三個子彈傷害(賦值)
var first = bulletDmgs[0]; //第一發傷害(30)
var second = bulletDmgs[1]; // 第二發傷害(29)
var third - bulletDmgs[2]; // 第三發傷害(42)
//預先宣告花色數量(不賦值)
string[] pokerSuits = new string[4];
pokerSuits[0] = "Spade" ; //第一個花色"黑桃

//以下類推
```
* 宣告時賦值會給予賦值數量的陣列長度(Length)
* 陣列的第一個元素從0開始
* 指定取第幾個陣列元素(Element)的數字稱之為素引Index)
* 低於0或大於陣列宣告長度的索引會報錯
### 二維陣列
```csharp!
int[,] grids = new int[, ] (
(1, 2, 3),
(4, 5, 6),
[7, 8, 9,
float[,] reds = new float[1024, 768]
Console.WriteLine (grids[1, 1]); //顯示5 (剛好是正中間元素)
Console.writeLine (grids ,GetLength (0)) ; //顯示3 (橫的數量)
Console.WriteLine (grids.GetLength(1)) ; //顯示3 (縱的數量)

Console.WriteLine (grids . Length) ; //顯示9 (全長3*3)
```
* 可以在宣告時給予指定元素
* 每個子陣列都必須等長
* 使用GetLength(0)、GetLength(1)分别取得[m,n]陣列中的mn
### 三維(較少用，略)

### 不規則陣列
```csharp!
int[][] grids = new int[] []f
new int[](1, 2, 3],
new int[](4, 5, 6],
new int[](7, 8, 9, 10]
Console.WriteLine (grids.Length) ; //子陣列有3個,顯示3
Console.WriteLine (grids[0].Length) ; //第一個子列有3個元素,顯示3
Console.WriteLine (grids [2].Length) ; //第三個子陣列有4個元素.顯示4
```
* 等於是陣列的陣列,每個子陣列長度不一定相同

## 迴圈
```csharp!
int sum = 0;
for (int i = 1; i <= 10; i++) ( //從1~10·每執行一次1就加一
sum += i;
Console.WriteLine (sum) ; //總共55
```
* 格式為for(初始化;執行條件;執行後行為)
```csharp!
int sum(int[,] nums){
int sum = 0;
for (int i = O; i < nums.GetLength(0); i++){
    for (int j= 0; j<nums.GetLength(1) ; j++){
    sum t= nums[i, j];
        }
    }
    return sum;
}
```
* 多個圈的結構我們稱之為巢狀圈(NestedLoop)
* 要努力避免這種情形發生

```csharp!
// infinite loop
int sum = 0;
int i = 1;
for (;;) //for的括內都可以填空
{
    sum += i;
     ++;
}
```
* 任何可能無法終止的圈都可以稱作無窮圈(InfiniteLoop)

```csharp!
// return
int Search(int[] nums, int n){
for (int i = 0; i < nums.Length; i++){
    if(nums[i] == n) 
        return i;
    }
    return -1 ;    
}
//陣列[1,2,3,4,5]中尋找3的index
//在行到=2的時候就會return
```
* return會直接回傳而跳出函式
```csharp!
// break
int Search(int[] nums, int n){
    for (int i = 0; i < nums.Length; i++){
        int index = -1;
        if (nums[i] == n){
            index = i;
            break;
        }
    }
    return index;
}
```
* 只跳離當前迴圈
```csharp!
// continue
int Search(int[] nums, int n){
    int index = -1;
    for (int i = 0; i < nums.Length; i++){
        if (nums[i] != n){
            continue;
        }
        index = i;
    }
    return index;
}
```
* 直接跳下一次迴圈


| 關鍵字   | 定義                                       | 備註 |
| -------- | ------------------------------------------ |:----:|
| return   | 跳出並回傳函式結果                         |      |
| break   | 中止迴圈，繼續執行接下來的程式碼 |      |
| continue   | 跳下一個迴圈，該次迴圈中之後的邏輯不會執行 |      |

```csharp!
//foreach
int Sum(int[] nums){
    int sum = 0;
    foreach(var n in nums){
        sum += n;
    }
    return sum;
}
```
* 不用特地宣告index或判斷條件的語法糖(Syntactic Sugar)
* **不可在foreach內修改圈元素**，會造成錯誤
```csharp!
//while
int i = 0;
int sum = 0;
int[] nums = new int[] ( 1, 2, 3, 4 );
while (i < nums. Length) {
    sum += nums[i];
    i++;
}
```
* 先判斷再執行
```csharp!
int i = 0;
int sum = 0;
int[] nums = new int[] ( 1, 2, 3, 4 );
do {
    sum += nums [i];
    i++;
} while (i < nums.Length);
```
* 先執行再判斷

## 列舉

### 基本用法
```csharp!
enum EBotstate{
    Idle, //閒置
    Warn, //警戒
    Combat, //戰鬥
    Flee //逃跑
}

var state = EBotState. Idle;
```
* 可用相較於int更為直觀的方式表現狀態等參數
* 可用編譯器檢查語法

### 帶入數值
```csharp!
enum EBotstate : int { //宣告列舉的數值類型(僅限整數系列的類型)
    Idle = 0, //可以不賦值,預設從0開始
    Warn, //預設從上一個列舉數值+1
    Combat, //依此類推...
    Flee    
}

var state = EBotstate.Idle;
```
* 可用任意整數類型(byte,short,int, ., e.t.c.)

```csharp!
enum EDebuff : byte {
    None  = 0b00000000,// 十進位為0
    Poison = 0b00000001, // 十進位為1
    Paralysis = 0b00000010, // 十進位為2
    Bleeding = 0b00000100, // 十進位為4
    Cursed = 0b00001000 // 十進位為8
}

EDebuff curDebuff = EDebuff.Poison | EDebuff.Paralysis;
bool HasDebuff(EDebuff current, EDebuff debuff){
    return (current & debuff) != 0;
}
```
* 也可作為一個位元操作的行為
* 在此範例中，這些狀態的數值以二進制為表示
* 當我們角色中了異常狀態的時候，可能不會只有一個，這時我們可以用 `curDebuff` 的寫法作為代表狀態為 Poision 與 Plarlysis 同時存在時的狀況，在案例裡為用或( | ) 計算，最後結果為 0b00000011，加起來為3，並用 HadDebuff 來判斷是否有此 buff 狀態。

## 函式(二)
### 不定長度參數、關鍵字params
```csharp
void printAll(params int[] nums){
    var str = nums[0]. Tostring() ; //將第一個元素先轉為字串
    for (int i = 1; i < nums.Length; i++){
        str += ", " t nums[i]; //之後的數字之前加逗號    
    } //從第二個元素開始
    Console.WriteLine (str);        
}
printAll(new int[](1, 2, 3)); //結果為"1,2,3”
printAll(2, 4, 6, 8, 10); //結果為2,4,6,8,10”
```
* params關鍵字表示宣告不定長度參數,僅限於函式使用,並且要接陣列類型參數
* 可以帶入同樣類型的陣列或元素類型任意數量
* 必須作為函式中的**最後(右邊)一個參數**
* printAll 可以把數值轉成字串，並以一個"數值,數值,"的方式呈現

### 選擇性參數(Optional Parameter)
```csharp!
int Sumseries(int origin, int step, int rise = 1){
    int sum = O;
    for (int i = 0; i < step; i++){
    sum += origin + i * rise;
    }
    return sum;
}
SumSeries(1, 3) ; //1+2+3，rise為1·每次數值增加1
SumSeries (1, 3, 2) ; //1+3+5,rise為2,每次數值增加2
```
* 呼叫時可省略被宣告為選擇性參數,示會自動使用預設的數值
* 選擇性參數必須在其他參數之後

## 備註：第零章小筆記
勞贖(程式)
\<details>
\<summary>我的答案</summary>
csharp
string GiveMeABananaOl
return "Banana";
\</details>
![](https://i.imgur.com/xspF9Zr.png)
這樣寫會有將資訊隱藏起來的效果