#24 剪刀石頭布(RPS)搭配跑馬燈動畫

目的:練習enum的運用

enum(列舉)真的好難懂,但感覺熟悉了之後會是一個很棒的武器!

學習重點

  • enum
  • switch
  • DispatchQueue.main.async

宣告enum

定義剪刀石頭布,新增一個型別為string的變數搭配switch來回傳每個case的內容

enum Sign {
case Rock
case Paper
case Scissors

var emoji: String {
switch self {
case .Rock:
return "✊🏻"
case .Paper:
return "🖐🏻"
case .Scissors:
return "✌🏻"
}
}

定義輸贏的結果

enum GameState {
case start
case win
case lose
case draw

var status: String {
switch self {
case .start:
return "Rock, Paper, Scissors?"
case .win:
return "You Win!!"
case .lose:
return "You Lose!!"
case .draw:
return "It's a Draw!"
}
}
}

隨機emoji

func randomSign() -> Sign {
let sign = Int.random(in: 0...2)
if sign == 0 {
return .Scissors
} else if sign == 1 {
return .Paper
} else {
return .Rock
}
}

判斷輸贏

func gameState(sign: Sign) -> GameState {
if self == sign {
return .draw
}
switch self {
case .Rock:
if sign == .Scissors {
return .win
}
case .Paper:
if sign == .Rock {
return .win
}
case .Scissors:
if sign == .Paper {
return .win
}
}
return .lose
}

updateUI

func updateUI(state: GameState) {
resultLbl.text = state.status
switch state {
case .start:
view.backgroundColor = .green
signLbl.text = "🎃"

paperBtn.isHidden = false
rockBtn.isHidden = false
scissorBtn.isHidden = false

paperBtn.isEnabled = true
rockBtn.isEnabled = true
scissorBtn.isEnabled = true
againBtn.isEnabled = true
case .win:
view.backgroundColor = .blue
case .lose:
view.backgroundColor = .gray
case .draw:
view.backgroundColor = .orange
}
}

跑馬燈動畫

利用CATransition做出動畫效果,搭配Timer讓動畫持續Loop,在這邊有稍微卡住一下,因為它會無限Loop,後來爬了一下文,發現DispatchQueue可以解決問題,DispatchQueue.main.asyncAfter 可以讓程式碼延後執行,所以我讓Timer.invalidate() 延後1.5秒再執行已達到讓動畫只持續1.5秒的效果

let emoji = ["✌🏻", "✊🏻", "🖐🏻"]
var index = 0
func runEmoji() {
index = (index + 1) % emoji.count
let transition = CATransition()
transition.type = .fade
signLbl.text = emoji[index]
signLbl.layer.add(transition, forKey: "runEmoji")
}
func play(userSign: Sign) {
let computerSign = randomSign()
let gameState = userSign.gameState(sign: computerSign)
timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { _ in
self.runEmoji()
}

DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
self.timer?.invalidate()
self.signLbl.text = computerSign.emoji
self.updateUI(state: gameState)
}


paperBtn.isEnabled = false
rockBtn.isEnabled = false
scissorBtn.isEnabled = false

paperBtn.isHidden = true
rockBtn.isHidden = true
scissorBtn.isHidden = true
switch userSign {
case .Rock:
rockBtn.isHidden = false
case .Paper:
paperBtn.isHidden = false
case .Scissors:
scissorBtn.isHidden = false
}

}

Demo

--

--