Tina Tang's Blog

在哪裡跌倒了,就在哪裡躺下來

0%

Android筆記(3)-建立Dice Roller應用程式

建立可執隨機擲骰子的 Kotlin 程式,當使用者「擲骰子」時,系統會隨機產生結果。

學習目標

  • 如何透過程式輔助方式產生隨機數字來模擬擲骰子的動作。
  • 如何透過建立含有變數和方法的 Dice 類別來建構程式碼。
  • 如何建立類別的物件例項、修改其變數,以及呼叫其方法。

使用隨機函式

如要擲骰子,需要設法呈現所有有效的骰子值。一般的 6 面骰子,可接受的結果有 1、2、3、4、5 和 6。
IntRange 是一種資料類型,代表從起點到終點的整數範圍。
在這裡,我們使用 IntRange 定義骰子可能產生的值。

  1. main() 函式 中定義為名為 diceRangeval,並給定 1 到 6 的 IntRange,代表 6 面骰子可以擲出的整數範圍。
1
val diceRange = 1..6
  • val diceRange = 1..6 等於 val diceRange: IntRange = 1..6
  1. 使用 random() 的函式,產生並傳回指定範圍的隨機數字,將結果儲存在變數中。
  • 在 main() 中,定義一個為名為 randomNumberval
  • diceRange 呼叫 random() 的結果,存在 randomNumber中 。
1
val randomNumber = diceRange.random()
  1. 執行程式碼數次印出 randomNumber ,可以發現隨機數字不一樣。
1
println("隨機數字: ${randomNumber}")

建立骰子類別

我們可以建立骰子的程式輔助藍圖,指出骰子有多個面,而且可以擲出隨機數字。此藍圖稱為類別
接下來,就可以透過該類別建立實際的骰子物件,稱為「物件執行個體」。例如建立有 12 個面或 4 個面的骰子。

定義骰子類別
  • 在下列步驟中,會定義名為 Dice 的新類別來代表可投擲的骰子。
  1. 為了重新開始,請清除 main() 函式中的程式碼。
1
2
3
fun main() {

}
  1. 在這個 main() 函式下方,新增空白行,然後新增程式碼來建立 Dice 類別。如下所示,請先輸入關鍵字 class,然後輸入類別名稱,後面加左右大括號。請在左右大括號之間留出空格,以便放入類別的程式碼。
1
2
3
class Dice {

}
  • 在類別定義中,您可以使用變數為類別指定一或多項屬性。真實的骰子可以有多個面、一種顏色或重量。在這項工作中,您的重點會放在骰子面數的屬性上。
  1. 在 Dice 類別中,新增名為 sidesvar 做為骰子的面數。將 sides 設為 6。
1
2
3
class Dice {
var sides = 6
}

var是可變變量,而val是不可變變量,var 在被賦予值後還能夠修改,但是val不行。

建立骰子類別的執行個體

有了這個 Dice 類別,等同您掌握骰子的藍圖。如要讓程式中「實際」顯示骰子,就需要建立 Dice 物件例項。(如果您需要三個骰子,就要建立三個物件執行個體。)

  1. 如要建立 Dice物件執行個體,請在 main() 函式中建立名為 myFirstDiceval,並將其初始化為 Dice 類別的執行個體
  • 請注意類別名稱之後的括號,代表要從類別建立新的物件執行個體
1
2
3
fun main() {
val myFirstDice = Dice()
}

現在已經有了根據藍圖建立的 myFirstDice 物件,便可以存取其屬性。Dice 唯一的屬性是 sides
如要存取 myFirstDicesides 屬性,可以使用「點標記法」呼叫 myFirstDice.sides,讀音為「myFirstDice 點 sides」。

  1. 在 myFirstDice 宣告下方,新增 println() 陳述式,以輸出 myFirstDice. 的 sides 數量
1
println(myFirstDice.sides)
  1. 執行程式,應會輸出 Dice類別 中定義的 sides數量

現在程式碼:

1
2
3
4
5
6
7
8
fun main() {
val myFirstDice = Dice()
println(myFirstDice.sides)
}

class Dice {
var sides = 6
}

執行結果:

1
6

擲骰子

Dice類別 中新增一個用來擲骰子的 函式

  • 在類別中定義的函式也稱為「方法」
  1. 在 Dice 類別 sides 變數下方﹐插入一行空行,然後建立新的函式來擲骰子。
