【Swift 開發】#1 輪盤遊戲 Roulette

Yesa
海大 SwiftUI iOS / Flutter App 程式設計
7 min readMar 13, 2023

「生命中的每一個選擇都有機率和風險,但不要害怕失敗,因為從失敗中學到的經驗和教訓,往往是實現成功的關鍵。」 — — — ChatGPT 機率與人生

My Roulette App Icon

成品目標:

會轉動的輪盤、簡潔的下注區、紀錄最高分數

練習目標:

建立 func 函式、定義 struct 型別、使用 ForEach 加入元件

新增畫面元件來精簡程式,並利用 @Binding 參考資料來源

遊戲規則:

介紹程式:

設計籌碼結構時發生了這個錯誤

沒有遵從 Hashable 的 CGPoint 資料無法直接使用

參考彼得潘的教學解決了這個問題

struct Chip: Hashable {    
let id = UUID()
let num : [Int]
let value : Int
let x: CGFloat
let y: CGFloat

func hash(into hasher: inout Hasher) {
hasher.combine(id)
hasher.combine(num)
hasher.combine(value)
hasher.combine(x)
hasher.combine(y)
}

static func == (lhs: Chip, rhs: Chip) -> Bool {
return lhs.id == rhs.id && lhs.num == rhs.num && lhs.value == rhs.value && lhs.x == rhs.x && lhs.y == rhs.y
}
}

使用 UIScreen.main.bounds 來判斷畫面方向,調整排版模式

if UIScreen.main.bounds.width > UIScreen.main.bounds.height {
HStack {
...
}
}else{
VStack {
...
}
}
顯示不同方向的排列方式

利用 formatter.numberStyle = .currency 呈現金錢效果

當錢不夠支付籌碼時,剩餘金額會紅黑閃爍,提醒玩家資金不足

let moneyFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
return formatter
}()

...

if enoughMoney {
Text("Money: \(NSNumber(value: money), formatter: moneyFormatter)")
.font(.headline)
}else{
Text("Money: \(NSNumber(value: money), formatter: moneyFormatter)")
.font(.headline)
.foregroundColor(color)
.onAppear {
withAnimation(Animation.easeInOut(duration: 0.5).repeatForever()) {
color = Color.red
}
}
.onDisappear {
withAnimation {
color = Color.black
}
}
}
沒錢下注啦

利用黃色小圈圈增加下注選擇

if isOn {
ForEach((-5...6), id: \.self){ i in
let x = i * 50 - 25
let num = 3 * (i + 5) + 1
CircleView(x: CGFloat(x), y: 55)
.onTapGesture { putChip(num: [num,num+1,num+2], x: x, y: 55, xScope: 8, yScope: 8) }
...
...
}
增加邊角下注方式

內建沒有 Triangle() 怎麼辦,問好朋友GPT就對了

struct Triangle: Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to: CGPoint(x: rect.midX, y: rect.minY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.closeSubpath()
return path
}
}

部分函式介紹

//藉由輪盤停下的角度,回傳旋轉結果
func getNum(angle: Int) -> Int {
return rouletteNum[Int(Double(angle % 360) / (360.0 / 37.0))]
}

//將籌碼的座標加上局部隨機性,避免重疊,增加可視性
func putChip(num: [Int], x: Int, y: Int, xScope: Int, yScope: Int) {
isOn.toggle()
chips.append(Chip(num: num, value: chipChoose, x: CGFloat(x+Int.random(in: -xScope...xScope)), y: CGFloat(y+Int.random(in: -yScope...yScope))))
payment += chipChoose
money -= chipChoose
}
實測輪盤轉動與籌碼落點位置

--

--

Yesa
海大 SwiftUI iOS / Flutter App 程式設計

A student without a MacBook, trying to learn the Swift language with an iPad.