2011-01-29 42 views
1

我是新手編程,但很想學習,所以請原諒這個問題。我已經創建了這個遊戲,以幫助我學習OOP,並且遇到了一些問題。這是什麼導致我的問題:Ruby>如何從另一個類的方法中的一個類使用方法?

我有兩個類。在類Player的第3行,我有一些代碼可能是錯的,但基本上,我想要做的就是使用護甲來修改玩家受到的傷害。我得到一個錯誤,雖然:「未定義的方法'保護'零:NilClass(NoMethodError)

我有護甲作爲另一類,我認爲這個問題可能與我打電話@ armor.protection在Armor中提到了保護,並且在Player中提到了@armor,但我不確定如何解決這個問題。我添加了所有我認爲與以下問題相關的代碼。就像我說的,我真的是新手,所以請使用術語一個小白可以理解

class Player 
    def equip(armor) 
    @armor = armor 
    end 

    def hit(damage) 
    #damage = damage - @armor.protection 
    @health -= damage 
    end 
end 

class Armor 
    def initialize(name, protection) 
    @protection = protection 
    end 
end 

編輯:。添加額外的代碼來顯示所有的東西已經得到了持續了澄清我的我不希望任何人讀取所有的東西我已經得到了,雖然。 :S這很可怕,咆哮起來。 :P

class Player 

    def initialize(name, health) 
    @name = name 
    @health = health 
    end 

    def equip(armor) 
    @armor = armor 
    end 

    def health 
    @health 
    end 

    def health=(value) 
    @health = value 
    end 

    def hit(damage) 
damage = damage - @armor.protection 
    @health -= damage 
    end 

    def dead? 
if @health <= 0 
return true 
elsif @health > 0 
return false 
end 
    end 

    def name 
    @name 
    end 

    def attack(target) 
    damage = rand(30) 
    puts "#{@name} attacks #{target.name}" 
target.hit(damage) 
puts "#{@name} hits #{target.name} for #{damage} damage." 
    end 
end 

class Armor 
    def initialize(name, protection) 
    @protection = protection 
    end 
end 


player1 = Player.new("Melanie", 100) 
player2 = Player.new("a Monster", 200) 
shirt = Armor.new('shirt', 4) 
player1.equip(shirt) 

while player1.dead? == false && player2.dead? == false 
    player1.attack(player2) 
    if player2.health > 0 
     puts "#{player2.name}'s health is at #{player2.health}." 
    elsif player2.health <= 0 
puts "#{player2.name} has no health." 
end 
    player2.attack(player1) 
    if player1.health > 0 
     puts "#{player1.name}'s health is at #{player1.health}." 
    elsif player1.health <= 0 
puts "#{player1.name} has no health." 
end 
end 

if player1.health > player2.health 
    puts "#{player2.name} is dead." 
    puts "#{player1.name} wins." 
elsif player2.health > player1.health 
    puts "#{player1.name} is dead." 
    puts "#{player2.name} wins." 
elsif player2.health == player1.health 
    puts "#{player1.name} and #{player2.name} killed each other." 
end 

回答

3

如果你的護甲類有一個protection方法,它會正常工作。然而,它不會,所以即使你從Armor類中調用它,你也會得到同樣的錯誤。要定義它,您可以使用attr_readerattr_accessor或手動定義它。

class Armor 
    attr_accessor :protection 

    def initialize(name, protection) 
    @protection = protection 
    end 
end 

class Armor 
    def initialize(name, protection) 
    @protection = protection 
    end 

    def protection 
    @protection 
    end 
end 
+0

截至目前,該程序並不知道通過說鎧甲,我的意思是,在這個球員的情況下,一件襯衫。唯一提到的是我的裝甲,小寫字母a,除此之外,在傷害=傷害 - @ armor.protection中,是類Player中的裝備定義。我嘗試了第二個例子,希望能夠照顧到這一點,但無論如何我仍然有同樣的錯誤。我知道我有點過頭了,但我確實瞭解了很多,這絕對是一種學習體驗。 :S – 2011-01-29 12:50:38

+0

@Melanie:當我提到保護時,我意外地輸入了護甲,所以我的代碼首先出錯了,所以它無法工作。現在我解決了它,只要你在調用任何使用`@ armor`的方法之前調用`equip`,它就可以工作。 – sepp2k 2011-01-29 12:55:20

1

試試這個:

player = Player.new 
armor = Armor.new('Mythril', 100) 
player = player.equip(armor) #Initialise the armor object inside Player. 

player.hit(10) 
+1

應該是player = Player.new和player.equip(armbor)和player.hit(10),這些都是實例方法。 – Joelio 2011-01-29 12:16:15

+0

我想我已經有一些類似的東西了。我已經添加了所有我必須澄清的代碼。希望它是有道理的。 – 2011-01-29 12:27:49

1

這裏的問題是,你有一個@protection實例變量,但沒有「訪問」得到它。實例變量對於他們擁有的類的實例是私有的,所以如果你想將它們暴露給外部世界,你必須設置訪問器來這樣做。在這種情況下,你想:

class Armor 
    attr_reader :protection 
    ... 
end 

這將讓你打電話@armor.protection,並且將返回你的護甲實例的@protection變量的值。

2

我剛剛跑你的第二(完整)的例子。

除了存取問題在其他的答案解釋(剛加入attr_reader :protectionArmor),你忽略了一些在測試場景:)

錯誤消息給出了一個暗示:undefined method 'protection' for nil:NilClass (NoMethodError)。鑑於這是hit方法的第一行引起的,這意味着@armornil,當然nil不是Armor的實例,所以它沒有protection方法。爲什麼是零?好吧,看你的戰鬥如何開始的:

player1 = Player.new("Melanie", 100) 
player2 = Player.new("a Monster", 200) 
shirt = Armor.new('shirt', 4) 
player1.equip(shirt) 

只有梅蘭妮有一個襯衫,你給怪物沒有盔甲的一切!不是很公平,是嗎:)

要解決這個問題,你需要給他一些盔甲,或者改變你的hit方法,以便它在@armor沒有初始化時仍然有效。這樣做的一個很好的方式OO是初始化所有玩家使用默認的虛擬鎧甲是不提供任何保護:

class Player 
    def initialize(name, health) 
    @armor = Armor.new('nothing', 0) 
    # ... 

完成!現在


,因爲這虛擬的裝甲將是有益的無論你的遊戲的具體規則,我會摘要但從Player類,點通過使Armor類負責創建它,而不是:

class Armor 
    class << self # define a class method, like new 
    def none 
     self.new('nothing', 0) 
    end 
    end 
    # ... 

然後,你可以說Armor.none而不是Armor.new('nothing', 0)Player.initialize。這樣,如果您需要更改Armor的內部工作方式,則可以同時更新虛擬裝甲,而無需觸摸其他類。

相關問題