我是编程新手,但我很想学习,所以请原谅这个问题。我创造了这个游戏的东西,以帮助我学习OOP,我遇到了部分问题。这就是导致我出现问题的原因:
我有两节课。在Player类的第3行,我有一些可能错误的代码,但基本上,我正在尝试做的是使用armor来修改玩家受到的伤害。我收到一个错误:“nil的未定义方法'保护':NilClass(NoMethodError)
我将Armor作为另一个班级。我认为这个问题可能与我在Armor中提到保护并且在Player中提到@armor时调用@ armor.protection的事实有关,但我不确定如何解决这个问题。我在下面添加了我认为与我的问题相关的所有代码。就像我说的那样,我对此非常陌生,所以请使用noob可以理解的术语。
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
答案 0 :(得分:3)
如果你的Armor类有一个protection
方法,它会正常工作。但它没有,所以即使你从Armor
类中调用它,你也会得到同样的错误。要定义它,您可以使用attr_reader
或attr_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
答案 1 :(得分:2)
我刚刚运行了你的第二个(完整)示例。
除了存取问题在其他的答案解释(刚加入attr_reader :protection
类Armor
),你忽略了在测试场景中的东西:)
错误消息提示:undefined method 'protection' for nil:NilClass (NoMethodError)
。考虑到这是在hit
方法的第一线引起的,此装置@armor
是nil
,当然nil
不是的一个实例Armor
,所以它没有protection
方法。为什么没有?好吧,看看你的战斗是如何开始的:
player1 = Player.new("Melanie", 100)
player2 = Player.new("a Monster", 200)
shirt = Armor.new('shirt', 4)
player1.equip(shirt)
只有梅兰妮有一件衬衫,你根本没给了怪物任何盔甲!不太公平,是吧:)。
要解决这个问题,您可能需要给他一些盔甲,或者改变您的hit
方法,使其没有初始化@armor
时仍然有效。这样做的一个好方法是使用默认的虚拟装甲初始化所有玩家,不提供任何保护:
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
内部的工作方式,您可以同时更新虚拟装甲,而无需触及其他类。
答案 2 :(得分:1)
试试这个:
player = Player.new
armor = Armor.new('Mythril', 100)
player = player.equip(armor) #Initialise the armor object inside Player.
player.hit(10)
答案 3 :(得分:1)
这里的问题是你有一个@protection
实例变量,但没有“访问者”可以访问它。实例变量对于它们所拥有的类的实例是私有的,因此如果要将它们暴露给外部世界,则必须设置访问器来执行此操作。在这种情况下,您需要:
class Armor
attr_reader :protection
...
end
这样您就可以致电@armor.protection
,并返回您的护甲实例@protection
变量的值。