[英]Variable used before being initialized in function
我正在做ro sham bo游戲。 快速的功能與我以前使用的功能不同。 我不斷收到錯誤消息:
在函數中初始化之前使用的變量
我究竟做錯了什么?
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對此rval
,因此它會報告錯誤。 為了解決編譯錯誤,請將初始值添加到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
。 因此,沒有有效值被返回。 嘗試這個:
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
語句一起使用,這也是一個很好的選擇。 結合肖恩(Sean)的建議 ,我認為這是可行的。
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語句窮舉)
已編輯
您收到初始化程序錯誤,因為在設置之前尚未使用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!
正如其他人已經說過的那樣,問題在於您的條件沒有被滿足,然后returnval
沒有被初始化。
您可以使用switch語句+ guard +計算屬性。 像這樣
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均為零,則在我的代碼中有效,返回值為零。 在代碼中返回2。 您應該更改它,也許在我的代碼之上添加另一個
guard
。 就像是
guard chosen != rval else { return 2 }
如果您知道選擇並且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()
}
}
您可以更加迅速地進行操作。
例如...為什么使用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
}
然后,您要做的就是將其包裝在某種類型的Player
和Game
類型的東西中...
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中值得稱贊的要強大得多。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.