在 Kotlin 中新增條件式行為

1. 事前準備

在本 Kotlin 程式碼研究室中,您將建立另一款骰子遊戲 Lucky Dice Roll,試著擲出幸運數字。此遊戲程式將設定一個幸運數字,並擲出骰子。然後,程式會對照幸運數字檢查擲出的數字,並將適當的訊息列印至輸出內容。爲此,您將學習如何在 Kotlin 程式中比較值並做出不同的決策。

為協助您專注於程式設計概念,而無須擔心應用程式的使用者介面,您將使用以瀏覽器為基礎的 Kotlin 程式設計工具,並將結果輸出至控制台。

必要條件

課程內容

  • 如何使用 ifelse 陳述式。
  • 如何使用大於 (>)、小於 (<) 和等於 (==) 等運算子來比較值。
  • 如何使用 when 陳述式來根據指定值選擇選項。
  • Boolean 資料類型是什麼,以及如何使用 truefalse 值來做出決策。

建構項目

  • Lucky Dice Roll 是一款以 Kotlin 為基礎的骰子遊戲,您可以在其中指定一個幸運數字。只要玩家擲出這個幸運數字,即可獲勝。

需求條件

  • 連線網際網路的電腦。

2. 在程式碼中做出決策

Lucky Dice Roller 程式需判斷使用者是否擲出幸運數字,並根據結果傳送祝賀訊息或再試一次訊息。

應用程式開發人員須決定應用程式的行為方式,並為使用者建立不同的結果。

如要建構購物應用程式,可以根據使用者選擇的配送選項顯示不同的畫面。若是測驗遊戲,則會根據玩家答案是否正確來顯示不同的畫面。視應用程式而定,您可能需要在程式碼中考量多種可能的結果。

在 Lucky Dice Roller 程式中,應用程式應處理不同的情況,例如:

  • 如果擲出的骰子是幸運數字,系統會顯示恭喜訊息!
  • 否則如果擲出的骰子並非幸運數字,系統會顯示再試一次訊息。

如要在程式碼中新增此邏輯,請使用特殊的 Kotlin 關鍵字,例如 ifelsewhen

以下舉幾個例子來說明。

使用 if 陳述式來設定符合的條件

  1. 檢查下方的程式碼。您猜得到輸出內容是什麼嗎?
fun main() {
   val num = 5
   if (num > 4) {
       println("The variable is greater than 4")
   }
}
  1. 將程式碼複製及貼上到 Kotlin 程式編輯器中,然後執行程式來觀察輸出內容。
The variable is greater than 4

此程式的決策過程如下所示:

  1. 建立變數 num 並將其設為 5.
  2. 如果 num 大於 4,系統會列印 "The variable is greater than 4"
  3. 在所有其他情況下,不必採取任何行動。

在上述範例中,num 設定為 5。if 陳述式會比較變數是否大於 4。由於比較結果為 true,系統接下來會執行大括號內的指令並列印訊息。

請注意 if 陳述式的一般格式:

  • if 關鍵字開頭。
  • 後接一對括號 ()。括號內包含條件。該條件可以是結果為 truefalse 的任何條件。例如,一個數字是否大於另一個數字。
  • 後接一對大括號 {}。在大括號內包含結果為 true 的條件時要執行的程式碼。
if (condition-is-true) {
    execute-this-code
}

使用 if 陳述式來設定不符合的條件

  1. num 的值變更為 3,如下所示。如果執行這個程式碼,您預計會發生什麼情況?
fun main() {
    val num = 3
    if (num > 4) {
        println("The variable is greater than 4")
    }
}
  1. 將這些程式碼複製並貼到 Kotlin 程式編輯器中,然後執行程式來觀察輸出內容是否為空白。

num 設為 3 時,系統不會列印任何內容,因為 num 的值小於 4。num 大於 4 的條件結果為 false,並且系統將不會執行大括號內的程式碼,也不會列印任何內容。

使用 else 為不符合的條件建立替代條件

在不符合條件的情況下,您可以為使用者提供其他內容,而非毫無行動。就像使用一般語言一樣,您可以使用 else 陳述式來實現此目標。

  1. 新增一個 else 陳述式,以在 num 不大於 4 的情況下列印訊息,如下所示。如果執行這個程式碼,您預計會發生什麼情況?
