#80 創作 iOS App 擲骰子遊戲 — 十八啦!

小時候家人每逢除夕夜都聚在一起玩撲克牌和骰子遊戲,
其中又以十八啦最為熱鬧刺激,
下注後撒骰子,三顆骰子中要有兩顆點數相同、第三顆骰子不相同的點數即為分數,之後再與莊家比大小。比莊家大,可以贏得賭注;比莊家小,就輸掉賭注。若三顆骰子一模一樣都是六,加起來點數共18是全場通殺。因此擲骰子時會習慣吆喝「洗芭樂!」(台語意思的「十八啦!」)來增加士氣。

這次本來打算莊家和玩家們分別不同的畫面,
想要設計多人遊玩的模式,可以各別傳遞手機來下注並擲骰子,但看來畫面傳遞的部分還需要再學習…可能留待之後優化 App 了

這次使用到的技巧有:

1. 漸層設計的背景

2. 頁面間傳遞資料(記得 Storyboard ID 也要設定,可和 ViewController 同名)

3. 同時控制三顆骰子取亂數的 Outlet Collection

4. 播放擲骰子音效、換人音效、遊戲結束音效

5. 顯示警告訊息的 UIAllertController

操作細節:

首先首頁輸入姓名及籌碼,利用頁面間的資訊傳遞匯入到第二頁:

//按下Play按鈕傳遞資料
@IBAction
func playButton(_ sender: UIButton) {
performSegue(withIdentifier: "showInfo", sender: UIButton.self)
}
@IBSegueAction func showInfo(_ coder: NSCoder) -> playViewController? {
let controller = playViewController(coder: coder)
let gamerName = gamerNameText.text!
let tokenNumer = Double((tokenNumberText.text!)) ?? 0
controller?.name = gamerName
controller?.token = tokenNumer
return controller
}

到了主畫面,擲骰子的功能寫成一個 function。這裏採用先將骰子數目取亂數,再呈現成骰子的 Image,是因後續要取出骰子點數,在判斷輸贏時使用。試過先將 Image名稱做 Array 取亂數,後續要取出數字較麻煩,因此採取現在的方式。

func rollDice(){
//三顆骰子綁成 Outlet collection後利用number取亂數,再呈現成圖片
for _ in diceImages{
number0 = Int.random(in: 1...6)
diceImages[0].image = UIImage(named: "\(number0!)")
number1 = Int.random(in: 1...6)
diceImages[1].image = UIImage(named: "\(number1!)")
number2 = Int.random(in: 1...6)
diceImages[2].image = UIImage(named: "\(number2!)")
}

//搖骰子音效 let diceSound = Bundle.main.url(forResource: "rolldice", withExtension: "mp3")!
player = AVPlayer(url: diceSound)
player?.play()
}
}

接著分成 「莊家畫面 bankerRound」及「玩家畫面 playerRound」,分別將兩人畫面分開來做處理,每次使用「換人」按鈕時,切換左右畫面。

func bankerRound(){
playerTitleLabel.isHidden = false
playerTitleLabel.text = name!
...(太長了不一一列舉)
bankerChangeButton.isHidden = true
}

判斷骰子點數,其中兩顆骰子點數一樣時,第三顆不同點數則為結果。沒有點數時顯示警告視窗,並重骰骰子。

func bankerDiceResult(){if (number0 == number1) && (number0 != number2)
{ bankerResult = number2
bankerResultLabel.isHidden = false
bankerResultLabel.text = "點數:\(bankerResult!)"
bankerRollButton.isHidden = true
bankerChangeButton.isHidden = false
} else if (number1 == number2) && (number1 != number0)
{ bankerResult = number0
bankerResultLabel.isHidden = false
bankerResultLabel.text = "點數:\(bankerResult!)"
bankerRollButton.isHidden = true
bankerChangeButton.isHidden = false
} else if (number0 == number2) && (number0 != number1)
{ bankerResult = number1
bankerResultLabel.isHidden = false
bankerResultLabel.text = "點數:\(bankerResult!)"
bankerRollButton.isHidden = true
bankerChangeButton.isHidden = false
} else {
let resultController = UIAlertController(title: "沒有點數!", message: "重來一次吧", preferredStyle: .alert)
let okAction = UIAlertAction(title: "再骰", style: .default, handler: nil)
resultController.addAction(okAction)
present(resultController, animated: true, completion: nil)
bankerRollButton.setTitle("再骰一次", for: .normal)
}
}

計算籌碼,若贏得比賽,玩家贏取一倍下注金,輸了則輸一倍。若有 18啦(三顆相同為6),則贏得兩倍下注金。

func tokenUpdate(){
if let playerResult = playerResult,
let bankerResult = bankerResult{
if eighteenla == true{
}
else if playerResult > bankerResult{
playerToken = playerToken! + bet
bankerToken = bankerToken! - bet
let Controller = UIAlertController(title: "你贏了!", message: "可以拿到一倍下注金 目前持有\(playerToken!)", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
Controller.addAction(okAction)
present(Controller, animated: true, completion: nil)
bankerTokenLabel.text = "\(bankerToken!)"
playerTokenLabel.text = "\(playerToken!)"
}

else if playerResult < bankerResult{
playerToken = playerToken! - bet
bankerToken = bankerToken! + bet
let Controller = UIAlertController(title: "你輸了!", message: "籌碼扣掉一倍下注金 目前持有\(playerToken!)", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
Controller.addAction(okAction)
present(Controller, animated: true, completion: nil)
bankerTokenLabel.text = "\(bankerToken!)"
playerTokenLabel.text = "\(playerToken!)"
}

else if playerResult == bankerResult{
let Controller = UIAlertController(title: "平手!", message: "籌碼不變 目前持有\(playerToken!)", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
Controller.addAction(okAction)
present(Controller, animated: true, completion: nil)
bankerTokenLabel.text = "\(bankerToken!)"
playerTokenLabel.text = "\(playerToken!)"
}
}
}

莊家擲骰子時進行以上動作:

@IBAction func bankerRollDice(_ sender: Any) {
rollDice()
bankerDiceResult()
tokenUpdate()
}

期間大約來回執行了數十次吧!確定所有細節都合乎期待,設計遊戲真的好累啊!但也很有成就感,迫不及待要給姪子姪女們試試看~~

p.s. 還是有個 bug — 玩家應該要在莊家擲骰子前就下注的!但我懶得修了,不想再聽到任何骰子聲了啊~~

實際遊戲操作如下:

--

--