2017-01-16 7 views
1

これは難しいことではないと思っていますので、助言をいただければ幸いです。クラス内のメソッドからvar値を更新する

私は、もっと良いクラスを理解しようとしている遊び場でちょうど回っています。ゲームのシナリオでは、私は健康値と攻撃値を持つ 'Player'クラスを作った。攻撃値は、「Weapon」という名前の別のクラスに由来し、それぞれ独自のDouble値を持ちます。私は 'Player'クラスの中から、新しい武器が拾われてプレイヤーの新しい攻撃値を作成するように呼び出されるという関数を作成しようとしています。

私の関数 'weaponPickUp'は、Weapon.Typeの値をDouble型に割り当てることはできません。この機能を意図したとおりに動作させるためのアドバイスが必要です!

class Player { 
    var health = 100.00 
    var armor = 0 
    var attack: Double 

    init() { 
     attack = Weapon.init().fist 
    } 

    func weaponPickUp(weaponPickedUp: Weapon.Type){ 
     attack = weaponPickedUp 
    } 

    func attackEnemy(enemy: Enemy) { 
     let weaponStrike = enemy.health - attack 
     let currentEnemyHealth = weaponStrike 

     if currentEnemyHealth > 0 { 
      print("Enemy Hit, life remaining \(currentEnemyHealth)") 
      enemy.health = currentEnemyHealth 
     } else { 
      print("Enemy Destroyed") 
     } 
    } 
} 


class Weapon { 
    var fist = 25.0 
    var machette = 35.0 
    var special = Enemy.init().health/2.0 
} 


class Enemy { 
    var health = 100.0 
    var armor = 100.0 
    var attack1 = 10.0 
    var specialAttack = 50.0 
} 
+0

あなたがリファクタリングすることはお勧めできません。なぜなら、あなたが学習曲線上でどこにいるのかがはっきりしているからです。代わりに、これらの概念を紹介するチュートリアル、または別の*チュートリアルを見つける必要があります。 – Andreas

答えて

1

これがプログラム全体の場合、私は間違いなくSweeperのスタイルでこれを書いていますが、すぐに処理したいと思っているよりもはるかに高い学習曲線かもしれないクロージャの理解に依存しています。また、武器が損傷以外の他の属性を持つことができればそれが望ましいかもしれないならば、それは柔軟ではない。今、あなたは特定の武器を持つことができます

protocol Weapon { 
    func damage(whenAttacking enemy: Enemy) -> Double 
} 

:この問題にアプローチする

もう一つの方法は、単純なWeaponプロトコルとなります。これが本当にすべての武器(一組の統計)であれば、おそらく構造体でなければなりません。しかし、ゲームでユニークなアイテムとして武器を追跡する場合は、武器をクラスにすることもできます。今のところ、それらを構造体にします(これは、例えば、2つのMachettesが区別できないことを意味します)。

struct Fist: Weapon { 
    func damage(whenAttacking enemy: Enemy) -> Double { 
     return 25 
    } 
} 

struct Machette: Weapon { 
    func damage(whenAttacking enemy: Enemy) -> Double { 
     return 35 
    } 
} 

struct SpecialWeapon: Weapon { 
    func damage(whenAttacking enemy: Enemy) -> Double { 
     return enemy.health/2.0 
    } 
} 

Playerに変更されました。私はいくつかのスタイルを変更しました(初期値を設定するだけでinitの必要はありません)。そしていくつかの実質的な変更(ダメージの計算方法)を行いました。

class Player { 
    var health = 100.00 
    var armor = 0 
    var weapon: Weapon = Fist() 

    // You'd almost certainly not bother with this method, and just let people call 
    //  player.weapon = Machette() 
    func pickUp(weapon: Weapon){ 
     self.weapon = weapon 
    } 

    func attack(enemy: Enemy) { 
     let weaponStrike = enemy.health - weapon.damage(whenAttacking: enemy) 
     let currentEnemyHealth = weaponStrike 

     if currentEnemyHealth > 0 { 
      print("Enemy Hit, life remaining \(currentEnemyHealth)") 
      enemy.health = currentEnemyHealth 
     } else { 
      print("Enemy Destroyed") 
     } 
    } 
} 

