携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情。
在本章中,我们继续完成使用SwiftUI
搭建一个剪刀石头布App。
交互逻辑
我们继续来完成石头剪刀布的逻辑部分,本章可能对于初学者有点难度,我们一步一步来。
系统出牌方法
首先是系统出牌部分,我们可以使用随机数来获得数组中的数据来作为系统出牌结果,示例:
// 随机猜拳方法
func randomPush() {
let index = Int.random(in: 0 ... 2)
computerPushImage = gameModels[index]
gameTimes -= 1
}
上述代码中,我们通过random
函数获得0到2
的随机数值,然后把computerPushImage
系统出牌结果赋值为从gameModels
数组中随机取的的结果,并且每次出牌后gameTimes
游戏次数就会减少。
然后我们在立即猜拳的操作中增加点击交互,示例:
// 立即猜拳
func playGame() -> some View {
Text("立即猜拳")
.font(.system(size: 17))
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 10, maxHeight: 32)
.padding()
.foregroundColor(.white)
.background(Color(red: 51 / 255, green: 51 / 255, blue: 51 / 255))
.cornerRadius(8)
.onTapGesture {
if isSelected {
randomPush()
}
}
}
上述代码中,我们给playGame
视图中的Text
添加了onTapGesture
修饰符,当我们点击时判断下用户是否了出牌,选择后我们才调用系统随机猜拳的方法。
猜拳结果判断
有了系统猜拳后,在用户选择出牌后,我们需要合系统出牌进行对比,看看谁赢,我们这里创建一个方法来判断猜拳结果。
首先要声明3个变量
来展示所需的结果。示例:
@State var computerWinCount: Int = 0
@State var winName: String = ""
@State var winMessage: String = ""
上述代码中,我们声明了三个变量computerWinCount
计算机赢的次数,winName
谁赢,winMessage
结果的描述信息。
然后我们创建一个方法来判断猜拳结果。示例:
// 判断最终猜拳结果
func showWinner() {
if computerPushImage == "rock" && selectedImage == "paper" || computerPushImage == "paper" && selectedImage == "scissors" || computerPushImage == "scissors" && selectedImage == "rock" {
winName = "你输了"
computerWinCount += 1
winMessage = "你还有" + String(gameTimes) + "次机会"
} else if computerPushImage == selectedImage {
gameTimes += 1
winName = "平手"
winMessage = "你还有" + String(gameTimes) + "次机会"
} else {
winName = "你赢了"
winMessage = "你还有" + String(gameTimes) + "次机会"
}
}
上述代码中,我们创建了一个方法showWinner
。
我们判断computerPushImage
系统出牌和selectedImage
用户选择出牌的结果,如果计算机赢了,我们给winName
赋值,告知赢方。
若计算机赢了,computerWinCount
计算机赢的次数加1,且winMessage
拼接展示剩余的gameTimes
游戏次数。
若两者平手,则gameTimes
游戏次数加1,且同样展示赢方和剩余的gameTimes
游戏次数。
若用户赢了,也同样展示赢方和剩余的gameTimes
游戏次数。
然后我们在playGame
立即猜拳的视图中,点击操作时调用判断猜拳结果的方法,示例:
// 立即猜拳
func playGame() -> some View {
Text("立即猜拳")
.font(.system(size: 17))
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 10, maxHeight: 32)
.padding()
.foregroundColor(.white)
.background(Color(red: 51 / 255, green: 51 / 255, blue: 51 / 255))
.cornerRadius(8)
.onTapGesture {
if isSelected {
randomPush()
showWinner()
}
}
}
游戏是否结束
有了系统猜拳的方法后,由于我们有几种规则:一局定胜负、三局两胜、五局三胜。
因此我们在每次猜拳后,还要根据游戏次数规则,判断游戏最终是否结束。
首先需要声明一个游戏的总次数参数,然后和系统赢的次数computerWinCount
做对比,示例:
@State var gameTotal: Int = 1
@State var isShowWinner: Bool = false
我们声明了一个变量gameTotal
,用来存储游戏总次数,再声明了一个Bool
变量isShowWinner
,用来最后确定是否展示结果。
下一步还需要在系统规则中根据用户选择的游戏规则,对gameTotal
游戏总次数进行赋值,示例:
// 规则
func ruleView() -> some View {
Menu {
Button("一局定胜负") {
self.gameTimes = 1
self.ruleName = "一局定胜负"
self.gameTotal = 1
}
Button("三局两胜") {
self.gameTimes = 3
self.ruleName = "三局两胜"
self.gameTotal = 3
}
Button("五局三胜") {
self.gameTimes = 5
self.ruleName = "五局三胜"
self.gameTotal = 5
}
} label: {
Label(ruleName, systemImage: "slider.horizontal.3")
.foregroundColor(.gray)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 10, maxHeight: 60)
.background(Color(.systemGray6))
.cornerRadius(8)
}
}
这时,我们就有了3个参数
来记录游戏玩的过程:gameTotal
游戏总次数,gameTimes
游戏剩余次数,computerWinCount
计算机赢的次数。
我们需要有个方法判断游戏是否结束,示例:
// 判断游戏是否结束
func isEndGame() {
if gameTimes == 0 {
if gameTotal == 5 && computerWinCount == 3 || gameTotal == 3 && computerWinCount == 2 || gameTotal == 1 && computerWinCount == 1 {
computerWinCount = 0
gameTimes = gameTotal
winName = "计算机赢了"
winMessage = "游戏结束"
isShowWinner = true
} else {
computerWinCount = 0
gameTimes = gameTotal
winName = "你赢了"
winMessage = "游戏结束"
isShowWinner = true
}
} else {
isShowWinner = true
}
}
上述代码中,我们创建了一个方法isEndGame
,用来判断游戏是否结果。
判断规则首要判断gameTimes
游戏剩余次数是否为0
,如果游戏剩余次数为0
,则代表游戏结束。
游戏结束时,我们还需要判断gameTotal
游戏总次数和computerWinCount
计算机赢的次数的关系,如果满足规则,则代表计算机赢了。
这时我们需要重置计算机赢的次数computerWinCount``为0
,并且重置剩余的游戏次数gameTimes
等于游戏总次数,并告知winName
最终结果谁赢了,已经告知winMessage
游戏结束的信息。
如果游戏没有结束,也就是gameTimes
不为0
,则还是展示结果isShowWinner
。
我们把判断游戏是否结束的方法加到判断每次猜拳的结果方法中,示例:
// 判断最终猜拳结果
func showWinner() {
if computerPushImage == "rock" && selectedImage == "paper" || computerPushImage == "paper" && selectedImage == "scissors" || computerPushImage == "scissors" && selectedImage == "rock" {
winName = "你输了"
computerWinCount += 1
winMessage = "你还有" + String(gameTimes) + "次机会"
isEndGame()
} else if computerPushImage == selectedImage {
gameTimes += 1
winName = "平手"
winMessage = "你还有" + String(gameTimes) + "次机会"
isEndGame()
} else {
winName = "你赢了"
winMessage = "你还有" + String(gameTimes) + "次机会"
isEndGame()
}
}
上述代码中,我们在每一次判断时,都调用isEndGame
判断游戏是否结束的方法。
猜拳结果展示
我们有了系统随机出牌的方法randomPush
,还有判断猜拳结果的方法showWinner
,再完成了判断游戏是否结束的方法isEndGame
。
最后我们还需要展示结果,我们可以通过Alert
弹窗来告知用户结果。示例:
// 展示猜拳结果
func showResult() -> Alert {
let alert = Alert(
title: Text(winName),
message: Text(winMessage),
dismissButton: .default(Text("继续")) {
self.computerPushImage = "game"
self.isSelected = false
}
)
return alert
}
上述代码中,我们创建了一个Alert
视图showResult
。
我们Alert
视图的标题title
关联winName
,信息message
关联winMessage
,当我们点击继续按钮时,computerPushImage
系统出牌恢复到默认图片,且用户选择isSelected
切换为未选择。
我们在body
主要视图中,调用Alert
方法,示例:
var body: some View {
VStack(spacing: 20) {
titleView()
ruleView()
computerPush()
Spacer()
Spacer()
if isSelected {
personPush()
} else {
personSelected()
}
Spacer()
playGame()
}
.padding()
.alert(isPresented: $isShowWinner) {
showResult()
}
}
项目成果展示
恭喜你,完成了整个项目的全部内容!
快来动手试试吧。
如果本专栏对你有帮助,不妨点赞、评论、关注~