【问题标题】:Embedded switch in function, how do i retrieve the return value?函数中的嵌入式开关,我如何检索返回值?
【发布时间】:2015-08-13 22:44:28
【问题描述】:

我是“深入”OOP 和 iOS 开发的新手,所以这周一直在搞砸。我感觉更舒服了,所以决定制作一个石头、纸、剪刀游戏。我知道它非常简单,欢迎对这个非常简单的陈述提出任何批评。

为了比较用户和计算机选择,我创建了 compare picks 函数,其中嵌入了 case 语句。我得到的错误是该函数没有收到任何要返回的内容,大概是因为返回调用都在 switch 语句中。

func comparePicks(var human: String, var computer: String) -> String {
    switch human{
        //Player Chooses Rock
        case "Rock":
            if computer == "Rock"{
                return "Draw"}
            else if computer == "Paper"{
                return "Lose"}
            else if computer == "Scissors"{
                return "Win"}
            //Player Chooses Scissors
        case "Scissors":
            if computer == "Scissors"{
                return "Draw"}
            else if computer == "Rock"{
                return "Lose"}
            else if computer == "Paper"{
                return "Win"}
            //Player Chooses Paper
        case "Paper":
            if computer == "Paper"{
                return "Draw"}
            else if computer == "Rock"{
                return "Lose"}
            else if computer == "Scissors"{
                return "Win"}
        default:
            return "error"
    }
    // Error here - "Missing return in a function expected to return 'String'
}

这些也会在哪里返回,switch 语句是否可以返回,我没有看到文档中提到的任何内容。我该如何更改它,以便将返回值提供给 compare Picks 函数。 TIA。

【问题讨论】:

  • 您看到的错误是因为 Swift 不相信您已经涵盖了所有可能性。考虑一下如果为计算机传入“Spock”​​会发生什么。
  • 解决问题的一个好方法是创建一个 3x3 数组,其中 3 列表示石头、剪刀、纸张,3 行表示相同,每个交叉点的值 -1 丢失,0平局,1胜,所以只要问result = array[computerValue, userValue]就可以知道结果
  • 使用enum 代替下面建议的字符串可能是这里最好的解决方案。在其他情况下,您可以使用fatalError() 告诉编译器某些情况“不会发生”,例如stackoverflow.com/questions/30189505/…

标签: ios function swift switch-statement


【解决方案1】:

你的 switch 语句中的返回确实离开了函数,但你没有考虑所有可能的路径。如果您使用“Spock”​​调用您的函数以供计算机选择,您将不会遇到任何现有的返回语句。

如果将计算机的第三个比较替换为else,则可以:

func comparePicks(var human: String, var computer: String) -> String {
    switch human{
        //Player Chooses Rock
    case "Rock":
        if computer == "Rock"{
            return "Draw"}
        else if computer == "Paper"{
            return "Lose"}
        else {
            return "Win"}

        //Player Chooses Scissors
    case "Scissors":
        if computer == "Scissors"{
            return "Draw"}
        else if computer == "Rock"{
            return "Lose"}
        else {
            return "Win"}

        //Player Chooses Paper
    case "Paper":
        if computer == "Paper"{
            return "Draw"}
        else if computer == "Rock"{
            return "Lose"}
        else {
            return "Win"}

    default:
        return "error"
    }

    // No error, all cases accounted for.
}

因此,如果所有路径都被覆盖,则不需要额外的 return 语句。正如@MartinR 在 cmets 中指出的那样,这隐藏了错误,因为“Spock”​​现在可能是一个获胜状态,而实际上它应该是一个错误。

正如其他答案所暗示的那样,枚举将是一种更好的方法,因为这样您就可以通过只为枚举设置 3 个有效值来避免这种可能的错误情况。


这是一个使用枚举的解决方案,只是因为我玩得很开心......

enum Choices: String, Printable {
    case Rock = "Rock"
    case Paper = "Paper"
    case Scissors = "Scissors"

    var description: String {
        return self.rawValue
    }

    static func random() -> Choices {
        return [.Rock, .Paper, .Scissors][Int(arc4random_uniform(3))]
    }
}

func comparePicks(human: Choices, computer: Choices) -> String {
    switch human {

    //Player Chooses Rock
    case .Rock:
        switch computer {
        case .Rock:     return "Draw"
        case .Paper:    return "Lose"
        case .Scissors: return "Win"
        }

    //Player Chooses Scissors
    case .Scissors:
        switch computer {
        case .Scissors: return "Draw"
        case .Rock:     return "Lose"
        case .Paper:    return "Win"
        }

    //Player Chooses Paper
    case .Paper:
        switch computer {
        case .Paper:    return "Draw"
        case .Scissors: return "Lose"
        case .Rock:     return "Win"
        }
    }
}

let human = Choices.random()
println(human)  // prints "Paper"
let computer = Choices.random()
println(computer)  // Prints "Rock"
println(comparePicks(human, computer))  // Prints "Win"

通过创建一个选择元组,您可以将比较组合到一个 switch 语句中:

func comparePicks(human: Choices, computer: Choices) -> String {
    switch (human, computer) {
    case (.Rock, .Rock), (.Scissors, .Scissors), (.Paper, .Paper): return "Draw"
    case (.Rock, .Scissors), (.Scissors, .Paper), (.Paper, .Rock): return "Win"
    case (.Rock, .Paper), (.Paper, .Scissors), (.Scissors, .Rock): return "Lose"
    }
}

【讨论】:

  • 但是这种方法“隐藏”了编程错误,例如“SomeString”的处理方式与“Scissors”相同。
  • 好点。我试图帮助他们理解为什么编译器会抱怨,而不一定是暗示这是编写代码的方式。
  • 不,这是一个很好的答案,显然我知道它应该以不同的方式完成,但也很高兴知道为什么。
【解决方案2】:

使用enum 代替字符串文字会更好。 enum 准确地代表了您允许的所有状态,并防止您出现拼写错误。并且enum 也可以比字符串比较更有效率。

在您的代码中,您不需要switchdefault: 部分,因为这是备用情况,如果没有编码错误,则不应该出现这种情况。因此,删除该子句并将return "error" 移动到函数的最后一行。

【讨论】:

  • 您的正确感谢,将这些更改为枚举。我最初使用字符串,因为我知道如何选择随机字符串。我知道默认值:不需要,我将其用于测试目的,之后将被删除。
  • 如果您使用字符串,则需要默认值。改成使用枚举后就不需要了。
  • 完全同意这会容易得多。虽然选择一个随机枚举似乎是下一个挑战!
  • enum Choices { case Rock, Scissors, Paper } let choice = [Choices.Rock, Choices.Scissors, Choices.Paper][Int(arc4random_uniform(3))]
  • 是的。这是经过测试的。你看到什么问题?这是两行代码,不是一行。
【解决方案3】:

你的函数必须返回一个字符串,Swift 编译器不相信这总是会发生。我喜欢在我的代码最后有一个退出点(一个返回),我使用一个变量来保持返回的结果,我相信它更容易理解,但这是我个人的选择。 为您提供的解决方案: 您可以在 return 中添加一个问号,这样它就不必总是返回一些东西,最后您返回 nil

func comparePicks(var human: String, var computer: String) -> String?{
    //some code
    return nil
}

或者你可以只返回一个对你有意义的字符串

func comparePicks(var human: String, var computer: String) -> String {
        //some code
        return "No Result"
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-21
    • 1970-01-01
    • 2020-09-04
    • 1970-01-01
    • 2010-09-21
    • 2016-11-10
    • 1970-01-01
    • 2023-03-19
    相关资源
    最近更新 更多