在函数初始化之前使用的变量

我正在制作一个ro sham bo游戏。 swift中的函数与我之前使用的函数不同。 我一直收到错误:

在函数初始化之前使用的变量

我究竟做错了什么?

import Foundation import UIKit class Result: UIViewController { var rval: Int? var chosen: Int? func determineWinner() -> Int { var returnval: Int if (chosen == rval){ returnval = 2 } else if (chosen == 1 && rval == 3){ returnval = 1 } else if (chosen == 1 && rval == 2){ returnval = 0 } else if (chosen == 2 && rval == 1){ returnval = 1 } return (returnval) } @IBOutlet weak var wl: UILabel! @IBAction func PlayAgain(sender: AnyObject) { } override func viewDidLoad() { print(chosen) } } 

有问题的语句是return (returnval)因为Swift编译器认为有一个if-then-else链的传递不会导致returnval赋值。

例如,如果chosen为3且rval为2,则不会进行赋值。

也许你的程序的其他部分使得不可能在rval为2的情况下同时chosen 3,但是Swift不知道这一点,所以它报告错误。 为了修复编译错误,请将一个初始值添加到returnval

如果您完全确定if-then-else链枚举所有有效的可能性,请将returnval设置为-1 ,并在返回之前声明将其设置为非负值:

 var returnval = -1 ... // your conditionals go here assert(returnval >= 0, "Logic of determineWinner is broken") return returnval 

Swift程序流中的每个可能路径都必须具有已定义的返回值。 在您的情况下,如果if / else if / else部分都被跳过, returnval保留returnval 。 因此,没有返回有效值。 尝试这个:

 import Foundation import UIKit //space things out to be easier to read class Result: UIViewController { var rval: Int? //these should have better names var chosen: Int? func determineWinner() -> Int { var returnval = -1 //needs a default value if (chosen == rval){ returnval = 2 } else if (chosen == 1 && rval == 3){ returnval = 1 } else if (chosen == 1 && rval == 2){ returnval = 0 } else if (chosen == 2 && rval == 1){ returnval = 1 } return returnval //don't put return value in brackets } @IBOutlet weak var wl: UILabel! @IBAction func PlayAgain(sender: AnyObject) { } override func viewDidLoad() { print(chosen) } } 

这也是使用switch语句进行模式匹配的一个很好的选择。 这是我认为旁边的工作,与肖恩的建议相结合。

 var determineWinner: Int? { guard let chosen = chosen, let rval = rval else { //handle error, either chosen or rval is nil return nil } switch ((chosen, rval)) { case let (x, y) where x == y: return 2 case (1, 3): return 1 case (1, 2): return 0 case (2, 1): return 1 default: print("handle default case here") return nil; } } 

尝试var returnval: Int = 0 (或者if-else语句详尽无遗的另一个随机数)

退回国际?

正如其他人已经说过的那样,问题是没有满足任何条件,因此不会初始化returnval

您可以使用switch语句+ guard + computed属性。 喜欢这个

 var winner: Int? { guard let chosen = chosen, rval = rval else { return nil } switch (chosen, rval) { case (let chosen, let rval) where chosen == rval : return 2 case (1, 3): return 1 case (1, 2): return 0 case (2, 1): return 1 default: return nil } } 

请注意我稍微改变了你的逻辑。 在我的代码中,如果选择并且rval都为nil,则返回值为nil。 在您的代码2中返回。 你应该改变它,也许在我的代码之上添加另一个guard 。 就像是

 guard chosen != rval else { return 2 } 

返回Int +致命错误

如果您知道选择,那么将始终填充rval

 var winner: Int { guard let chosen = chosen, rval = rval else { fatalError() } switch (chosen, rval) { case (let chosen, let rval) where chosen == rval : return 2 case (1, 3): return 1 case (1, 2): return 0 case (2, 1): return 1 default: fatalError() } } 

EDITTED

问题解决

您将获得初始化程序错误,因为您在设置之前未使用Int()初始化returnval

代码改进

考虑使用计算属性来返回赢得谁的值。 我在下面的代码中做了假设,你使用的值2根据你的逻辑推断出一个平局情况。

在这里,我创建了一个枚举,以确保返回值仅以您期望结果的特定方式处理。 您仍然可以通过枚举案例中的哈希值访问Int值。 使用.rawValue来执行此操作。

在这种情况下,尽量避免使用Int值非常重要,因为它们可以是其他值。

在下面包含的代码中,我写了一组失败的guard语句,并在检查的值不允许确定获胜者状态时返回fatalError消息。

改进的代码

 import Foundation import UIKit class Result: UIViewController { var rval: Int? var chosen: Int? enum Winner: Int { case one = 0 case two = 1 case tie = 2 } var winner: Winner? { guard (rval > 0 || rval < 4) else { fatalError("rval out of bounds: cannot determine winner") } guard (chosen > 0 || chosen < 3) else { fatalError("chosen out of bound: cannot determine winner") } guard (rval != nil && chosen != nil) else { fatalError("rval or chosen are nil: cannot determine winner") } switch (chosen!, rval!) { case (let chosen, let rval) where chosen == rval: return Winner.tie case (1, 3): return Winner.two case (1, 2): return Winner.one case (2, 1): return Winner.two default: return nil } } @IBOutlet weak var wl: UILabel! @IBAction func PlayAgain(sender: AnyObject) { } override func viewDidLoad() { print(chosen) } } 

作为旁注,请务必为您喜欢的答案+1!

你可以让这更加开心。

例如……为什么使用Int来表示不同的动作? 在这里,我使用枚举来表示移动和胜利背后的逻辑……

 enum RoShamBo { case Rock case Paper case Scissors func beats(opposingPlay: RoShamBo) -> Bool { return self > opposingPlay } } // I thought it made sense to make it Comparable. // That way you can use the < or > operator to determine // the winning move. // I then used this in the function beats() above extension RoShamBo: Comparable {} func < (lhs: RoShamBo, rhs: RoShamBo) -> Bool { // this is required for Comparable // in this we return true if lhs loses to rhs // Scissors beat Paper return lhs == .Paper && rhs == .Scissors // Paper beats Rock || lhs == .Rock && rhs == .Paper // Rock beats Scissors || lhs == .Scissors && rhs == .Rock } 

那么你需要做的就是把它包装成某种PlayerGame类型的东西……

 struct Player { let name: String let move: RoShamBo } struct Game { func winner(player1: Player, player2: Player) -> Player? { if player1.move.beats(opposingPlay: player2.move) { return player1 } if player2.move.beats(opposingPlay: player1.move) { return player2 } // tie return nil } } let p1 = Player(name: "Oliver", move: .Rock) let p2 = Player(name: "Geoff", move: .Scissors) let game = Game() let winner = game.winner(player1: p1, player2: p2) print(winner) //Output Optional(Player(name: "Oliver", move: RoShamBo.Rock)) 

在整个事情中没有使用任何一个Int,你可以确切地看到获胜的举动是什么以及谁赢得了…

在Swift中,枚举实际上比它们的function强大得多。