これは合理的なアプローチですが、これを行う方法は他にもたくさんあります。

class Enemy { 
    private(set) var health = 100.0 
    private var armor = 100.0 
    private var attack1 = 10.0 
    private var specialAttack = 50.0 

    var isAlive: Bool { 
     return health > 0 
    } 

    func receiveAttack(from weapon: Weapon) { 
     health -= weapon.damage(whenAttacking: self) 
     // Personally I'd let health be negative, but feel free to force it to be 0 here 
    } 
} 

そして今、Player.attackは次のようになります:これは内部の敵の健康状態を変更するためのロジックを置く

func attack(enemy: Enemy) { 
    enemy.receiveAttack(from: weapon) 

    if enemy.isAlive { 
     print("Enemy Hit, life remaining \(enemy.health)") 
    } else { 
     print("Enemy Destroyed") 
    } 
} 

実際に、私は個人的にEnemyにこの方法をattackコードの大部分を移動したいです敵の新しい敵にMachettesに対して特別な権限がある場合、Player(または他のオブジェクト)を変更することなくreceiveAttackの中に入れることができます。

+0

これは非常に役に立ちます!あなたが提案したそれぞれの変更についての深い説明に感謝し、今度は 'Enemy'クラスの中に' attack'コードを置く方が意味があることに完全に同意します。私が持っている1つの質問は、 'Enemy'変数を' private'に設定する理由は何ですか? – sluppickc

+0

現在のコードでは、外部の呼び出し元がアクセス権を必要とする理由は見当たりませんでしたので、私はそれらを非公開にしました。多くの場合、最良の質問は「なぜこれが公開されたのですか?」です。そして、あなたが良い答えを持っていない場合は、それを非公開にしてください。しかし、上記のケースでは、どのタイプが最良であるかを十分に分かっているわけではありません。 –

2

Weaponクラスはあまりうまく設計されていません。 Weaponクラスでは、武器のタイプとその攻撃のダメージを列挙したようです。しかし、それらをインスタンスプロパティとして宣言するべきではありません。また、specialは、敵の健康状態を半分にするのではなく、常に50のダメージを与えます。

私は、構造体の中にあなたの武器クラスを再設計:

struct Weapon { 
    var damage: (Enemy) -> Double 
    static let fist = Weapon { _ in return 25.0 } 
    static let machette = Weapon { _ in return 35.0 } 
    static let special = Weapon { enemy in return enemy.health/2.0 } 
} 

damage店舗武器のダメージを返すクロージャ。 fistmachettespecialという静的定数を作成して、新しい武器のインスタンスを作成せずにアクセスできるようにしました。ここで

が変更プレーヤーのクラスです:

class Player { 
    var health = 100.00 
    var armor = 0 
    var weapon: Weapon 

    init() { 
     weapon = Weapon.fist 
    } 

    func weaponPickUp(weaponPickedUp: Weapon){ 
     weapon = weaponPickedUp 
    } 

    func attackEnemy(enemy: Enemy) { 
     let weaponStrike = enemy.health - weapon.damage(enemy) 
     let currentEnemyHealth = weaponStrike 

     if currentEnemyHealth > 0 { 
      print("Enemy Hit, life remaining \(currentEnemyHealth)") 
      enemy.health = currentEnemyHealth 
     } else { 
      print("Enemy Destroyed") 
     } 
    } 
} 

special半分敵の健康ので、あなたは敵が持っているどのくらいの健康のPlayer依存しないで一定のattack値を持つことはできません。だから私はそれをWeaponインスタンスに変更しました。 attackEnemyでは、武器にどれくらいのダメージを与えることができるかを把握するために、私たちが攻撃している敵を渡す必要があるため、私はweapon.damage(enemy)と書きました。

+0

ありがとう!私はそれをよりよく理解するためにあなたのすべての推奨事項を解析しています。私はまだ構造体とクラスとクロージャの使用を使用するときに私の頭を包み込むことを試みています。私は武器クラスを持っていた方法が何よりも問題のほうが大きかったと思った。 – sluppickc

関連する問題