Переменная, используемая до инициализации в функции

Я делаюро шам бо игра. Функции в 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)
    }
}
 Scott Hunter20 июн. 2016 г., 20:38
Какая переменная? Где в коде?
 Prune21 июн. 2016 г., 00:13
Улучшено форматирование кода; уточнил формулировку и предоставил ссылку на игру.
 Hamish20 июн. 2016 г., 20:39
Что если ни один из ваших операторов if-else не сработает в функции? Что вы ожидаете, что он вернется в таких обстоятельствах? Вы должны предоставить некоторую форму значения по умолчанию дляreturnvalили заставьте вашу функцию возвращать необязательный.
 Fogmeister23 июн. 2016 г., 01:26
Не забудьте проголосовать и принять ответ, если он отвечает на ваш вопрос.
 Gruntcakes20 июн. 2016 г., 20:38
Если ни один из операторов if не совпадает, returnval не имеет значения, что является причиной ошибки.

Ответы на вопрос(6)

var returnval: Int = 0 (или другое случайное число, если ваши операторы if-else являются исчерпывающими)

Каждый возможный путь в потоке программы Swift должен иметь определенное возвращаемое значение. В вашем случае, еслиif/else if/else разделы все пропущены, оставляяreturnval Unassigned. Таким образом, действительное значение не возвращается. Попробуй это:

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;
    }
}
 Alexander20 июн. 2016 г., 21:19
Хороший улов, я забыл, что они были условны. Я думаю, что лучшеguard их
 Luca Angeletti20 июн. 2016 г., 21:28
Кстати, поздравляю с большим вкладом, который вы вносите здесь, на SO, о swift.
 Luca Angeletti20 июн. 2016 г., 21:19
Нет проблем, в остальном ваш ответ идеален.
 Luca Angeletti20 июн. 2016 г., 21:12
Привет, чтобы использовать дополнительные функции вswitch пункт вам нужно поставить что-то вроде этогоcase (Optional<Int>.Some(1), Optional<Int>.Some(3)): return 1 в дело.
 Alexander20 июн. 2016 г., 21:23
Тебе нравится моя охранная идея, как я вижу: p
 Luca Angeletti20 июн. 2016 г., 21:26
Нет, я предложил вам сопоставить шаблон сOptional в комментарии, но мой ответ сguard был уже размещен. Это было просто другое решение.
 Luca Angeletti20 июн. 2016 г., 21:25
I КОПИРОВАНИЕ несколько частей вашего ответаНО guard это моя идея: D
 Alexander20 июн. 2016 г., 21:26
Вы собирались использовать сопоставление с образцом наOptional перечисления! :п

Например ... Зачем использоватьInt представлять разные ходы? Здесь я использовал enum для представления ходов и логики того, что побеждает ...

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.

return (returnval) потому что компилятор Swift считает, что через цепочку if-then-else есть проход, который не приводит к присваиваниюreturnval.

Например, еслиchosen 3 иrval 2, не было бы назначения.

Возможно, другие части вашей программы делают невозможнымchosen быть 3 одновременно сrval 2, но Swift не знает об этом, поэтому сообщает об ошибке. Чтобы исправить ошибку компиляции, добавьте начальное значение вreturnval.

Если вы абсолютно уверены, что ваша цепочка if-then-else перечисляет все допустимые возможности, установитеreturnval в-1и сделайте утверждение о том, что для него задано неотрицательное значение перед возвратом:

var returnval = -1
... // your conditionals go here
assert(returnval >= 0, "Logic of determineWinner is broken")
return returnval
Возвращая Int?

проблема в том, что ни одно из ваших условий не будет выполненоreturnval не инициализируется.

Вы можете использовать оператор switch + guard + computed property. Как это

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
    }
}

Обратите внимание, я немного изменил вашу логику. Infact в моем коде, если выбрано и rval оба равны нулю, возвращаемое значение равно нулю. Пока в вашем коде 2 возвращается. Вы должны изменить его, возможно, добавив еще одинguard поверх моего кода. Что-то вроде

guard chosen != rval else { return 2 } 
Возвращая Int + Fatal error

Если вы знаете, выбрал и 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

Вы получаете ошибку инициализатора, потому что вы не инициализировали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 к ответам, которые вам нравятся!

 Sean20 июн. 2016 г., 21:00
Согласен, мне нравятся ваши заявления о смене
 Sean20 июн. 2016 г., 20:57
ха-ха, что случилось, когда я вставил его. Спасибо!
 Alexander20 июн. 2016 г., 20:53
Это отступление дало мне рак. я починил это
 Alexander20 июн. 2016 г., 21:01
Мне нравится ваше использование опций и вычисляемых свойств. я вернулся-1, Я чувствую себя грязным.
 Alexander20 июн. 2016 г., 20:59
Я собираюсь объединить наши два ответа вместе

Ваш ответ на вопрос