fun main() {
    val num = 3
    if (num > 4) {
        println("The variable is greater than 4")
    } else {
        println("The variable is less than 4")
    }
}
  1. 將程式碼複製及貼上到 Kotlin 程式編輯器中,然後執行程式來觀察輸出內容。
The variable is less than 4
  1. 請注意,當 num 的值為 3 時,程式會顯示與 else 陳述式相關聯的 The variable is less than 4 訊息,因為 num 不大於 4。
  2. num 變更為 5,然後再次執行該程式。現在,num 大於 4,而程式會列印「The variable is greater than 4」。
  3. num 變更為 4 並執行程式。現在,4 不大於 4,程式會列印「The variable is less than 4」。

雖然「The variable is less than 4」是程式碼中所設定條件的正確輸出內容,但顯示的陳述式不準確,因為 4 不小於 4。您可以新增另一個條件,用於檢查第三種可能性,即 num 是否等於 4,並在條件為 true 時顯示正確的陳述式。

使用 else if 組合新增替代條件

您可以設定多個條件。舉例來說,您可以使用下列方式涵蓋 num 的所有可能性:

  • 如果 num 大於 4,則顯示 "The variable is greater than 4"
  • 否則如果 num 等於 4,則顯示 "The variable is equal to 4"
  • 否則,系統會列印 "The variable is less than 4"

這些條件在 If-else 陳述式中稱為不同情況。上面列出 3 種情況。

更新後的程式碼如下所示:

fun main() {
    val num = 4
    if (num > 4) {
        println("The variable is greater than 4")
    } else if (num == 4) {
        println("The variable is equal to 4")
    } else {
        println("The variable is less than 4")
    }
}

請注意下列異動:

  • num 的值現已設為 4,因此您可以測試新條件。
  • 在原始的 ifelse 陳述式之間是新的 else if 陳述式,適用於 num 恰好為 4 的情況。
  1. 將上述程式碼複製並貼到 Kotlin 程式編輯器中,然後執行程式來觀察輸出內容。
The variable is equal to 4
  1. 嘗試變更 num 的值,看看會對輸出內容產生什麼影響。將 num 變更為 2 和 6 後,您會看到每個條件變爲 true

控制流程

您查看上述 if-else 陳述式時,會發現程式碼可能會執行或繼續,如同受到條件的控制。因此,藉由這些條件來引導程式執行的過程稱為程式的「控制流程」。

  • 假設擲骰子的 num 為 3,該程式會檢查第一個條件 (num > 4)。結果為 false,因此程式會檢查下一個條件 (num == 4),結果同樣為 false。然後,程式會執行 else 陳述式的程式碼,這是最後一個選項。
  • 如果擲出的骰子 num 為 6,第一個條件 (num > 4) 的結果為 true。程式會顯示「The variable is greater than 4」訊息。由於此條件結果為 true,因此無須檢查其餘條件,使用 if-else 陳述式即可完成這項工作。
  • 使用 else + if 組合可新增替代條件。

3. 建立 Lucky Dice Roll 遊戲

在本節中,您將運用在上一個工作中學到的內容更新 Dice Roller 程式,檢查是否擲出預設的幸運數字。擲出預設的幸運數字代表您獲勝!

設定範例程式碼

您用來開始建構 Lucky Dice Roller 的程式碼,會類似於先前 Kotlin Dice Roller 程式的解決方案程式碼。您可以編輯先前程式碼中的 main() 函式來進行比對,也可以複製及貼上下方的程式碼來開始建構。

fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    println("Your ${myFirstDice.numSides} sided dice rolled ${rollResult}!")
}

class Dice (val numSides: Int) {

    fun roll(): Int {
        return (1..numSides).random()
    }
}

檢查是否擲出幸運數字

