SwiftUI100天:使用SwiftUI搭建一个剪刀石头布App(下)

携手创作,共同成长!这是我参与「掘金日新计划 · 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) + "次机会"
    }
}

1.png

上述代码中,我们创建了一个方法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
}

2.png

上述代码中,我们创建了一个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()
    }
}

项目成果展示

3.gif

恭喜你,完成了整个项目的全部内容!

快来动手试试吧。

如果本专栏对你有帮助,不妨点赞、评论、关注~

猜你喜欢

转载自juejin.im/post/7126002711153098789