Как изменить значение свойства статическим методом? - PullRequest
0 голосов
/ 03 октября 2018

В этой простой игре есть класс Fighter, цель которого - заставить двух бойцов сражаться.Тот, кто теряет здоровье ниже 0, теряет игру.

Для борьбы используется статический метод боя (..), который повторяется до тех пор, пока один боец ​​не выиграет игру, поддерживаемый атакой другого не статического метода (..)

объект Здоровье бойца должно меняться, так как два объекта сражаются во время игры, используя методы бой (...) и атака (...).Проблема в том, что он всегда печатает одно и то же здоровье бойца, и игра никогда не заканчивается.Я не вижу, где проблема

class ViewController: UIViewController {
     override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let david = Fighter(name: "David", health: 100, damage: 30, defense: 10, initiative: 80)
        let goliath = Fighter(name: "Goliath", health: 300, damage: 60, defense: 14, initiative: 90)


        let myFight1 = Fighter.fight(fighter1: david, fighter2: goliath) // always executing same Fighters
        print(myFight1)

    }
}

import Foundation


struct Fighter {
    var name: String
    var health: Double
    var damage: Int
    var defense: Int
    var initiative: Int

    init (name: String, health: Double, damage: Int, defense: Int, initiative: Int) {
        self.name = name
        self.health = health
        self.damage = damage
        self.defense = defense
        self.initiative = initiative
    }

     init (name: String, health: Double, damage: Int, defense: Int) {
        self.name = name
        self.health = health
        self.damage = damage
        self.defense = defense
        self.initiative = 0
    }

    static func fight(fighter1: Fighter, fighter2: Fighter) -> Fighter {
        let f1 = fighter1
        let f2 = fighter2

        if f1.health == f2.health {
            return f1
        }

        if f2.initiative > f1.initiative {
           f2.attack(f: f1)
        }

        var i = 0

        while f1.health > 0 {
            i += 1
            print("--> i: \(i)")
            f1.attack(f: f2 )

            if f2.health <= 0 {
                return f1
            }
        f2.attack(f: f1)
            }
        return f2
        }

    func attack(f: Fighter) -> Void {
        var g = f
        g.health = g.health - Double(g.damage * (1 - g.defense / 100))
        print(g)
    }        
}

Ответы [ 4 ]

0 голосов
/ 03 октября 2018

Как отмечает Ракеша, структуры являются типами значений, поэтому ваш код attack фактически ничего не меняет:

func attack(f: Fighter) -> Void {
    var g = f   // Make a mutable copy of `f` called `g`
    g.health = g.health - Double(g.damage * (1 - g.defense / 100)) // Modify g
    print(g) // Print g
    // Throw g away
}

(Примечание: я думаю, что g.damage здесь неверно; я думаю, что вывероятно, имелось в виду self.damage.)

Ничто там на самом деле не меняет f.Есть несколько способов решить эту проблему.Одним из них является использование классов, которые вводят тонкое изменяемое состояние.Я не думаю, что я сделал бы это здесь.Под «тонким изменяемым состоянием» я подразумеваю, что вы ожидаете, что attack изменит f, но ничто в подписи не говорит, что это так, и вызывающий абонент может быть удивлен.

Вместо этого у вас есть несколько способовреализовать это, чтобы сделать ваши мутации явными на структурах.Вы можете attack явно изменить f:

func attack(f: inout Fighter) {
    f.health = f.health - Double(damage * (1 - f.defense / 100))
}

Или вы можете повернуть его и изменить себя, когда на вас нападает кто-то еще:

mutating func attackedBy(f: Fighter) {
    health = health - Double(f.damage * (1 - defense / 100)
}
0 голосов
/ 03 октября 2018

После вызова метода func attack(f: Fighter) -> Void каждый раз свойства атакующего Fighter не обновляются.Так что while цикл не будет разрываться ни в одной точке.

Пожалуйста, замените код ниже.

static func fight(fighter1: Fighter, fighter2: Fighter) -> Fighter {
        var f1 = fighter1
        var f2 = fighter2

        if f1.health == f2.health {
            return f1
        }

        if f2.initiative > f1.initiative {
            f1 = f2.attack(f: f1)
        }

        var i = 0

        while f1.health > 0 {
            i += 1
            print("--> i: \(i)")
            f2 = f1.attack(f: f2 )

            if f2.health <= 0 {
                return f1
            }
            f1 = f2.attack(f: f1)
        }
        return f2
    }

    func attack( f: Fighter) -> Fighter {
        var g = f
        g.health = g.health - Double(g.damage * (1 - g.defense / 100))
        print(g)
        return g
    }
0 голосов
/ 03 октября 2018

Когда вы говорите ...

    var g = f

... вы фактически создаете копию этого объекта, а не ссылку.Итак, когда вы меняете свойство «здоровье», вы меняете его в копии.Есть 2 простых решения:

1) Измените структуру на класс, потому что на классы ссылаются, в отличие от структур, которые просто копируют.

2) Замените оригинальный объект его измененной копией (г)

0 голосов
/ 03 октября 2018

Вы используете struct для Fighter, который является типом значение в Swift.

Самая основная отличительная особенность типа значения заключается в том, что копирование - эффект присваивания, инициализации и передачи аргумента - создает независимый экземпляр со своей уникальной копией своих данных

Решение: Измените Fighter на class и все готово.

Вывод операторов печати: (Второй оператор печатиизменено на print(g.name, g.health))

Давид 70,0
-> я: 1
Голиаф 240,0
Давид 40,0
-> я: 2
Голиаф 180,0
Дэвид 10.0
-> i: 3
Голиаф 120.0
Дэвид -20.0


Для дополнительного чтения: Типы значений и ссылки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...