簡體   English   中英

在函數中初始化之前使用的變量

[英]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 } 

返回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()
    }
} 

您可以更加迅速地進行操作。

例如...為什么使用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中值得稱贊的要強大得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM