#35 骰子轉轉轉,比大小,骰子吹牛

Rose
彼得潘的 Swift iOS / Flutter App 開發教室
10 min readMay 1, 2021

製作骰子猜大小的遊戲,6顆骰子加總,玩家與系統比大小

使用元件:

  • 骰子圖:Image View
  • 點數加總:Label
  • 資產統計:Label
  • 加值按鈕:Button
  • 比大小選項:Segmented Control
  • 下注金額顯示:Label
  • 增減下注金額:Stepper
  • 下注按鈕:Button
  • 遊戲訊息:Text View

功能包含:

  1. 能夠顯示贏錢輸錢,現有金額等等
  2. 加上一些生動的音效, 例如贏的時候會有勝利的聲音;輸的時候會有悲哀的叫聲;骰子轉動時會有骰子聲;加值時會有收銀的聲音
  3. 開始賭骰子後需要等骰子聲落地才出現結果,且此時按鈕不能再按
  4. 文字訊息欄可不斷更新,可以拖動觀看舊訊息
  5. 可以賭大、賭小、賭21點,賠率不同
  6. 可以豪賭,最高一次可下注10000美金
  7. 可以加值,一次加值1000美金

加入1~6點的自製骰子圖

增減下注金額 加入 Stepper

排版完成

拉 IBOutlet 連結畫面與程式

將多個元件變成 Array 的 Outlet Collection

這裡有個重點 把多顆骰子圖連到同一個 IBoutlet

原本是六顆骰子要拉六個IBOutlet,比方下圖有六顆骰子,為了從程式控制每顆骰子,我們需要拉六個IBoutlet,產生六個變數

@IBOutlet weak var dice1Images: UIButton!
@IBOutlet weak var dice2Images: UIButton!
@IBOutlet weak var dice3Images: UIButton!
@IBOutlet weak var dice4Images: UIButton!
@IBOutlet weak var dice5Images: UIButton!
@IBOutlet weak var dice6Images: UIButton!

但是要做到這樣的功能,更適合的方式是存放在 array ,並搭配 for in 迴圈。比方想同時擲六顆骰子時,只要以 for in 跑六次,即可設定每顆骰子的數字。

IBOutlet 有個兄弟名字叫 outlet collection。接下來就讓我們透過它將六顆骰子存在 Array中。

(1)點選左上第一顆骰子,拉線到程式碼

(2)將 Connection 改成 Outlet Collection,Name 欄位輸入名稱 diceImages

(3)產生diceImages,型別為 [UIImageView]!,因此它是個存放 UIImageView 的 array。

@IBOutlet var diceImages: [UIImageView]!

(4) 將其它骰子圖 連線到剛剛產生的變數diceImages。

由於 array 有順序,所以東西存放在 array 的順序,將依據當初我們拉線的順序。

(5)最後檢查是不是有全部連結成功

(6) 查看 outlet collection array 裡成員的順序。

我們可切換到 controller 的 Connections inspector 頁面查詢。如下圖所示,當我們將游標移到第二個 Button,將看到它對應的骰子,因此 diceButtons[1] 是右上的骰子。

骰子圖片設定陣列

let diceArray = ["Dice1","Dice2","Dice3","Dice4","Dice5","Dice6"]

載入 AVFoundation

因為有用到輸贏音效所以要載入 AVFoundation

import AVFoundation

播放聲音

func playSound(name: String) {
//播放各種音效
if let url = Bundle.main.url(forResource: name, withExtension: "mp3"){
self.player = try? AVAudioPlayer(contentsOf: url)
self.player?.play()
}
}

Function 設定

func showtextBottom(){
statusText.scrollRangeToVisible(NSRange(location: .max, length: 0))
}

func gamblemoneyUpdate(){
gambleMoney.text = "此次下注:" + String(format: "%.f", gamblemoneyStepper.value) + "美金"
}

func moneyUpdate(){
moneyText.text = "總賭金:" + String(money) + "美金"
}
//播放各種音效
func playSound(name: String) {
if let url = Bundle.main.url(forResource: name, withExtension: "mp3"){
self.player = try? AVAudioPlayer(contentsOf: url)
self.player?.play()
}
}
// 輸贏判斷
func win(Odds: Double){
self.playSound(name: "win")
let gamoney = Int(Odds * self.gamblemoneyStepper.value)
self.money += gamoney
self.moneyUpdate()
self.statusText.text += String("\n恭喜您贏了\(gamoney)美金,總賭金\(self.money)美金")
showtextBottom()
}

func lose(){
self.playSound(name: "lose")
let gamoney = Int(self.gamblemoneyStepper.value)
self.money -= gamoney
self.moneyUpdate()
self.statusText.text += String("\n您輸了\(gamoney)美金,總賭金\(self.money)美金")
showtextBottom()
}

拉下注、加值按鈕、增減金額IBAction

下注按鈕

@IBAction func buttonPressed(_ sender: Any) {

//優先判斷賭金是否足夠支付下注金額
if Int(gamblemoneyStepper.value) > money {
self.statusText.text = String("賭金不足!\n") + self.statusText.text
}else{
//通過判斷賭金後,為了禁止連續點擊,停用按鈕一段時間
self.startButton.isEnabled = false
//每次按下按鈕時都先把總合歸零,並開始跑骰子聲
var diceSum = 0
self.playSound(name: "dice_shake")
//時間間隔起算
let diceTime:TimeInterval = 1.42
DispatchQueue.main.asyncAfter(deadline:DispatchTime.now() + diceTime)
{

//跑隨機骰子及計算總和
for i in 0...5 {
let diceNum = Int.random(in: 1...6)
diceSum += diceNum
self.diceImages[i].image = UIImage(named: self.imageNames[diceNum-1])
}
//將總和顯示在畫面上
self.dicesumText.text = String(diceSum) + "點"
//開始判斷大小21點情形
switch diceSum
{
case 6...20:
if self.gambleSelecter.selectedSegmentIndex == 0 {
self.win(Odds: 2)
}else{
self.lose()
}
case 22...36:
if self.gambleSelecter.selectedSegmentIndex == 2 {
self.win(Odds: 2)
}else{
self.lose()
}
default:
if self.gambleSelecter.selectedSegmentIndex == 1 {
self.win(Odds: 10)
}else{
self.lose()
}
}
self.startButton.isEnabled = true
}
}
}

搖晃手機下注

override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
//放入手機搖晃後執行的程式碼,所以會跟buttonPressed的內容一樣。
}

在TextView最前面加上文字並換行

//在字串""中加上\n代表換行,後面加上「自己」,就可以在最前面新增文字且換行
textView.text = String("要新增的文字&狀態\n") + textView.text

在TextView底部加上文字,並使底部維持可見,顯示底部

操作動畫

--

--

Rose
彼得潘的 Swift iOS / Flutter App 開發教室

Coding & Design 一直在學習的路上,從未停止,一有空檔就會摸摸我的兔子🐰