---
# System prepended metadata

title: 大一服務學習_程設小天使_CH3共筆

---

## Chapter 3 流程控制

:::info
本章為**邱奕禓**負責，接下來的內容將會利用例子以及綜合應用闡述本章內容。
:::

### 簡介

> 在一個複雜的程式碼中，往往會由**三種結構**所提供的敘述所組合而成

* 循序結構:==由上而下==行執行程式碼。

* 選擇結構:程式執行時，==改變程式執行流程。==

* 重複結構:當程式中某敘述區域需要==執行多次==時使用。

### 選擇結構
> 是人都會有選擇的時候，程式碼也一樣。
:::warning
小明跟他的朋友在玩真心話大冒險，但他在猶豫要選真心話還是大冒險，因為那群損友們出的題目都千奇百怪。
:::

#### if
> 小明說如果他的女朋友在旁邊，他就選真心話。
```csharp!
if (小明的女朋友在旁邊){                    // 如果小明的女朋友在旁邊
    Console.WriteLine("小明選真心話");     // 小明選真心話
}
```
>語法長這樣

```csharp!
if(條件式)
{
    [敘述區段]
}
```

![image alt](https://scontent.xx.fbcdn.net/v/t1.15752-9/419006704_325336047219343_4150591357125187569_n.jpg?stp=dst-jpg_p403x403&_nc_cat=104&ccb=1-7&_nc_sid=5f2048&_nc_ohc=nPDkAavJDYoAX__NtuD&_nc_ad=z-m&_nc_cid=0&_nc_ht=scontent.xx&oh=03_AdSyrBY23serdu2hwkaFYbp61Khj67znL-uoKV_3SQU0jA&oe=6624AB24 =40%x)


#### if...else...
:::info
**else**的作用是假設**if的條件為False**的話，則執行else的敘述區段
:::
> 小明的女朋友在旁邊就選真心話，**反之，選大冒險**。
```csharp!
if (小明的女朋友在旁邊){                   // 如果小明的女朋友在旁邊
    Console.WriteLine("小明選真心話");    // 小明選真心話
}
else{
    Console.WriteLine("小明選大冒險");    // 小明選大冒險
}
```
> 語法長這樣

```csharp!
if (條件式){
    [敘述區段 1]
}
else{
    [敘述區段 2]
}

```
![image alt](https://scontent.frmq2-1.fna.fbcdn.net/v/t1.15752-9/419504129_422634333652249_1852624627412644825_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=5f2048&_nc_ohc=p5HAWH1HxtwAX_DdGH2&_nc_ht=scontent.frmq2-1.fna&oh=03_AdSQhwMfgk_KsojQDJGEY7pURxiaIyt-wh1cyRBwwsUKTg&oe=6626FDC6 =40%x)

#### if...else if...else...
:::info
**else if**的作用在**為程式碼新增一個條件**，假設為True，就會執行else if的敘述區段。
:::
> 小明的女朋友今天要工作，但小明的前女友卻坐在小明旁邊，尷尬的小明**選擇烙跑**。

```csharp!
if (小明的女朋友在旁邊){                     // 如果小明的女朋友在旁邊
    Console.WriteLine("小明選真心話");      // 小明選真心話
}
else if(小明的前女友在旁邊){                // 如果今天是前女友在旁邊 
    Console.WriteLine("小明烙跑");         // 小明選擇烙跑
}
else{
    Console.WriteLine("小明選大冒險");      // 小明選大冒險
}

```
:::warning
* 小明的女朋友在旁邊，他就會選擇真心話。
* 小明的前女友在旁邊，他就會選擇烙跑
* 如果女朋友和前女友都不在，他就會選擇大冒險。
:::
![image alt](https://scontent-tpe1-1.xx.fbcdn.net/v/t1.15752-9/421533214_2910763415746048_126839793039628753_n.jpg?stp=dst-jpg_p403x403&_nc_cat=105&ccb=1-7&_nc_sid=5f2048&_nc_ohc=zO7biuCAV1YAX-R-ktY&_nc_ht=scontent-tpe1-1.xx&oh=03_AdRG6w6A2u0Kij3Jlefm5g7WH65JLw852x4ulXzMfVFGTg&oe=6628B442)

> 語法長這樣
```csharp!
if (條件式){
    [敘述區段 1]
}
else if(條件式){
    [敘述區段 2]
}
else{
    [敘述區段 3]
}

```
> 那如果他的女朋友跟前女友都在呢?
:::success
會選擇**大冒險**，因為**循序結構**的關係，導致雖然他的前女友也在，但是最開始的條件就已經符合了，因此小明還是會選擇大冒險
:::
#### 巢狀選擇
:::info
巢狀選擇就像**俄羅斯娃娃**一樣，一套包著一套。
:::
> 假設小明中真心話以後，被問說甚麼時候要跟前女友復合，坐在旁邊的女朋友會站起來搧他一巴掌，否則小明都會誠實地回答問題。
```csharp!
if (小明的女朋友在旁邊){                                // 如果小明的女朋友在旁邊
    if (被問甚麼時候要跟前女友復合){                     // 被問甚麼時候復合
        Console.WriteLine("女朋友站起來搧他一巴掌");    // 女朋友站起來搧他巴掌 
    }
    else{
        Console.WriteLine("小明誠實地回答問題");       // 小明誠實回答問題
    }
}
else{
    Console.WriteLine("小明選大冒險");                // 小明選大冒險
}

```
![419051698_1422894498595676_6733760388002535773_n](https://hackmd.io/_uploads/rJny7tZkR.jpg )
:::warning
請注意!巢狀選擇要在**通過判斷式的條件才會執行內部**的選擇條件。就如同今天晚餐選擇去牛排館，到牛排館後才會選擇要吃牛排還是雞排一樣。因此，與其說巢狀迴圈是一種用法，不如說它是一種**概念**。
:::
#### switch
> 假設今天小明突然提議玩擲骰子的遊戲，遊戲規則如下:如果骰到**1,3點**，就**喝1杯酒**;如果骰到**2,4點**，就**喝2杯酒**;如果骰到**6點**，就**不用喝酒**。
* 假如說利用if...else...程式碼會長這樣。
```csharp!
int i = 0
if (i==1 || i==3){
    Console.WriteLine("喝1杯酒");
}
else if (i==2 || i==4){
    Console.WriteLine("喝2杯酒");
}
else{
    Console.WriteLine("不用喝酒");
}

```
* 假如說利用switch程式碼會長這樣。

```csharp!
int i = 0
switch(i)
{
    case 1:
    case 3:
        Console.WriteLine("喝一杯酒");
        break;
    case 2:
    case 4:
        Console.WriteLine("喝兩杯酒");
        break;
    default:
        Console.WriteLine("不用喝酒");
        break;
}
Console.Read();
```
:::success
是不是感覺switch有種更簡單易懂的感覺呢?
:::

> 語法長這樣
```csharp!
switch (運算式或變數)
{
    case value1:
        [敘述區段 1]
        break;
    case value 2:
        [敘述區段 2]
        break;
    default:
        [敘述區段 default]
        break;
}
Console.Read();
```
### 補充:三元運算子

:::info
如同**if...else語法**一樣，但用**一行**就可以表示出來!!!

:::
> 普通的if...else...語法
```csharp!
if (條件式){
    [敘述區段 1]
}
else{
    [敘述區段 2]
}
```
>三元運算子
```csharp!
variable = (condition) ? expressionTrue :  expressionFalse;
```
> 如果利用if...else...範例式子，三元運算子就會長這樣:

```csharp!
小明 = 女朋友是否在旁邊 ? 選真心話 : 選大冒險;
```
:::info
就如同if...else...語法一樣，假如設**一條件為真**，就會**執行冒號左邊那行式子**。反之，則執行右邊那行式子。
:::
### 重複結構
> 如果需要**重複做某一件事情**的時候，就會使用重複結構。
:::warning
小明在玩真心話大冒險的過程中不斷喝下了好幾杯酒，一杯，兩杯，三杯...
:::

#### for迴圈
:::success
for迴圈是甚麼?
> 在**有區間限制**的情況下重複某件事情
:::
> 小明知道自己喝超過十杯就會做出脫序的行為，因此打算喝到第十杯就不再喝了。

```csharp!
for (int i=1 ; i<=10 ; i++){
    Console.WriteLine($"小明喝了第{i}杯酒");
}
Console.WriteLine($"不喝了不喝了!");
```
![image](https://hackmd.io/_uploads/rkemD-Wl0.png)

> 語法長這樣
```csharp!
for (初值 ; 條件式 ; 增值){
    [敘述區段]
    [break/continue;]            // 之後會講到
}
```

#### 巢狀迴圈
:::info
大腸包小腸，先剪開**大腸(i迴圈)**，再**包裡面的料(j迴圈)**。

那如果我今天要做==三個==大腸包小腸呢?
```csharp!
for (int i = 1; i <=3; i++) 
  {
      Console.WriteLine($"第{i}根大腸包小腸");
      Console.WriteLine($"米腸" );  

      for (int j = 1; j <= 1; j++) 
      {
          Console.WriteLine($"	香腸" );
          Console.WriteLine($"	蒜頭" );
          Console.WriteLine($"	香菜" ); 
          Console.WriteLine($"	小黃瓜" ); 
          Console.WriteLine($"	酸菜" ); 
      }
  }
```
:::
![image](https://hackmd.io/_uploads/ryJ7FWbl0.png)

![419123894_1097886854662808_5557959626480869041_n](https://hackmd.io/_uploads/SkebSJbxR.jpg)

> 只見小明越喝越多，眼看快要失控了!!!趁著醉酒之意，小明與女朋友決定比賽酒量，假設女朋友每喝一杯酒，他就相對地得要喝三杯!
```csharp!
// Outer loop
for (int i = 1; i <=3; i++) 
{
Console.WriteLine($"女朋友喝第{i}瓶酒:" );  

    // Inner loop
    for (int j = 1; j <= 3; j++) 
    {
      Console.WriteLine($"小明喝第{j}瓶酒" ); 
    }
}
```
![image](https://hackmd.io/_uploads/Bkr4lkbg0.png)

> 如果將兩種迴圈分開來會更好理解喔!
#### while
:::success
while迴圈是甚麼?
>**無區間限制**地重複某件事情，除非有人制止你。
:::


>完蛋了!小明走火入魔了!他甚至誇下海口說:「我要喝光全世界的酒!」，說罷，就開始毫無節制地喝起酒來!
:::warning
現在能阻止他的只有兩種辦法:
* 在while函式新增一個條件式。
* 使用break強制打斷。(後面的內容會講)
:::

> 小明雖然嘴上這樣說，但他的身體機能告訴他，喝到第十五杯的時候就會斷片。

```csharp!
int i = 1;
while(i<=15){
    Console.WriteLine($"小明喝了第{i}杯");
    i++;
}
Console.WriteLine($"啊...斷片了");
```
![螢幕擷取畫面 2024-04-08 125221](https://hackmd.io/_uploads/Byg8OlbxC.png)



> 語法長這樣
```csharp!
while (條件式){
    敘述區段;
}
```

#### break & continue
##### **break**
---
:::danger
如果今天while語句**沒有條件式**會變成甚麼樣?
> 小明解除了身體限制!!!全宇宙的酒都被喝光光。~~他喝完了我們喝甚麼!~~
:::
:+1: 因此需要利用==break==來阻止噩耗發生!
> 女朋友看到小明如此脫序的模樣，再也忍無可忍，放下狠話說如果小明敢喝超過20杯酒，她就要跟他分手!

```csharp!
int i = 1;
while (true){
    Console.WriteLine($"小明喝了第{i}杯");
    i++;
    if (i<=50){
        break;
    }
}
Console.WriteLine($"不敢喝了!再喝就要分手了!");
```
![螢幕擷取畫面 2024-04-08 143510](https://hackmd.io/_uploads/By8EefblR.png)

##### **continue**

---
:::info
**continue**就像==跳過==一樣，直接跳過continue以下的程式碼。
:::
> 小明的身體機制很奇怪，每喝五杯酒就會不由自主地跳起舞來。

```csharp!
int i = 1;
while (true){
    Console.WriteLine($"小明喝了第{i}杯");
    i++;
    if (i % 5 == 0 ){
        Console.WriteLine($"小明開始跳舞了!!!");
        continue;
    }
    		
}

```
![image](https://hackmd.io/_uploads/SyQjCGbeR.png)



#### do...while...
> 先做do裡面的敘述區段，如果while的條件成立，就再做一次do的敘述區段!
:::warning
與while語句不同(while需要條件達到才會執行迴圈裡面的內容)
* do...while...會先將敘述區段做一次，才會去看while的條件是否有達到:
    - 假如while條列式成立，則==再做一次do裡面的內容==
    - 反之，則結束此段程式碼。
:::
> 語法長這樣
```csharp!
do{
    [敘述區段]
}
while (條件)
```

### 綜合演練
:::info
吃飽喝足的小明一行人，再準備結帳的時候才發現!完蛋!剛剛喝得太開心早就忘記自己點過那些酒了，這樣完全不知道自己喝了多少錢啊!正當他們不知所措之際，店長笑到:「早就知道你們想透過喝一大堆酒來逃避酒錢了!」，我早就利用你們在happy的時候，做出了一個可以精確算出酒錢的程式碼來了!!!
:::
> 老闆到底是怎麼結合上面的概念作出酒錢程式呢?
```csharp!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 酒店老闆做的程式碼
{
    class Program
    {
        static void Main(string[] args)
        {
            int sum = 0;
            string wine;

            do
            {
                Console.Write("請輸入喝酒的品項(直接按\"Enter\"結束輸入):");
                wine = Console.ReadLine();
                if (wine != "")
                {
                    Console.Write("請輸入此酒的價格:");
                    int price = Convert.ToInt32(Console.ReadLine());
                    sum += price;
                }
            }
            while (wine != "");
            Console.WriteLine($"以上的酒總價為{sum}元");
            Console.WriteLine("輸入任意鍵以退出視窗...");
            Console.ReadKey();
        }
    }
}

```
![image](https://hackmd.io/_uploads/H1Xp84-lC.png)
> 在結束結帳的問題之後，小明一夥人開心的從酒吧走了出去。

:::success
我認為上面的程式碼還有很多可以改進的空間，像是每次都要輸入酒的品項實在很累，因此期望將來能做一個更加方便與便捷的程式碼!
:::
:+1: 如果有任何問題歡迎詢問
> s112213017@mail1.ncnu.edu.tw **邱奕禓**