練習 - 使用 if 陳述式

已完成

最廣泛使用的分支陳述式是 if 陳述式。 if 陳述式依賴用一組括弧括住的布林運算式。 如果運算式為 True,則會執行陳述式 if 之後的程式碼。 如果運算式為 False,則會略過陳述式 if 之後的程式碼。

使用 if 陳述式建立亂數遊戲

現在我們將開發一個遊戲,以協助我們撰寫 if 陳述式。 我們會為制訂幾條遊戲規則,然後以程式碼來實作。

會使用 Random.Next() 方法來模擬骰出三顆 6 面骰。 我們將評估值來計算分數。 如果點數大於任意總計值,則向使用者顯示獲勝訊息。 否則,將向使用者顯示失敗訊息。

  • 如果您擲出的任兩個骰子產生相同的值,即會因為擲出兩倍而得到兩點獎勵。
  • 如果您擲出的三顆骰子全都產生相同的值,則會因為擲出三倍而得到六點獎勵。
  • 如果這三顆骰子擲出的總和加上任何獎勵點數為 15 或以上,您就贏得此遊戲。 否則,您就輸了。

我們將在深入了解 if 陳述式時增加規則數目。

重要

將會大量使用到 System.Random 類別,我們已在使用 C# 從 .NET Class Library 呼叫方法課程模組中討論過此類別。 如果需要複習 Random.Next() 的運作方式,請參閱該課程模組。

步驟 1 - 撰寫程式碼以產生三個亂數,並在輸出中顯示這些亂數

在 .NET 編輯器中,將程式碼反白並選取鍵盤上的退格鍵來刪除所有先前步驟中的程式碼。 然後,在下列程式碼片段中選取 [執行],以在 .NET 編輯器中執行程式碼:

Random dice = new Random();

int roll1 = dice.Next(1, 7);
int roll2 = dice.Next(1, 7);
int roll3 = dice.Next(1, 7);

int total = roll1 + roll2 + roll3;

Console.WriteLine($"Dice roll: {roll1} + {roll2} + {roll3} = {total}");

我們會建立 System.Random 類別的新執行個體,並在 dice 變數中儲存該物件的參考。 然後,在 dice 物件上呼叫 Random.Next() 方法三次,並同時提供下限和上限來限制 16 之間的可能值。 我們會將這三個亂數分別儲存於變數 roll1roll2roll3 中。

接下來,加總這三顆骰子的擲出點數,並將值儲存在 total 變數中。

最後,使用字串插補來顯示所有值。

當您執行程式碼時,應會看到下列訊息 (數字為隨機產生,因此會有所不同):

Dice roll: 4 + 5 + 2 = 11

步驟 1 是設定步驟。 現在可在程式碼中加入決策邏輯,讓此遊戲變得更有趣。

步驟 2 - 加入 if 陳述式,根據 total 變數的值顯示不同的訊息

修改先前步驟的程式碼,納入 if 陳述式:

Random dice = new Random();

int roll1 = dice.Next(1, 7);
int roll2 = dice.Next(1, 7);
int roll3 = dice.Next(1, 7);

int total = roll1 + roll2 + roll3;

Console.WriteLine($"Dice roll: {roll1} + {roll2} + {roll3} = {total}");

if (total > 14)
{
    Console.WriteLine("You win!");
}

if (total < 15)
{
    Console.WriteLine("Sorry, you lose.");
}

我們加入了兩個 if 陳述式來處理輸贏案例。 讓我們將焦點放在第一個 if 陳述式。

if 陳述式由三個部分組成:

  • if 關鍵字。
  • 位於括弧 () 之間的布林運算式。
  • 以大括弧 { } 定義的程式碼區塊。

系統會在執行階段評估布林運算式 total > 14。 若此運算式為 True (如果 total 的值大於 14),執行流程將繼續執行程式碼區塊中所定義的程式碼。 換句話說,它將執行大括弧中的程式碼。

不過若布林運算式為 False,執行流程將略過此程式碼區塊。 換句話說,它將不會執行大括弧中的程式碼。

最後,若使用者輸了,第二個 if 陳述式就會控制訊息。 在下一個單元中,我們將在 if 陳述式上使用變化,來將這兩個陳述式縮短成單一陳述式,更清楚地表達我們的意圖。

什麼是布林運算式?