請先建立一個幸運數字,再比較擲出的數字與該數字。

  1. main() 中,刪除 println() 陳述式。
  2. main() 中,新增名為 luckyNumberval,並將其設為 4。您的程式碼應如下所示。
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4
}
  1. 在下方新增 if 陳述式,括號 () 內包含條件,用於檢查 rollResult 是否等於 (==) luckyNumber。在大括號 {} 之間保留一些空間,以新增更多程式碼。
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4
    if (rollResult == luckyNumber) {

    }
}
  1. 在大括號 {} 內新增 println 陳述式,以列印 "You win!"
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    if (rollResult == luckyNumber) {
        println("You win!")
    }
}
  1. 執行程式。您可能需要執行幾次之後才會得到幸運數字,並在輸出內容中看到獲勝訊息。
You win!

在未擲出幸運數字時回應

在使用者沒有獲勝的情況下,如果程式沒有任何回應,使用者就可能懷疑程式是否故障。最好的做法是對使用者的每個動作給予回應。在 Lucky Dice Roller 程式中,可以使用 else 陳述式告知使用者他們並未獲勝。

  1. 新增 else 陳述式以列印 "You didn't win, try again!"
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    if (rollResult == luckyNumber) {
        println("You win!")
    } else {
        println("You didn't win, try again!")
    }
}
  1. 執行程式。無論結果為何,使用者都會收到通知。

此時,使用者會知道自己是否獲勝,但不知道原因。請務必向使用者提供相關資訊,讓他們瞭解自己的操作結果!假設您的程式是貸款應用程式。提供「您的信用評等較差,因此並未獲得核准」訊息,會比提供「很抱歉,無法向您提供貸款,請再試一次!」訊息更實用。在 Lucky Dice Roller 中,如果使用者失敗,您可以在使用者每次擲出骰子時提供不同的資訊型訊息。為此,請使用多個 else if 陳述式。

  1. 新增 else if 陳述式,即可針對每次擲骰輸出不同訊息。必要時,請參閱您在上一個工作中學到的格式。
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    if (rollResult == luckyNumber) {
        println("You win!")
    } else if (rollResult == 1) {
        println("So sorry! You rolled a 1. Try again!")
    } else if (rollResult == 2) {
        println("Sadly, you rolled a 2. Try again!")
    } else if (rollResult == 3) {
        println("Unfortunately, you rolled a 3. Try again!")
    } else if (rollResult == 5) {
        println("Don't cry! You rolled a 5. Try again!")
    } else {
        println("Apologies! You rolled a 6. Try again!")
    }
}

在上方的程式碼中,您可以

  • 檢查 rollResult 是否為 luckyNumber
  • 如果 rollResultluckyNumber,系統會列印獲勝訊息。
  • 否則,請檢查 rollResult 是否為 1。如果是,系統會列印再試一次訊息。
  • 否則,請檢查 rollResult 是否為 2。如果是,系統會列印另一則再試一次訊息。
  • 否則,請繼續檢查,直至數字 5。
  • 如果這個數字並非介於 1 到 5,則僅剩下選項 6,因此不必再使用 else if 進行測試,可以透過最後一個 else 陳述式直接擷取最後一個選項。

由於使用多個 else if 的情況很常見,因此 Kotlin 提供一種更簡單的編寫方法。

4. 使用 when 陳述式

在程式設計中,針對許多不同的結果或情況進行測試的做法很常見。有時,可能的結果很多。舉例來說,如果使用 12 面骰子,成功結果與最終 else 之間會有 11 個 else if 陳述式。為了讓這類陳述式更容易寫入和讀取,Kotlin 提供 when 陳述式,以幫助避免錯誤。

您將變更程式,改為使用 when 陳述式。when 陳述式的開頭為關鍵字 when,後接 () 括號。括號內包含要測試的值。後接大括號 {},讓程式碼可以在不同的條件下執行。

  1. 在程式的 main() 中,選取從第一個 if 陳述式至括住最後一個 else 陳述式的大括號 } 之間的程式碼,然後刪除這些程式碼。
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4
}
  1. main() 中的 luckyNumber 宣告下方,建立 when 陳述式。由於 when 須針對擲出的結果進行測試,因此請將 rollResult 包含在括號 () 內。新增大括號 {} 並留出額外的空格,如下所示。
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    when (rollResult) {

    }
}