1
2
3
4
5
6
7
class Dice {
var sides = 6

fun roll() {

}
}
  1. roll() 方法中建立一個 val randomNumber,並呼叫 random() 以在 1..6 範圍內產生一個隨機數字。
1
2
3
4
5
6
7
class Dice {
var sides = 6

fun roll() {
val randomNumber = (1..6).random()
}
}
  1. 產生隨機數字後將其輸出。完成的 roll() 方法應如以下程式碼所示。
1
2
3
4
fun roll() {
val randomNumber = (1..6).random()
println(randomNumber)
}
  1. 如要實際投擲 myFirstDice,請在 main() 中對 myFirstDice 呼叫 roll() 方法,如 myFirstDice.roll(),讀音為「myFirstDice 點 roll()」。

現在程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
fun main() {
val myFirstDice = Dice()
println(myFirstDice.sides)
myFirstDice.roll()
}

class Dice {
var sides = 6

fun roll() {
val randomNumber = (1..6).random()
println(randomNumber)
}
}

執行結果:

1
2
6
1
  • 1為隨機產生的數字

傳回擲骰子的結果值

roll() 方法的結果(產生的隨機數字)存在一個變數中,並回傳到 main函式

  1. 在 main() 中,修改顯示 myFirstDice.roll() 的行。建立名為 diceRollval

    1
    val diceRoll = myFirstDice.roll()
  2. 變更 roll() 函式,以指定要傳回的資料類型。在本例子中,隨機數字是 Int,因此傳回類型為 Int
    指定傳回類型的語法為 在函式名稱後面,在括號後加上冒號和空格,然後為函式的傳回類型加上 Int 關鍵字

1
2
3
4
5
6
7
8
class Dice {
var sides = 6

fun roll(): Int {
val randomNumber = (1..6).random()
println(randomNumber)
}
}
  1. roll() 中移除 println() 陳述式,並以 randomNumberreturn 來取代。
1
2
3
4
5
6
7
8
class Dice {
var sides = 6

fun roll(): Int {
val randomNumber = (1..6).random()
return randomNumber
}
}
  1. main函式 中輸出 sidesdiceRoll 的值。
    1
    2
    3
    4
    5
    fun main() {
    val myFirstDice = Dice()
    val diceRoll = myFirstDice.roll()
    println("Your ${myFirstDice.sides} sided dice rolled ${diceRoll}!")
    }

現在程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
fun main() {
val myFirstDice = Dice()
val diceRoll = myFirstDice.roll()
println("Your ${myFirstDice.sides} sided dice rolled ${diceRoll}!")
}

class Dice {
var sides = 6

fun roll(): Int {
val randomNumber = (1..6).random()
return randomNumber
}
}

執行結果:

1
Your 6 sided dice rolled 4!
  • 6為骰子的面數,4為1~6中隨機產生的數字

變更骰子面數

不是所有骰子都有 6 面!骰子有各種形狀和尺寸,有 4 面、8 面,最多可到 120 面!

  1. Dice 類別的 roll() 方法中,將硬式編碼的 1..6 改為使用 sides。這樣,範圍與擲出的隨機數字便一律適用於面數。
1
val randomNumber = (1..sides).random()
  1. 在 main() 函式中,在擲出的骰子結果下方,將 myFirstDicesides 變更為 20。
1
myFirstDice.sides = 20
  1. 複製下方的現有輸出陳述式,然後貼到變更面數的後面,然後將 myFirstDice 的輸出結果替換為對 diceRoll 呼叫 roll() 方法的輸出結果。
1
println("Your ${myFirstDice.sides} sided dice rolled ${myFirstDice.roll()}!")

現在程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fun main() {
val myFirstDice = Dice()
val diceRoll = myFirstDice.roll()
println("Your ${myFirstDice.sides} sided dice rolled ${diceRoll}!")

myFirstDice.sides = 20
println("Your ${myFirstDice.sides} sided dice rolled ${myFirstDice.roll()}!")
}

class Dice {
var sides = 6

fun roll(): Int {
val randomNumber = (1..sides).random()
return randomNumber
}
}

執行結果:

1
2
Your 6 sided dice rolled 2!
Your 20 sided dice rolled 15!
  • 第一行為 6面骰子 的訊息,第二行為 20面骰子 的訊息

