建立可執隨機擲骰子的 Kotlin 程式,當使用者「擲骰子」時,系統會隨機產生結果。
學習目標
- 如何透過程式輔助方式產生隨機數字來模擬擲骰子的動作。
- 如何透過建立含有變數和方法的 Dice 類別來建構程式碼。
- 如何建立類別的物件例項、修改其變數,以及呼叫其方法。
使用隨機函式
如要擲骰子,需要設法呈現所有有效的骰子值。一般的 6 面骰子,可接受的結果有 1、2、3、4、5 和 6。IntRange
是一種資料類型,代表從起點到終點的整數範圍。
在這裡,我們使用 IntRange
定義骰子可能產生的值。
- 在
main() 函式
中定義為名為diceRange
的val
,並給定 1 到 6 的 IntRange,代表 6 面骰子可以擲出的整數範圍。
1 | val diceRange = 1..6 |
val diceRange = 1..6
等於val diceRange: IntRange = 1..6
- 使用
random()
的函式,產生並傳回指定範圍的隨機數字,將結果儲存在變數中。
- 在 main() 中,定義一個為名為
randomNumber
的val
。 - 將
diceRange
呼叫random()
的結果,存在randomNumber
中 。
1 | val randomNumber = diceRange.random() |
- 執行程式碼數次印出
randomNumber
,可以發現隨機數字不一樣。
1 | println("隨機數字: ${randomNumber}") |
建立骰子類別
我們可以建立骰子的程式輔助藍圖,指出骰子有多個面,而且可以擲出隨機數字。此藍圖稱為類別。
接下來,就可以透過該類別建立實際的骰子物件,稱為「物件執行個體」。例如建立有 12 個面或 4 個面的骰子。
定義骰子類別
- 在下列步驟中,會定義名為
Dice
的新類別來代表可投擲的骰子。
- 為了重新開始,請清除
main()
函式中的程式碼。
1 | fun main() { |
- 在這個
main()
函式下方,新增空白行,然後新增程式碼來建立Dice
類別。如下所示,請先輸入關鍵字class
,然後輸入類別名稱,後面加左右大括號。請在左右大括號之間留出空格,以便放入類別的程式碼。
1 | class Dice { |
- 在類別定義中,您可以使用變數為類別指定一或多項屬性。真實的骰子可以有多個面、一種顏色或重量。在這項工作中,您的重點會放在骰子面數的屬性上。
- 在 Dice 類別中,新增名為
sides
的var
做為骰子的面數。將 sides 設為 6。
1 | class Dice { |
var是可變變量,而val是不可變變量,var 在被賦予值後還能夠修改,但是val不行。
建立骰子類別的執行個體
有了這個 Dice 類別,等同您掌握骰子的藍圖。如要讓程式中「實際」顯示骰子,就需要建立 Dice 物件例項。(如果您需要三個骰子,就要建立三個物件執行個體。)

- 如要建立
Dice
的物件執行個體,請在main()
函式中建立名為myFirstDice
的val
,並將其初始化為 Dice 類別的執行個體。
- 請注意類別名稱之後的
括號
,代表要從類別
建立新的物件執行個體
。
1 | fun main() { |
現在已經有了根據藍圖建立的 myFirstDice
物件,便可以存取其屬性。Dice 唯一的屬性是 sides
。
如要存取 myFirstDice
的 sides
屬性,可以使用「點標記法」呼叫 myFirstDice.sides
,讀音為「myFirstDice 點 sides」。
- 在 myFirstDice 宣告下方,新增 println() 陳述式,以輸出 myFirstDice. 的 sides 數量
1 | println(myFirstDice.sides) |
- 執行程式,應會輸出
Dice類別
中定義的sides數量
。
現在程式碼:
1 | fun main() { |
執行結果:
1 | 6 |
擲骰子
在 Dice類別
中新增一個用來擲骰子的 函式
。
- 在類別中定義的函式也稱為「方法」。
- 在 Dice 類別 sides 變數下方﹐插入一行空行,然後建立新的函式來擲骰子。
1 | class Dice { |
- 在
roll()
方法中建立一個val
randomNumber
,並呼叫random()
以在 1..6 範圍內產生一個隨機數字。
1 | class Dice { |
- 產生
隨機數字
後將其輸出。完成的 roll() 方法應如以下程式碼所示。
1 | fun roll() { |
- 如要實際投擲
myFirstDice
,請在main()
中對myFirstDice
呼叫roll()
方法,如myFirstDice.roll()
,讀音為「myFirstDice 點 roll()」。
現在程式碼:
1 | fun main() { |
執行結果:
1 | 6 |
1
為隨機產生的數字
傳回擲骰子的結果值
將 roll()
方法的結果(產生的隨機數字)存在一個變數中,並回傳到 main函式
。
在 main() 中,修改顯示 myFirstDice.roll() 的行。建立名為
diceRoll
的val
。1
val diceRoll = myFirstDice.roll()
變更
roll()
函式,以指定要傳回的資料類型。在本例子中,隨機數字是Int
,因此傳回類型為Int
。
指定傳回類型的語法為在函式名稱後面,在括號後加上冒號和空格,然後為函式的傳回類型加上 Int 關鍵字
。
1 | class Dice { |
- 在
roll()
中移除println()
陳述式,並以randomNumber
的return
來取代。
1 | class Dice { |
- 在
main函式
中輸出sides
和diceRoll
的值。1
2
3
4
5fun main() {
val myFirstDice = Dice()
val diceRoll = myFirstDice.roll()
println("Your ${myFirstDice.sides} sided dice rolled ${diceRoll}!")
}
現在程式碼:
1 | fun main() { |
執行結果:
1 | Your 6 sided dice rolled 4! |
6
為骰子的面數,4
為1~6中隨機產生的數字
變更骰子面數
不是所有骰子都有 6 面!骰子有各種形狀和尺寸,有 4 面、8 面,最多可到 120 面!
- 在
Dice
類別的roll()
方法中,將硬式編碼的1..6
改為使用sides
。這樣,範圍與擲出的隨機數字便一律適用於面數。
1 | val randomNumber = (1..sides).random() |
- 在 main() 函式中,在擲出的骰子結果下方,將
myFirstDice
的sides
變更為 20。
1 | myFirstDice.sides = 20 |
- 複製下方的現有輸出陳述式,然後貼到變更面數的後面,然後將
myFirstDice
的輸出結果替換為對diceRoll
呼叫roll()
方法的輸出結果。
1 | println("Your ${myFirstDice.sides} sided dice rolled ${myFirstDice.roll()}!") |
現在程式碼:
1 | fun main() { |
執行結果:
1 | Your 6 sided dice rolled 2! |
- 第一行為
6面骰子
的訊息,第二行為20面骰子
的訊息
自訂骰子
修改 Dice類別
,以便在建立新的執行個體時指定面數。
- 變更
Dice類別定義
就能提供面數,這與函式接受輸入引數的方式類似。
- 修改
Dice類別定義
,以接受名為numSides
的整數。類別中的程式碼不會改變。1
2
3class Dice(val numSides: Int) {
// Code inside does not change.
} - 在
Dice類別
中刪除sides變數
,並將用到sides
的地方修改成numSides
。
1 | class Dice(val numSides: Int) { |
- 在
main()
中,如要建立含有 6 個面的myFirstDice
,您現在必須提供面數做為 Dice 類別的引數。
1 | val myFirstDice = Dice(6) |
- 在輸出陳述式中,將 sides 變更為 numSides。
- 然後在下方,刪除將 sides 變更為 20 的程式碼,因為該變數已不再存在。
- 請一併刪除下方的 println 陳述式。
main() 函式應如下列程式碼所示:
1 | fun main() { |
- 新增程式碼來建立並輸出第二個名為
mySecondDice
的Dice物件
,這個骰子包含20
個面。
1 | val mySecondDice = Dice(20) |
- 新增用於投擲和輸出傳回值的輸出陳述式。
1 | println("Your ${mySecondDice.numSides} sided dice rolled ${mySecondDice.roll()}!") |
現在程式碼:
1 | fun main() { |
執行結果:
1 | Your 6 sided dice rolled 3! |
- 第一行為
第一個骰子(6面骰子)
的執行結果,第二行為第二個骰子(20面骰子)
的執行結果。
採用完善程式設計做法
編寫程式碼時,應保持簡潔。
- 可以去除
randomNumber
變數,並直接傳回隨機數字。
1 | fun roll(): Int { |
- 在字串範本中呼叫
myFirstDice.roll()
並刪除diceRoll
變數。
1 | println("Your ${myFirstDice.numSides} sided dice rolled ${myFirstDice.roll()} |
最終的程式碼:
1 | fun main() { |
總結
- 對
IntRange
呼叫random()
函式以產生隨機數字:(1..6).random()
類別
就像是物件的藍圖
,會包含屬性
和行為
,可做為變數
和函式
來實作。類別的執行個體
代表一個物件
,通常是實物,例如骰子。您可以對物件呼叫動作,並變更其屬性。- 可以在建立執行個體時,為類別提供值。例如:
class Dice(val numSides: Int)
,然後使用Dice(6)
建立執行個體。 - 函式可以傳回結果。在函式定義中指定要傳回的資料類型,並在函式主體中使用
return
來傳回一些內容。例如:fun example(): Int { return 5 }
自行練習
建立 Coin
類別,讓它能夠翻轉、建立類別執行個體,以及拋擲一些硬幣!您會如何使用 random()
函式搭配範圍來完成硬幣拋擲動作呢?
程式碼:
1 | fun main() { |
執行結果:
1 | Your 2 sided coin rolled 1! |
- 硬幣有正反2面,假設
1
為正面,2
為反面。
建立互動式的Dice Roller應用程式
建立一個 Dice Roller Android 應用程式,讓使用者能在應用程式中按一下
Button
來擲骰子。擲骰子結果會顯示在螢幕上的TextView
中。
學習目標
- 如何將
Button
新增至 Android 應用程式。 - 如何新增輕觸應用程式
Button
時的行為。 - 如何開啟及修改應用程式的
Activity
程式碼。 - 如何顯示
Toast
訊息。 - 如何在應用程式執行期間更新
TextView
的內容。
設定應用程式
*範例為使用 Empty View Activity 構建App,非新版 Empty Activity
- 在 Create New Project(建立新專案) 中,使用
Empty View Activity
範本建立新的 Kotlin 專案。

- 將應用程式命名為「Dice Roller」,指定最低 API 級別 19 (KitKat)。

建立應用程式的版面配置
- 開啟
activity_main.xml
,在「Hello World」TextView 下方新增Button
。

- TextView 和 Button 皆位於 ViewGroup 類型的
ConstraintLayout
中。

- 由於
Button
位於ConstraintLayout
內,因此您必須設定垂直和水平限制條件進行定位。

安排按鈕的位置
新增從 Button 頂端到 TextView 底部的垂直限制條件。
- 在「Design」檢視畫面中,按住
Button
上方邊緣有藍色邊框的白色圓圈。拖曳指標,並箭頭會遵循指標。當您移動到「Hello World」TextView
底部邊緣時放開。這項操作會建立版面配置限制條件,且Button
往上滑至TextView
正下方。

- 查看「Layout Editor」(版面配置編輯器) 右側的「Attributes」(屬性)。請留意「Constraint Widget」中,新版面配置的限制條件設定為
TextView
的底部,例如Top → BottomOf textView (0dp)
。
- (0dp) 表示邊界為 0。已發生缺少水平限制條件的錯誤。

- 新增從
Button
的左側至父項ConstraintLayout
的左側的水平限制條件。並於右側重複操作,將Button
的右邊緣連接到ConstraintLayout
的右邊緣。結果看起來會像這樣

- 在仍然選取
Button
的情況下,「Constraint Widget」應如下所示。您新增了兩個額外的限制條件:Start → StartOf parent (0dp)
和End → EndOf parent (0dp)
。這表示Button
是水平置中於其父項ConstraintLayout
中。

- 執行應用程式,應如以下螢幕截圖所示。

變更按鈕文字
- 在版面配置編輯器中,如果已選取 Button,請前往「Attributes」,將「text」變更為「Roll」,然後按下 Enter 鍵 (Mac 則是按下 Return 鍵)。

- 在「Component Tree」中,Button 旁邊會顯示橘色的警示三角形。只要游標懸停在三角形上,就會顯示訊息。Android Studio 在您的應用程式的程式碼中偵測到硬式編碼字串 (「Roll」),因此建議您改用字串資源。

- 在「Component Tree」中點選橘色三角形。在訊息底部的「Suggested Fix」下方,按一下「Fix」按鈕。(您可能需要向下捲動頁面。)

- 系統隨即會開啟「Extract Resource」(擷取資源) 對話方塊。擷取字串代表擷取「Roll」文字,並在 strings.xml 中建立一個名為 roll 的字串資源 (app > res > values > strings.xml)。由於預設值正確無誤,因此請按一下「OK」。

- 在「Attributes」中,Button 的 text 屬性現在會指向 @string/roll

設定 TextView 的樣式
小型「Hello, World!」訊息取代為數字以顯示搖骰子值,並放大字型,讓使用者一目瞭然。
- 在「Design Editor」中選取
TextView
,接著將TextView
的textSize
變更為 36sp,以便放大且易讀。

- 清除
TextView
的text
屬性。您不用在 TextView 中顯示任何資訊,直到使用者擲骰子為止。

不過,當您編輯應用程式的版面配置和程式碼時,在 TextView
中查看部分文字會很有幫助。為此,您可以在 TextView
新增文字,這些文字只會顯示在版面配置預覽中,但在應用程式執行時不會顯示。
在「Common Attributes」下方找到「text」屬性,下方則顯示含有工具圖示的「text」屬性。text 屬性是在應用程式執行時顯示給使用者。含有工具圖示的「text」屬性是專為您 (開發人員) 設計的「tools text」屬性。
在
TextView
中將工具文字設定為「1」
(假設您有一個顯示「1」的骰子)。「1」
只會出現在 Android Studio 的「Design Editor」(設計編輯器) 中,但當您在實際裝置或模擬器上執行應用程式時,畫面上不會顯示「1」
。

啟用自動匯入作業
如果您同時使用更多類別,新增 import 陳述式會變得困難。幸好,使用他人提供的類別時,Android Studio 可協助您選擇正確的匯入作業。
在 macOS 中:
-> 依序前往「File」(檔案) >「New Project Settings」(新專案設定) >「Preferences for New Project…」(新專案的偏好設定…) 開啟設定。
-> 依序展開「Other Settings」(其他設定) >「Auto Import」(自動匯入)。
-> 在「Java」和「Kotlin」區段中,確定已勾選「Add unambiguous imports on the fly」(快速新增不明確的匯入) 和「Optimize imports on the fly (for current project)」(快速最佳化匯入 (適用於目前的專案))。
-> 按下「OK」儲存變更,然後關閉設定。

提高按鈕互動性
在點選按鈕時顯示訊息
在按下按鈕時,畫面底部顯示簡短訊息。
setContentView()
呼叫後,將下列程式碼新增至onCreate()
方法。findViewById()
方法會在版面配置中找到Button
。R.id.button
是Button
的資源 ID,這是其專屬識別碼。
1 | val rollButton: Button = findViewById(R.id.button) |
- 使用
rollButton
物件並呼叫setOnClickListener()
方法,在物件上設定點擊事件監聽器,來監聽使用者是否點選Button
。
- 在方法名稱後面使用大括號,而不要使用括號。這是一個宣告
Lambda
的特殊語法,詳情請見未來程式碼研究室的內容。
1 | rollButton.setOnClickListener { |
- 呼叫
Toast.makeText()
即可建立內含文字 “Dice Rolled!” 的Toast
。
1 | val toast = Toast.makeText(this, "Dice Rolled!", Toast.LENGTH_SHORT) |
- 然後呼叫
show()
方法,讓Toast
自行顯示。
1 | val toast = Toast.makeText(this, "Dice Rolled!", Toast.LENGTH_SHORT).show() |
- 執行應用程式,然後按一下「Roll」按鈕。浮動式訊息應會以彈出式視窗顯示在螢幕底部,而且不久後就會消失。

在點選按鈕時更新 TextView
如果不想顯示臨時 Toast
訊息,您必須撰寫程式碼,並在點選「Roll」按鈕時更新畫面上的 TextView
。
- 註解
Toast
的程式碼行。 - 建立一個名稱為
resultTextView
的新變數,以便儲存TextView
。
1 | val resultTextView: TextView = findViewById(R.id.textView) |
- 將
resultTextView
上的文字設定為在雙引號內的6
。
1 | resultTextView.text = "6" |
新增擲骰子邏輯
新增 Dice (骰子) 類別
在 MainActivity 類別中加上最後一個大括號後,透過
roll()
方法建立Dice
類別。1
2
3
4
5
6class Dice(val numSides: Int) {
fun roll(): Int {
return (1..numSides).random()
}
}將游標懸停在
numSides
上,畫面上就會顯示「Property ‘numSides' could be private」
彈出式視窗。
- 將
numSides
標示為private
後,您只能在Dice
類別中存取。由於只有使用numSides
的程式碼才會位於Dice
類別內,因此可為Dice
類別指定這個引數private
。
- 按一下「Make ‘numSides’ ‘private」,繼續透過 Android Studio 修正建議問題。
建立 rollDice() 方法
現在您已經新增 Dice
類別至應用程式,必須更新 MainActivity
才能使用該類別。如要妥善整理程式碼,請將所有擲骰子邏輯放入一個函式中。
- 將點擊事件監聽器中將文字設定為
"6"
的程式碼替換為呼叫rollDice()
。
1 | rollButton.setOnClickListener { |
- 因為尚未定義
rollDice()
,Android Studio 會標記誤並以紅色顯示rollDice()
。滑鼠游標懸停在rollDice()
上時,Android Studio 會顯示問題和可能的解決方法。

- 按一下「More actions…」開啟選單。(Mac 可按下
Option+Enter
開啟選單。) - 選取
「Create function ‘rollDice'」
。Android Studio 會為 MainActivity 中的函式建立空白定義。

1 | private fun rollDice() { |
建立新的 Dice 物件例項
在這個步驟中,您必須建立 rollDice()
方法並擲骰子,然後在 TextView
中顯示結果。
- 在
rollDice()
中刪除 TODO() 呼叫,並加入程式碼即可建立具有 6 個面的骰子。
1 | val dice = Dice(6) |
- 呼叫
roll()
方法即可擲骰子,並將結果儲存在名為diceRoll
的變數中。
1 | val diceRoll = dice.roll() |
- 呼叫
findViewById()
即可找到TextView
。
1 | val resultTextView: TextView = findViewById(R.id.textView) |
- 將
diceRoll
轉換成字串,並使用該字串更新resultTextView
的文字。
- 變數
diceRoll
是數字,但TextView
使用文字。您可以在diceRoll
上使用toString()
方法,將數字轉換為字串。
1 | resultTextView.text = diceRoll.toString() |
- 執行應用程式,點選按鈕即可擲骰子。

採用完善程式設計做法
團隊合作時,理想的做法是以類似的方式撰寫程式碼,讓程式碼之間保持一致。因此,Android 提供樣式指南來說明如何編寫 Android 程式碼,包括命名慣例、格式和其他遵循的建議做法。
撰寫 Android 程式碼時遵循這些指南:Android 開發人員適用的 Kotlin 樣式指南。
清理您的程式碼
- 縮減程式碼
將程式碼縮減成較短行的程式碼,讓程式碼更精簡。以下範例是設定Button
點擊事件監聽器的程式碼。
1 | rollButton.setOnClickListener { |
由於點擊事件監聽器的操作說明只有 1 行,因此您可以縮減 rollDice()
方法呼叫,將此呼叫和大括號全部置於一行。
1 | rollButton.setOnClickListener { rollDice() } |
- 重新設定程式碼格式
現在,您必須重新設定程式碼格式,確保程式碼符合 Android 建議的程式碼格式規範。
在 MainActivity.kt
類別中,用 Windows 的鍵盤快速鍵 Control+A
(Mac 則是 Command+A
) 就可選取檔案中的所有文字。或者您可以在 Android Studio 的選單中依序點選「Edit」>「Select All」
。
選取檔案中的所有文字後,在 Android Studio 的選單中依序點選「Code」>「Reformat Code」
,或使用鍵盤快速鍵 Ctrl+Alt+L
(Mac 則是 Command+Option+L
)。
- 這會更新程式碼的格式,包括空白字元、縮排等等。您可能還看不到任何變化,這很好。您的程式碼已正確格式化!
- 為程式碼加上註解
為每個類別 (MainActivity
和Dice
是您的應用程式中僅有的類別) 和您撰寫的每個方法新增註解。請在註解的開頭和結尾使用/**
和*/
符號,告訴系統這不是程式碼。系統在執行程式碼時會忽略這些行。
自行練習
在應用程式中新增另一個骰子。按一下「Roll」按鈕應擲 2 個骰子。螢幕上應在 2 個不同的 TextViews
中顯示結果。
執行畫面:
程式碼:
1 | /** |