#12 桌球計分板(Scoreboard)
Published in
9 min readJul 20, 2022
實作 Simple Table Tennis Scoreboard 這個 APP 的功能
實作步驟
- 先安裝 Simple Table Tennis Scoreboard 並了解這個 APP 的操作功能
- 開始規畫程式需要利用到的參數
var leftScoresValue = 0 // 目前左邊的分數
var rightScoresValue = 0 // 目前右邊的分數
var leftWinsValue = 0 // 目前左邊贏的局數
var rightWinsValue = 0 // 目前右邊贏的局數
var played = 0 // 目前已比完的局數
var states = Stack() // 可以回溯的 Stack 裡面可以存下每一個狀態 State (快照)
var leftName = "player 1" // 目前左邊的玩家名稱
var rightName = "player 2" // 目前右邊的玩家名稱struct State {
let leftScoresValue: Int
let rightScoresValue: Int
let leftWinsValue: Int
let rightWinsValue: Int
let played: Int
let leftServeLabelValue: Bool
let rightServeLabelValue: Bool
let leftName: String
let rightName: String
}
3. 規畫畫面並拉出元件的IBOutlet
@IBOutlet weak var leftScores: UIButton!
@IBOutlet weak var rightScores: UIButton!
@IBOutlet weak var leftWins: UIButton!
@IBOutlet weak var rightWins: UIButton!
@IBOutlet weak var leftServeLabel: UILabel!
@IBOutlet weak var rightServeLabel: UILabel!
@IBOutlet weak var leftNameText: UITextField!
@IBOutlet weak var rightNameText: UITextField!
4. 拉出元件的IBAction,分別對應畫面上按下元件的動作
@IBAction func rewind(_ sender: Any) {
if states.peek() != nil {
let state = states.pop()
leftScoresValue = state.leftScoresValue
rightScoresValue = state.rightScoresValue
leftWinsValue = state.leftWinsValue
rightWinsValue = state.rightWinsValue
played = state.played
leftServeLabel.isHidden = state.leftServeLabelValue
rightServeLabel.isHidden = state.rightServeLabelValue
leftNameText.text = state.leftName
rightNameText.text = state.rightName
updateAllScores()
}
}@IBAction func changeSide(_ sender: Any) {
snapshot()
swapName()
toggleServe()
(leftWinsValue, rightWinsValue) = (rightWinsValue, leftWinsValue)
(leftScoresValue, rightScoresValue) = (rightScoresValue, leftScoresValue)
updateAllScores()
}@IBAction func reset(_ sender: Any) {
played = 0
leftServeLabel.isHidden = false
rightServeLabel.isHidden = true
leftScoresValue = 0
rightScoresValue = 0
leftWinsValue = 0
rightWinsValue = 0
leftNameText.text = leftName
rightNameText.text = rightName
updateAllScores()
}@IBAction func addLeftScore(_ sender: Any) {
snapshot()
played += 1
leftScoresValue += 1
updateAllScores()
checkStatus()
}@IBAction func addRightScore(_ sender: Any) {
snapshot()
played += 1
rightScoresValue += 1
updateAllScores()
checkStatus()
}@IBAction func addLeftWin(_ sender: Any) {
snapshot()
leftWinsValue += 1
updateAllScores()
}@IBAction func addRightWin(_ sender: Any) {
snapshot()
rightWinsValue += 1
updateAllScores()
}@IBAction func updateLeftName(_ sender: Any) {
leftName = leftNameText.text ?? ""
}@IBAction func updateRightName(_ sender: Any) {
rightName = rightNameText.text ?? ""
}
5. 依桌球比賽的規則,寫下每次動作需要檢查的函式 checkStatus()
func checkStatus() {
if leftScoresValue == 11 && rightScoresValue < 10 {
leftWinsValue += 1
updateAllScores()
clearScores()
return
}
if rightScoresValue == 11 && leftScoresValue < 10 {
rightWinsValue += 1
updateAllScores()
clearScores()
return
}
if (leftScoresValue < 10 && rightScoresValue < 10) ||
(leftScoresValue >= 10 && rightScoresValue < 10) ||
(leftScoresValue < 10 && rightScoresValue >= 10) {
if played % 2 == 0 {
toggleServe()
}
} else if leftScoresValue >= 10 && rightScoresValue >= 10 {
if (leftScoresValue - rightScoresValue) > 1 {
leftWinsValue += 1
updateAllScores()
clearScores()
return
}
if (rightScoresValue - leftScoresValue) > 1 {
rightWinsValue += 1
updateAllScores()
clearScores()
return
}
toggleServe()
}
}
6. 存下每次狀態的快照函式 snapshot(),以便在呼叫 rewind 時可以回復前一個狀態
func snapshot() {
let state = State(leftScoresValue: leftScoresValue, rightScoresValue: rightScoresValue, leftWinsValue: leftWinsValue, rightWinsValue: rightWinsValue, played: played, leftServeLabelValue: leftServeLabel.isHidden, rightServeLabelValue: rightServeLabel.isHidden, leftName: leftName, rightName: rightName)states.push(state)
}
7. 設定啟始畫面為橫向顯示
override func viewDidLoad() {
super.viewDidLoad()
let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
reset(0)
}override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .landscapeLeft
}override var shouldAutorotate: Bool {
return true
}
成果
GitHub
參考
心得
實作出來的程式跟 Simple Table Tennis Scoreboard 已經功能幾乎都達到成了,而且還比它多了可以 寫上玩家名字 的功能,唯獨少了可了更換顏色的功能而已。整個開發都只有從原本的程式,直接復刻出來的,在開發過程中,一直不斷地增刪參數/規畫各類函式,也歡迎大家能回報問題給我。