自訂骰子

修改 Dice類別,以便在建立新的執行個體時指定面數

  • 變更 Dice類別定義 就能提供面數,這與函式接受輸入引數的方式類似。
  1. 修改 Dice類別定義,以接受名為 numSides 的整數。類別中的程式碼不會改變。
    1
    2
    3
    class Dice(val numSides: Int) {
    // Code inside does not change.
    }
  2. Dice類別 中刪除 sides變數,並將用到 sides 的地方修改成 numSides
1
2
3
4
5
6
class Dice(val numSides: Int) {
fun roll(): Int {
val randomNumber = (1..numSides).random()
return randomNumber
}
}
  1. main() 中,如要建立含有 6 個面的 myFirstDice,您現在必須提供面數做為 Dice 類別的引數。
1
val myFirstDice = Dice(6)
  • 在輸出陳述式中,將 sides 變更為 numSides。
  • 然後在下方,刪除將 sides 變更為 20 的程式碼,因為該變數已不再存在。
  • 請一併刪除下方的 println 陳述式。

main() 函式應如下列程式碼所示:

1
2
3
4
5
fun main() {
val myFirstDice = Dice(6)
val diceRoll = myFirstDice.roll()
println("Your ${myFirstDice.numSides} sided dice rolled ${diceRoll}!")
}
  1. 新增程式碼來建立並輸出第二個名為 mySecondDiceDice物件,這個骰子包含 20 個面。
1
val mySecondDice = Dice(20)
  1. 新增用於投擲和輸出傳回值的輸出陳述式。
1
println("Your ${mySecondDice.numSides} sided dice rolled  ${mySecondDice.roll()}!")

現在程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fun main() {
val myFirstDice = Dice(6)
val diceRoll = myFirstDice.roll()
println("Your ${myFirstDice.numSides} sided dice rolled ${diceRoll}!")

val mySecondDice = Dice(20)
println("Your ${mySecondDice.numSides} sided dice rolled ${mySecondDice.roll()}!")
}

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

執行結果:

1
2
Your 6 sided dice rolled 3!
Your 20 sided dice rolled 19!
  • 第一行為 第一個骰子(6面骰子) 的執行結果,第二行為 第二個骰子(20面骰子) 的執行結果。

採用完善程式設計做法

編寫程式碼時,應保持簡潔。

  1. 可以去除 randomNumber 變數,並直接傳回隨機數字。
1
2
3
fun roll(): Int {
return (1..numSides).random()
}
  1. 在字串範本中呼叫 myFirstDice.roll() 並刪除 diceRoll 變數。
