【问题标题】:How to change property value with static method?如何使用静态方法更改属性值?
【发布时间】:2018-10-03 12:33:19
【问题描述】:

在这个简单的游戏中,有一个职业战士,其目的是让两个战士战斗。生命值低于 0 的人将输掉比赛。

为了战斗,有一个静态方法战斗(..)迭代直到一个战士赢得比赛,由另一个非静态方法攻击(..)支持

object Fighter 的生命值应该随着两个对象在游戏中使用fight(...) 和attack (...) 方法进行战斗而改变。问题是它总是打印相同的战斗机健康状况,并且游戏永远不会结束。我看不出问题出在哪里

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

【问题讨论】:

  • 战士的damagedefense 值是多少?
  • 你在问这个吗?
  • let david = Fighter(name: "David", 生命值: 100, 伤害: 30, 防御: 10, 主动性: 80) let goliath = Fighter(name: "Goliath", 生命值: 300,伤害:60,防御:14,先攻:90)
  • 任一a)您需要为战士创建一个mutating健康属性,并且需要在每次迭代后更新健康值;或 b) 使战士class 并在每次迭代后更新健康值;或 c) 在评估期间将战士的健康值存储在本地范围内,以逐渐降低它们;或 d) 放弃 while 循环并计算每个战斗机的命中数,然后比较这些值以宣布获胜者。

标签: ios swift swift-structs swift-class


【解决方案1】:

您正在使用 struct 表示 Fighter,这是 Swift 中的 value 类型。

值类型最基本的区别特征是复制——赋值、初始化和参数传递的效果—— 创建一个具有自己唯一数据副本的独立实例

解决方案:Fighter 更改为 class 即可。

输出的打印语句:(第二次打印语句更改为print(g.name, g.health)

大卫 70.0
--> i: 1
歌利亚 240.0
大卫 40.0
--> 我:2
歌利亚 180.0
大卫 10.0
--> i: 3
歌利亚 120.0
大卫 -20.0


更多阅读:Value and Reference Types

【讨论】:

    【解决方案2】:

    每次调用func attack(f: Fighter) -&gt; 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
        }
    

    【讨论】:

      【解决方案3】:

      当你说...

          var g = f
      

      ...您实际上是在创建该对象的副本,而不是引用。因此,当您更改“健康”属性时,您将在副本中更改它。 有两个简单的解决方案:

      1) 将结构更改为类,因为类被引用,不像结构,它只是复制。

      2) 用修改后的副本替换原始对象 (g)

      【讨论】:

        【解决方案4】:

        正如 Rakesha 所说,结构是值类型,因此您的 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)
        }
        

        【讨论】:

          猜你喜欢
          • 2015-12-22
          • 1970-01-01
          • 1970-01-01
          • 2022-01-03
          • 2014-02-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多