布林運算式是任何會傳回布林值 (truefalse) 的程式碼。 最簡單的布林運算式是值 truefalse。 或者,布林運算式可以是會傳回值 truefalse 的方法的結果。 舉例來說,以下是一個簡單的程式碼範例,此範例使用 string.Contains() 方法來評估某個字串是否包含另一個字串:

string message = "The quick brown fox jumps over the lazy dog.";
bool result = message.Contains("dog");
Console.WriteLine(result);

if (message.Contains("fox"))
{
    Console.WriteLine("What does the fox say?");
}

因為 message.Contains("fox") 會傳回 truefalse 值,所以符合布林運算式的條件,而且可在 if 陳述式中使用。

您可以使用運算子來建立其他簡單的布林運算式,以比較兩個值。 運算子包括:

  • ==,用來測試是否相等的「等號比較」運算子。
  • >,用來測試左邊值是否大於右邊值的「大於」運算子。
  • <,用來測試左邊值是否小於右邊值的「小於」運算子。
  • >=,「大於或等於」運算子。
  • <=,「小於或等於」運算子。
  • 依此類推

注意

我們將在整個課程模組專門討論布林運算式。 可以選用許多運算子來建立布林運算式,而這邊只會討論一些基本的運算子。 如需詳細資訊,請參閱在 C# 中評估布林運算式以進行決策課程模組。

在我們的範例中,我們已評估過 total > 14 布林運算式。 不過其實也可以選擇 total >= 15 布林運算式,因為在此案例中是相同的。 假設遊戲規則指定「如果這兩顆骰子的點數加上任何獎勵點數為 15 或以上,您就贏得遊戲」,那麼,我們可能偏好後者。 我們將在此練習的下一個步驟中進行該變更。

什麼是程式碼區塊?

程式碼區塊是一或多行程式碼的集合,以左和右大括弧符號 { } 來定義。 它代表在我們的軟體系統中具有單一用途的程式碼完整單位。 在此案例中,若布林運算式為 True,即會在執行階段執行程式碼區塊中的所有程式碼。 反之,若布林運算式為 False,則會忽略程式碼區塊中的所有程式碼。

C# 中有許多層級的程式碼區塊。 事實上,.NET 編輯器會隱藏在定義方法的程式碼區塊內執行程式碼的事實。 開始使用 Visual Studio Code 或 Visual Studio IDE 來撰寫 C# 程式碼時,會對這種結構更為敏銳。

程式碼區塊可以包含其他程式碼區塊。 我們將在此課程模組稍後示範該情況,因為我們會在一個 if 陳述式內巢狀處理另一個。

注意

我們會在整個課程模組專門討論程式碼區塊。 程式碼區塊是了解程式碼組織和結構的核心,可以定義變數範圍的界限。 如需詳細資訊,請參閱在 C# 中使用程式碼區塊控制變數範圍和邏輯課程模組。

步驟 3 - 加入另一個 if 陳述式來實作雙倍獎勵

接下來要實作新規則:「如果您擲出的任兩個骰子產生相同的值,即會因為擲出雙倍而得到兩點獎勵」。 修改先前步驟的程式碼,以符合下列程式碼清單:

Random dice = new Random();

int roll1 = dice.Next(1, 7);
int roll2 = dice.Next(1, 7);
int roll3 = dice.Next(1, 7);

int total = roll1 + roll2 + roll3;

Console.WriteLine($"Dice roll: {roll1} + {roll2} + {roll3} = {total}");

if ((roll1 == roll2) || (roll2 == roll3) || (roll1 == roll3))
{
    Console.WriteLine("You rolled doubles! +2 bonus to total!");
    total += 2;
}

if (total >= 15)
{
    Console.WriteLine("You win!");
}

if (total < 15)
{
    Console.WriteLine("Sorry, you lose.");
}

在這裡會結合三個布林運算式,在單行程式碼中建立一個大型布林運算式。 這種程式碼有時稱為「複合條件」。 我們有一組外部括弧,其中會結合三組以兩個直立線符號字元分隔的內部括弧。

雙直立線符號字元 ||邏輯 OR 運算子,基本上表示「左邊運算式或右邊運算式必須為 True,才能讓整個布林運算式為 True」。 如果這兩個布林運算式都為 False,整個布林運算式都會是 False。 我們使用兩個邏輯 OR 運算子,如此便能將評估擴充至第三個布林運算式。