1
println("Your ${myFirstDice.numSides} sided dice rolled ${myFirstDice.roll()}

最終的程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
fun main() {
val myFirstDice = Dice(6)
println("Your ${myFirstDice.numSides} sided dice rolled ${myFirstDice.roll()}!")

val mySecondDice = Dice(20)
println("Your ${mySecondDice.numSides} sided dice rolled ${mySecondDice.roll()}!")
}

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

總結

  • IntRange 呼叫 random() 函式以產生隨機數字:(1..6).random()
  • 類別就像是物件的藍圖,會包含屬性行為,可做為變數函式來實作。
  • 類別的執行個體代表一個物件,通常是實物,例如骰子。您可以對物件呼叫動作,並變更其屬性。
  • 可以在建立執行個體時,為類別提供值。例如:class Dice(val numSides: Int),然後使用 Dice(6) 建立執行個體。
  • 函式可以傳回結果。在函式定義中指定要傳回的資料類型,並在函式主體中使用 return 來傳回一些內容。例如:fun example(): Int { return 5 }

自行練習

建立 Coin 類別,讓它能夠翻轉、建立類別執行個體,以及拋擲一些硬幣!您會如何使用 random() 函式搭配範圍來完成硬幣拋擲動作呢?

程式碼:

1
2
3
4
5
6
7
8
9
10
fun main() {
val myCoin = Coin(2)
println("Your ${myCoin.numSides} sided coin rolled ${myCoin.roll()}!")
}

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

執行結果:

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

  1. 在 Create New Project(建立新專案) 中,使用 Empty View Activity 範本建立新的 Kotlin 專案。
  1. 將應用程式命名為「Dice Roller」,指定最低 API 級別 19 (KitKat)。

建立應用程式的版面配置

  1. 開啟 activity_main.xml,在「Hello World」TextView 下方新增 Button
  • TextView 和 Button 皆位於 ViewGroup 類型的 ConstraintLayout 中。
  1. 由於 Button 位於 ConstraintLayout 內,因此您必須設定垂直和水平限制條件進行定位。

安排按鈕的位置

新增從 Button 頂端到 TextView 底部的垂直限制條件。

  1. 在「Design」檢視畫面中,按住 Button 上方邊緣有藍色邊框的白色圓圈。拖曳指標,並箭頭會遵循指標。當您移動到「Hello World」TextView底部邊緣時放開。這項操作會建立版面配置限制條件,且 Button 往上滑至 TextView 正下方。
  1. 查看「Layout Editor」(版面配置編輯器) 右側的「Attributes」(屬性)。請留意「Constraint Widget」中,新版面配置的限制條件設定為 TextView 的底部,例如 Top → BottomOf textView (0dp)
  • (0dp) 表示邊界為 0。已發生缺少水平限制條件的錯誤。
  1. 新增從 Button 的左側至父項 ConstraintLayout 的左側的水平限制條件。並於右側重複操作,將 Button 的右邊緣連接到 ConstraintLayout 的右邊緣。結果看起來會像這樣
  1. 在仍然選取 Button 的情況下,「Constraint Widget」應如下所示。您新增了兩個額外的限制條件:Start → StartOf parent (0dp)End → EndOf parent (0dp)。這表示 Button 是水平置中於其父項 ConstraintLayout 中。
  1. 執行應用程式,應如以下螢幕截圖所示。

變更按鈕文字

  1. 在版面配置編輯器中,如果已選取 Button,請前往「Attributes」,將「text」變更為「Roll」,然後按下 Enter 鍵 (Mac 則是按下 Return 鍵)。
  1. 在「Component Tree」中,Button 旁邊會顯示橘色的警示三角形。只要游標懸停在三角形上,就會顯示訊息。Android Studio 在您的應用程式的程式碼中偵測到硬式編碼字串 (「Roll」),因此建議您改用字串資源。
  1. 在「Component Tree」中點選橘色三角形。在訊息底部的「Suggested Fix」下方,按一下「Fix」按鈕。(您可能需要向下捲動頁面。)
  1. 系統隨即會開啟「Extract Resource」(擷取資源) 對話方塊。擷取字串代表擷取「Roll」文字,並在 strings.xml 中建立一個名為 roll 的字串資源 (app > res > values > strings.xml)。由於預設值正確無誤,因此請按一下「OK」。
  1. 在「Attributes」中,Button 的 text 屬性現在會指向 @string/roll

設定 TextView 的樣式

小型「Hello, World!」訊息取代為數字以顯示搖骰子值,並放大字型,讓使用者一目瞭然。

  1. 在「Design Editor」中選取 TextView,接著將 TextViewtextSize 變更為 36sp,以便放大且易讀。
  1. 清除 TextViewtext 屬性。您不用在 TextView 中顯示任何資訊,直到使用者擲骰子為止。

不過,當您編輯應用程式的版面配置和程式碼時,在 TextView 中查看部分文字會很有幫助。為此,您可以在 TextView 新增文字,這些文字只會顯示在版面配置預覽中,但在應用程式執行時不會顯示。

  1. 在「Common Attributes」下方找到「text」屬性,下方則顯示含有工具圖示的「text」屬性。text 屬性是在應用程式執行時顯示給使用者。含有工具圖示的「text」屬性是專為您 (開發人員) 設計的「tools text」屬性

  2. 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」儲存變更,然後關閉設定。

提高按鈕互動性

在點選按鈕時顯示訊息

在按下按鈕時,畫面底部顯示簡短訊息。

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

如果不想顯示臨時 Toast 訊息,您必須撰寫程式碼,並在點選「Roll」按鈕時更新畫面上的 TextView

  1. 註解 Toast 的程式碼行。
  2. 建立一個名稱為 resultTextView 的新變數,以便儲存 TextView
1
val resultTextView: TextView = findViewById(R.id.textView)
  1. resultTextView 上的文字設定為在雙引號內的 6
1
resultTextView.text = "6"

新增擲骰子邏輯

新增 Dice (骰子) 類別
  1. 在 MainActivity 類別中加上最後一個大括號後,透過 roll() 方法建立 Dice 類別。

    1
    2
    3
    4
    5
    6
    class Dice(val numSides: Int) {

    fun roll(): Int {
    return (1..numSides).random()
    }
    }
  2. 將游標懸停在 numSides 上,畫面上就會顯示「Property ‘numSides' could be private」彈出式視窗。

  • numSides 標示為 private 後,您只能在 Dice 類別中存取。由於只有使用 numSides 的程式碼才會位於 Dice 類別內,因此可為 Dice 類別指定這個引數 private
  1. 按一下「Make ‘numSides’ ‘private」,繼續透過 Android Studio 修正建議問題。
建立 rollDice() 方法

現在您已經新增 Dice 類別至應用程式,必須更新 MainActivity 才能使用該類別。如要妥善整理程式碼,請將所有擲骰子邏輯放入一個函式中。

  1. 將點擊事件監聽器中將文字設定為 "6" 的程式碼替換為呼叫 rollDice()
1
2
3
rollButton.setOnClickListener {
rollDice()
}
  1. 因為尚未定義 rollDice(),Android Studio 會標記誤並以紅色顯示 rollDice()。滑鼠游標懸停在 rollDice() 上時,Android Studio 會顯示問題和可能的解決方法。
  1. 按一下「More actions…」開啟選單。(Mac 可按下 Option+Enter 開啟選單。)
  2. 選取「Create function ‘rollDice'」。Android Studio 會為 MainActivity 中的函式建立空白定義。
1
2
3
private fun rollDice() {
TODO("Not yet implemented")
}

建立新的 Dice 物件例項

在這個步驟中,您必須建立 rollDice() 方法並擲骰子,然後在 TextView 中顯示結果。

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

採用完善程式設計做法

團隊合作時,理想的做法是以類似的方式撰寫程式碼,讓程式碼之間保持一致。因此,Android 提供樣式指南來說明如何編寫 Android 程式碼,包括命名慣例、格式和其他遵循的建議做法。

撰寫 Android 程式碼時遵循這些指南:Android 開發人員適用的 Kotlin 樣式指南

清理您的程式碼
  1. 縮減程式碼
    將程式碼縮減成較短行的程式碼,讓程式碼更精簡。以下範例是設定 Button 點擊事件監聽器的程式碼。
1
2
3
rollButton.setOnClickListener {
rollDice()
}

由於點擊事件監聽器的操作說明只有 1 行,因此您可以縮減 rollDice() 方法呼叫,將此呼叫和大括號全部置於一行。

1
rollButton.setOnClickListener { rollDice() }
  1. 重新設定程式碼格式
    現在,您必須重新設定程式碼格式,確保程式碼符合 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)。

  • 這會更新程式碼的格式,包括空白字元、縮排等等。您可能還看不到任何變化,這很好。您的程式碼已正確格式化!
  1. 為程式碼加上註解
    為每個類別 (MainActivityDice 是您的應用程式中僅有的類別) 和您撰寫的每個方法新增註解。請在註解的開頭和結尾使用 /***/ 符號,告訴系統這不是程式碼。系統在執行程式碼時會忽略這些行。

自行練習

在應用程式中新增另一個骰子。按一下「Roll」按鈕應擲 2 個骰子。螢幕上應在 2 個不同的 TextViews 中顯示結果。

執行畫面:

程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/**
* This activity allows the user to roll a dice and view the result
* on the screen.
*/
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val rollButton: Button = findViewById(R.id.button)
val rollButton2: Button = findViewById(R.id.button2)

val resultTextView: TextView = findViewById(R.id.textView)
val resultTextView2: TextView = findViewById(R.id.textView2)

//when click button
rollButton.setOnClickListener {
// Update the screen with the dice roll
resultTextView.text = rollDice()
}
rollButton2.setOnClickListener {
// Update the screen with the dice roll
resultTextView2.text = rollDice()
}
}

/**
* Roll the dice and update the screen with the result.
*/
private fun rollDice(): String {
// Create new Dice object with 6 sides and roll it
val dice = Dice(6)
val diceRoll = dice.roll()

// return random number
return diceRoll.toString()
}
}

class Dice(private val numSides: Int) {

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