Search code examples
swiftfunctionfor-in-loop

How to handle this function?


I wanted to wrote a function where street fighters attacking them alternately. Each attack pulls some hearts of. When one of the fighters has 0 hearts, the fight is over. But I don't know how to do this process again and again. This is how my code looks right now:

public struct StreetFighter {
    var name: String
    var power: Int
    var defence: Int
    var hearts: Int
    func Attack() {
        print("\(name) is going into the offence...")
    }
    func Blocking() {
        print("\(name) is blocking the attack")
    }
}
var connorMcGregor = StreetFighter(name: "Connor McGregor", power: 8, defence: 7, hearts: 100)
var mikeTyson = StreetFighter(name: "Connor McGregor", power: 9, defence: 6, hearts: 100)
var alisterOverreem = StreetFighter(name: "Alister Overreem", power: 7, defence: 10, hearts: 100)
var khabib = StreetFighter(name: "Khabib", power: 9, defence: 8, hearts: 100)


struct Fight {
    var location: String
    mutating func Round1(firstFighter: StreetFighter,secondFighter: StreetFighter) -> Int {
        firstFighter.Attack()
        if firstFighter.power < secondFighter.defence  {
            secondFighter.Blocking()
            secondFighter.Attack()
        } else {
        secondFighter.hearts - firstFighter.power
            }
            
            if secondFighter.power < firstFighter.defence  {
                firstFighter.Blocking()
            } else {
        firstFighter.hearts - secondFighter.power
            }
        if firstFighter.hearts == 0 || secondFighter.hearts == 0 {
        print("The fight is over!")
        
        }
        return firstFighter.hearts
        return secondFighter.hearts
    }
}

var mma = Fight(location: "New York")
mma.Round1(firstFighter: connorMcGregor, secondFighter: khabib)

The problem is that the process stops after the first round. I tried it with for-in or repeat-while loops but without any success. Can anybody helps me?


Solution

  • First, you may try to move some functions to the StreetFighter itself:

    public struct StreetFighter {
        let name: String
        let power: Int
        let defence: Int
        var hearts = 100 // you can provide a default value
    
        var isAlive: Bool {
            hearts > 0
        }
    
        func attack() {
            print("\(name) is going into the offence...")
        }
    
        mutating func defend(attackingPower: Int) {
            if power > defence {
                hurt(damage: attackingPower)
            } else {
                block()
            }
        }
    
        private func block() {
            print("\(name) is blocking the attack")
        }
    
        private mutating func hurt(damage: Int) {
            print("\(name) is hurt")
            hearts -= damage
        }
    }
    

    Then, add a function in the Fight struct with a while loop (you can limit the number of rounds there as well):

    struct Fight {
        let location: String
        var fighter1: StreetFighter
        var fighter2: StreetFighter
    
        mutating func start() {
            var roundNumber = 0
            while !isFinished && roundNumber < 12 {
                roundNumber += 1
                round()
                print("Round \(roundNumber): \(fighter1.name) - \(fighter1.hearts), \(fighter2.name) - \(fighter2.hearts)")
            }
    
            print("The fight is over!")
        }
    
        private mutating func round() {
            fighter1.attack()
            fighter2.defend(attackingPower: fighter1.power)
            fighter2.attack()
            fighter1.defend(attackingPower: fighter2.power)
        }
    
        private var isFinished: Bool {
            !fighter1.isAlive || !fighter2.isAlive
        }
    }
    

    Now you can start your fight:

    let connorMcGregor = StreetFighter(name: "Connor McGregor", power: 8, defence: 7, hearts: 100)
    let mikeTyson = StreetFighter(name: "Connor McGregor", power: 9, defence: 6, hearts: 100)
    let alisterOverreem = StreetFighter(name: "Alister Overreem", power: 7, defence: 10, hearts: 100)
    let khabib = StreetFighter(name: "Khabib", power: 9, defence: 8) // you can use the default `hearts` count
    
    var mma = Fight(location: "New York", fighter1: connorMcGregor, fighter2: khabib)
    mma.start()
    

    Depending on your goal you may want to extract some parts of Fight outside. For example the start function can return a result (who won) and you can operate on it then.