和先前一樣,先測試 rollResult 是否與 luckyNumber 相同。

  1. when 陳述式的大括號 {} 內,新增用來測試 luckyNumber 的陳述式 rollResult。如果兩者相同,系統會顯示獲勝訊息。此陳述式如下所示:
luckyNumber -> println("You win!")

因此:

  • 請先放入您要與 rollResult 比較的值。即 luckyNumber
  • 後接箭頭 (->)。
  • 然後,新增系統偵測到相符內容時要執行的動作。

這可以讀做「如果 rollResultluckyNumber,系統會顯示 "You win!" 訊息」。

您的 main() 程式碼如下所示。

fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    when (rollResult) {
        luckyNumber -> println("You win!")
    }
}
  1. 使用相同的模式為可能擲出的數字 1 至 6 (4 除外) 新增行和訊息,如下所示。完成的 main() 函式應如下所示。
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    when (rollResult) {
        luckyNumber -> println("You won!")
        1 -> println("So sorry! You rolled a 1. Try again!")
        2 -> println("Sadly, you rolled a 2. Try again!")
        3 -> println("Unfortunately, you rolled a 3. Try again!")
        5 -> println("Don't cry! You rolled a 5. Try again!")
        6 -> println("Apologies! You rolled a 6. Try again!")
    }
}
  1. 執行程式。輸出內容沒有任何差異,但您的程式碼更爲精簡,也更容易閱讀。

恭喜!您已掌握根據條件輸出訊息的兩種方式。這是一款強大的工具,非常適合用來編寫有趣的程式!

5. 解決方案程式碼

fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    when (rollResult) {
        luckyNumber -> println("You won!")
        1 -> println("So sorry! You rolled a 1. Try again!")
        2 -> println("Sadly, you rolled a 2. Try again!")
        3 -> println("Unfortunately, you rolled a 3. Try again!")
        5 -> println("Don't cry! You rolled a 5. Try again!")
        6 -> println("Apologies! You rolled a 6. Try again!")
   }
}

class Dice(val numSides: Int) {
    fun roll(): Int {
        return (1..numSides).random()
    }
}

6. 總結

  • 使用 if 陳述式來設定執行部分指令的條件。舉例來說,如果使用者擲出幸運數字,系統會列印獲勝訊息。
  • Boolean 資料類型的值為 truefalse,可用於做出決策。
  • 使用大於 (>)、小於 (<) 和等於 (==) 運算子來比較值。
  • 使用 else if 陳述式鏈結可設定多個條件。例如,系統會為每次可能擲出的骰子列印不同的訊息。
  • 在條件鏈結的結尾處使用 else 陳述式,以捕捉您未明確涵蓋的任何情況。如果您涵蓋 6 面骰子的情況,else 陳述式會捕捉使用 8 面骰子時擲出的數字 7 和 8。
  • 使用 when 陳述式做為根據比較數值的結果執行程式碼的一種精簡形式。

if-else 的一般形式:

if (condition-is-true) {
    execute-this-code
} else if (condition-is-true) {
    execute-this-code
} else {
    execute-this-code
}

when 陳述式:

when (variable) {
    matches-value -> execute-this-code
    matches-value -> execute-this-code
    ...
}

7. 瞭解詳情

8. 自行練習

請練習下列項目:

  1. myFirstDice 變更為包含 8 個面並執行程式碼。會發生什麼?

提示:當您增加面數時,when 陳述式不會再涵蓋所有情況,因此如果出現未涵蓋的情況,系統不會顯示任何內容。

  1. 修正 when 陳述式,以涵蓋所有 8 個面。爲此,您可以新增針對其他數字的情況。挑戰:使用 else 陳述式可捕捉所有未明確涵蓋的情況,而不必針對每個數字新增新的情況。

提示:您可以新增更多情況來涵蓋更多面。如果您希望系統為擲出的每個數字顯示不同的訊息,可以採用這種方式。或者,您可以使用 else 陳述式,針對現有程式碼涵蓋的所有大於 6 的面顯示相同訊息。

  1. myFirstDice 變更為僅包含 4 個面。會發生什麼?

提示:將骰子的面數變更為小於 when 陳述式涵蓋的範圍時,不會產生明顯影響,因為會發生的所有情況均涵蓋在內。