首先,評估 (roll1 == roll2)。 若為 True,整個運算式為 True。 若為 False,就會評估 (roll2 == roll3)。 若為 True,整個運算式為 True。 若為 False,就會評估 (roll1 == roll3)。 若為 True,整個運算式為 True。 如果三者皆為 False,則整個運算式為 False。

若此複合布林運算式為 True,我們會執行下面的程式碼區塊。 這次有兩行程式碼。 第一行程式碼會向使用者列印訊息。 第二行程式碼則會依 2 遞增 total 的值。

最後也變更了檢查,以查看使用者是否成功使用 >= 運算子。 這與我們一開始所建立的需求更為相似,但運作方式應會與先前撰寫的相同。

if (total >= 15)

步驟 4 - 加入另一個 if 陳述式來實作三倍獎勵

接下來要新增另一個規則:「如果您擲出的三個骰子全都產生相同的值,則會因為擲出三骰同點而得到六點獎勵」。修改先前步驟的程式碼,以符合下列程式碼清單:

Random dice = new Random();

int roll1 = dice.Next(1, 7);
int roll2 = dice.Next(1, 7);
int roll3 = dice.Next(1, 7);

int total = roll1 + roll2 + roll3;

Console.WriteLine($"Dice roll: {roll1} + {roll2} + {roll3} = {total}");

if ((roll1 == roll2) || (roll2 == roll3) || (roll1 == roll3))
{
    Console.WriteLine("You rolled doubles! +2 bonus to total!");
    total += 2;
}

if ((roll1 == roll2) && (roll2 == roll3)) 
{
    Console.WriteLine("You rolled triples! +6 bonus to total!");
    total += 6;
}

if (total >= 15)
{
    Console.WriteLine("You win!");
}

if (total < 15)
{
    Console.WriteLine("Sorry, you lose.");
}

這裡會結合兩個布林運算式,在單行程式碼中建立一個複合布林運算式。 我們有一組外部括弧,其中會結合兩組以兩個 & 符號字元分隔的內部括弧。

雙 & 符號字元 &&邏輯 AND 運算子,基本上表示「只有在這兩個運算式都為 True 時,則整個運算式才為 True」。 在此案例中,如果 roll1 等於 roll2roll2 等於 roll3,則 roll1 必定等於 roll3,而且使用者擲出三骰同點。

如果執行此程式碼,可能會看到如以下範例的輸出結果:

Dice roll: 3 + 6 + 1 = 10
Sorry, you lose.

或是如此範例所示:

Dice roll: 1 + 4 + 4 = 9
You rolled doubles! +2 bonus to total!
Sorry, you lose.

或是如此範例所示:

Dice roll: 5 + 6 + 4 = 15
You win!

或者如果您很幸運,就會看到如下的輸出結果:

Dice roll: 6 + 6 + 6 = 18
You rolled doubles! +2 bonus to total!
You rolled triples! +6 bonus to total!
You win!

不過,等等,我們真的要獎勵玩家同時取得三倍獎勵和雙倍獎勵嗎? 畢竟,三倍意味著他們也擲出了雙倍。 在理想的情況下,這個獎勵不會「重複給予」。 它們應該是兩個不同的獎勵。 我們犯了第一個邏輯錯誤 (Bug)。

我們邏輯中的問題,以及改善程式碼的機會

雖然我們已經有了良好的出發點,而且了解許多關於 if 陳述式、布林運算式、程式碼區塊、邏輯 OR 與 AND 運算子等等的資訊,但其中還有許多改善空間。 我們將在下一個單元中執行此動作。

概括回顧

  • 使用 if 陳述式來為程式碼邏輯設定分支。 如果 if 決策陳述式的布林運算式等於 True,則將執行其程式碼區塊中的程式碼。 否則,執行階段將略過此程式碼區塊,並繼續執行此程式碼區塊後面的下一行程式碼。
  • 布林運算式是任何會傳回布林值的運算式。
  • 布林運算子將比較其左邊和右邊的兩個值,以進行相等、比較等操作。
  • 程式碼區塊會以大括弧 { } 來定義。 它會收集應視為單一單位的程式碼。
  • 邏輯 AND 運算子 && 會彙總兩個運算式,如此一來,這兩個子運算式都必須為 True,整個運算式才為 True。
  • 邏輯 OR 運算子 || 會彙總兩個運算式,如此一來,若任一個子運算式為 True,則整個運算式即為 True。