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

时间:2016-06-20 18:33:57

标签: ios swift

我正在进行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)
    }
}

6 个答案:

答案 0 :(得分:1)

有问题的陈述是return (returnval),因为Swift编译器认为传递了if-then-else链而不会导致returnval的分配。

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

也许程序的其他部分使chosen无法在rval为2的同时成为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

答案 1 :(得分:1)

Swift程序流程中的每个可能路径都必须具有已定义的返回值。在您的情况下,如果全部跳过00 / if / else if部分,则会else未分配。因此,不返回有效值。试试这个:

returnval

这也是使用switch语句进行模式匹配的非常好的候选者。以下是我认为可以与Sean's suggestion.

一起使用的内容
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) 
    }
}

答案 2 :(得分:0)

尝试var returnval: Int = 0(或其他随机数,以防你的if-else陈述详尽无遗)

答案 3 :(得分:0)

<强> EDITTED

问题解决

您收到初始值设定项错误,因为在设置之前您尚未使用returnval初始化Int()

代码改进

考虑使用计算属性来返回获胜者的值。我在下面的代码中做了假设,你使用的值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!

答案 4 :(得分:0)

返回Int?

正如其他人已经说过的那样,问题是没有满足您的条件,因此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()
    }
} 

答案 5 :(得分:0)

你可以让这更加活跃。

例如......为什么使用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,你可以确切地看到获胜的动作是什么以及谁赢了......

Enums实际上比Swift中的功能强大得多。