Search code examples
iosswiftswift-structsswift-class

How to change property value with static method?


In this simple game there is a class Fighter whose purpose is to make two fighters fight. The one who looses health below 0, it looses the game.

In order to fight there is a static method fight (..) which iterates till one fighter wins the game, supported by another non static method attack (..)

object Fighter health should change as two objects fight during the game using the methods fight(...) and attack (...). The problem is it always prints the same Fighter health, and the game never ends. I don´t see where the issue is

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

Solution

  • You are using a struct for Fighter which is a value type in Swift.

    The most basic distinguishing feature of a value type is that copying — the effect of assignment, initialization, and argument passing — creates an independent instance with its own unique copy of its data

    Solution: Change Fighter to a class and you are good to go.

    Output of the print statements: (Second print statement changed to print(g.name, g.health))

    David 70.0
    --> i: 1
    Goliath 240.0
    David 40.0
    --> i: 2
    Goliath 180.0
    David 10.0
    --> i: 3
    Goliath 120.0
    David -20.0


    For more reading: Value and Reference Types