#18 撞球計分板(Scoreboard)
Published in
15 min readMar 22, 2023
製作撞球14-1規則的計分板
SetViewController 資料傳遞到計分板畫面
import UIKit
class SetViewController: UIViewController {
@IBOutlet weak var playerATextField: UITextField!
@IBOutlet weak var playerBTextField: UITextField!
@IBOutlet weak var gameScoreTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
//點選空白處收鍵盤
@IBAction func closeKeyboard(_ sender: Any) {
view.endEditing(true)
}
//鍵盤按下return鍵收鍵盤
@IBAction func returnCloseKeyboard(_ sender: Any) {
}
//segue傳遞資料到計分板頁面
@IBSegueAction func showResult(_ coder: NSCoder) -> ScoreViewController? {
let setPlayerAName = String(playerATextField.text!)
let setPlayerBName = String(playerBTextField.text!)
let setGameScore = Int(gameScoreTextField.text!)
let controller = ScoreViewController(coder: coder)
controller?.playerAName = setPlayerAName
controller?.playerBName = setPlayerBName
controller?.gameScore = setGameScore
return controller
}
ScoreViewController 計分板介面
計時功能
var timer: Timer?
var counter = 0
override func viewDidLoad() {
super.viewDidLoad()
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
}
@objc func updateTime(){
counter += 1
timeLabel.text = formatedTime(counter)
}
//顯示時間格式
func formatedTime(_ seconds: Int) -> String {
var hourSting = String()
var minString = String()
var secString = String()
if seconds / 3600 == 0 {
hourSting = "00"
} else if (seconds / 3600 > 0 && seconds / 3600 < 10 ){
hourSting = "0\(seconds / 3600)"
} else {
hourSting = "\(seconds / 3600)"
}
if seconds / 60 == 0 {
minString = "00"
} else if (seconds / 60 > 0 && seconds / 60 < 10){
minString = "0\(seconds / 60)"
} else {
minString = "\(seconds / 60)"
}
if seconds % 60 == 0 {
secString = "00"
} else if (seconds % 60 < 10){
secString = "0\(seconds % 60)"
} else {
secString = "\(seconds % 60)"
}
return "比賽時間:\n\(hourSting):\(minString):\(secString)"
}
計分功能
//A隊加分
@IBAction func addScoreA(_ sender: Any) {
//單局雙方合計未達13分直接計分
if scoreA + scoreB < 13 {
scoreA += 1
playerABallView.frame.origin.y = CGFloat(60 + 40 * scoreA)
//Array紀錄得分扣分
getScoreArray.append(playerAScore)
} else if scoreA + scoreB < 14 {
//單局合計14分 計算雙方總分並顯示
scoreA += 1
playerABallView.frame.origin.y = CGFloat(60 + 40 * scoreA)
roundScoreA = roundScoreA + scoreA - foulScoreA
roundScoreB = roundScoreB + scoreB - foulScoreB
scoreALabel.text = roundScoreA.formatted()
scoreBLabel.text = roundScoreB.formatted()
getScoreArray.append(playerAScore)
}
//有設定獲勝分數 達標後會有獲勝提示
if gameScore != nil && gameScore > 0{
if scoreA + scoreB < 14 && (roundScoreA + scoreA - foulScoreA) == gameScore {
showWinner()
} else if scoreA + scoreB == 14 && roundScoreA == gameScore {
showWinner()
}
}
//B隊加分
@IBAction func addScoreB(_ sender: Any) {
if scoreA + scoreB < 13 {
scoreB += 1
playerBBallView.frame.origin.y = CGFloat(60 + 40 * scoreB)
getScoreArray.append(playerBScore)
} else if scoreA + scoreB < 14 {
scoreB += 1
playerBBallView.frame.origin.y = CGFloat(60 + 40 * scoreB)
roundScoreA = roundScoreA + scoreA - foulScoreA
roundScoreB = roundScoreB + scoreB - foulScoreB
scoreALabel.text = roundScoreA.formatted()
scoreBLabel.text = roundScoreB.formatted()
getScoreArray.append(playerBScore)
}
if gameScore != nil && gameScore > 0{
if scoreA + scoreB < 14 && (roundScoreB + scoreB - foulScoreB) == gameScore {
showWinner()
} else if scoreA + scoreB == 14 && roundScoreB == gameScore {
showWinner()
}
}
}
//A隊犯規扣分
@IBAction func reduceScoreA(_ sender: Any) {
if scoreA + scoreB != 14 {
foulScoreA += 1
foulALabel.text = foulScoreA.formatted()
getScoreArray.append(playerAFoul)
}
}
//B隊犯規扣分
@IBAction func reduceScoreB(_ sender: Any) {
if scoreA + scoreB != 14 {
foulScoreB += 1
foulBLabel.text = foulScoreB.formatted()
getScoreArray.append(playerBFoul)
}
}
下一局按鍵
14-1打完球檯上14顆球 重新排球計分進入下一局
@IBAction func changeNextGame(_ sender: Any) {
//達到雙方進球總和14分 重置單局分數及得分圖示初始位置
if scoreA + scoreB == 14 {
scoreA = 0
scoreB = 0
foulScoreA = 0
foulScoreB = 0
rounds += 1
foulALabel.text = foulScoreA.formatted()
foulBLabel.text = foulScoreB.formatted()
playerABallView.frame.origin.y = CGFloat(60)
playerBBallView.frame.origin.y = CGFloat(60)
totalScoreAArray.append(roundScoreA)
totalScoreBArray.append(roundScoreB)
getScoreArray.removeAll()
}
}
恢復上一步功能
@IBAction func rewind(_ sender: Any) {
//利用Array.popLast找出最後一步的操作
let lastScore = getScoreArray.popLast()
//判斷條件後 恢復上一步
switch lastScore {
case playerAScore:
if scoreA + scoreB == 14 {
scoreA -= 1
playerABallView.frame.origin.y = CGFloat(60 + 40 * scoreA)
roundScoreA = totalScoreAArray[rounds]
roundScoreB = totalScoreBArray[rounds]
scoreALabel.text = roundScoreA.formatted()
scoreBLabel.text = roundScoreB.formatted()
} else {
scoreA -= 1
playerABallView.frame.origin.y = CGFloat(60 + 40 * scoreA)
}
case playerBScore:
if scoreA + scoreB == 14 {
scoreB -= 1
playerBBallView.frame.origin.y = CGFloat(60 + 40 * scoreB)
roundScoreA = totalScoreAArray[rounds]
roundScoreB = totalScoreBArray[rounds]
scoreALabel.text = roundScoreA.formatted()
scoreBLabel.text = roundScoreB.formatted()
} else {
scoreB -= 1
playerBBallView.frame.origin.y = CGFloat(60 + 40 * scoreB)
}
case playerAFoul:
foulScoreA -= 1
foulALabel.text = foulScoreA.formatted()
case playerBFoul:
foulScoreB -= 1
foulBLabel.text = foulScoreB.formatted()
default:
break
}
獲勝提示
func showWinner(){
var winnerName = String()
//判斷雙方總分
if (roundScoreA + scoreA - foulScoreA) > (roundScoreB + scoreB - foulScoreB) {
winnerName = playerALabel.text!
} else {
winnerName = playerBLabel.text!
}
//使用UIAlert
let controller = UIAlertController(title: "恭喜\(winnerName)獲勝", message: "🏆🏆🏆🏆🏆🏆", preferredStyle: .alert)
let okAction = UIAlertAction(title: "重置比賽", style: .default){
_ in
//重置比賽
self.resetGame()
}
controller.addAction(okAction)
present(controller, animated: true)
}
重置比賽功能
func initialUI(){
//SetViewController傳遞的資料如果空白 設為預設值
if playerAName != "" {
playerALabel.text = playerAName
} else {
playerALabel.text = "A(先攻)"
}
if playerBName != ""{
playerBLabel.text = playerBName
} else {
playerBLabel.text = "B(後攻)"
}
if gameScore != nil {
gameScoreLabel.text = "獲勝總分:\( gameScore!.formatted())"
} else {
gameScoreLabel.text = "單局計分"
}
}
//重置功能
func resetGame(){
initialUI()
rounds = 0
scoreA = 0
scoreB = 0
foulScoreA = 0
foulScoreB = 0
roundScoreA = 0
roundScoreB = 0
totalScoreAArray = [0]
totalScoreBArray = [0]
scoreALabel.text = roundScoreA.formatted()
scoreBLabel.text = roundScoreB.formatted()
foulALabel.text = foulScoreA.formatted()
foulBLabel.text = foulScoreB.formatted()
playerABallView.frame.origin.y = CGFloat(60)
playerBBallView.frame.origin.y = CGFloat(60)
getScoreArray.removeAll()
}
//建立重置UIAlert提示
@IBAction func reset(_ sender: Any) {
let controller = UIAlertController(title: "重置比賽", message: "確定要重置比賽", preferredStyle: .alert)
let okAction = UIAlertAction(title: "確定", style: .default){ _ in
self.resetGame()
}
controller.addAction(okAction)
let cancelAction = UIAlertAction(title: "取消", style: .cancel)
controller.addAction(cancelAction)
present(controller, animated: true)
}
作品程式碼