Ruby初学者-访问另一个类对象

Ruby初学者-访问另一个类对象,ruby,Ruby,我试图在Ruby中创建一个简单的回合制战斗,但在涉及到类时,我总是陷入困境。我试图通过从基本代码开始并围绕它构建它来实现这一点。通过使用正则变量和基本攻击代码,我可以让它简单地工作: player = "goodguy" player_health = 15 player_damage = 5 enemy = "badguy" enemy_health = 15 enemy_damage = 5 puts "#{player} attacks #{enemy} and does #{play

我试图在Ruby中创建一个简单的回合制战斗,但在涉及到类时,我总是陷入困境。我试图通过从基本代码开始并围绕它构建它来实现这一点。通过使用正则变量和基本攻击代码,我可以让它简单地工作:

player = "goodguy"
player_health = 15
player_damage = 5

enemy = "badguy"
enemy_health = 15
enemy_damage = 5

puts "#{player} attacks #{enemy} and does #{player_damage} damage."
enemy_health -= player_damage
puts "#{enemy} has #{enemy_health} remaining."
然后,我将攻击转化为一个函数(我必须使变量成为全局变量,以便函数可以看到它们):

这就是我被卡住的地方。当我把
敌人
变成一个类(基本上完全按照
玩家
类建模)时,我不知道如何使这两个对象相互作用。这段代码不起作用,但这是我最后一次尝试。
#{}
变量比任何其他变量更能显示我试图实现的目标:

class Player
  attr_accessor :name; :hp; :damage
  def initialize(name, hp, damage)
    @name = name
    @hp = hp
    @damage = damage
  end

  def attack
    puts "#{self.name} attacks #{badguy.name}!"
    badguy.hp -= @damage
    puts badguy.hp
  end
end

class Enemy
  attr_accessor :name; :hp; :damage
  def initialize(name, hp, damage)
    @name = name
    @hp = hp
    @damage = damage
  end

  def attack
    puts "#{self.name} attacks #{goodguy.name}!"
    player.hp -= @damage
    puts player.hp
  end
end  

goodguy = Player.new("Nicehero", 15, 5)
badguy = Enemy.new("Eviljerk", 15, 5)

me.attack 
基本上,我想做的是使
玩家
对象可以与
敌人
对象交互。当我试图让两个类彼此交互时,我似乎无法实现这一点;另外,#{variable.name}并不是我试图让函数报告这些值的唯一方法,但我似乎找不到如何实际引用该对象


显然,对于对象如何交互,或者我的代码在做什么,以及我认为它应该做什么,我缺少了一些东西。我将非常感谢任何关于让这两个类进行交互的建议,或者如何重写这两个类以使其按预期运行的建议

由于
玩家
敌人
的所有代码都是相同的,我可以在父类中对它们进行建模(给它一个哑名
,你可以给它一个奇特的名字:D)删除所有代码重复,而不是从公共类继承

两个对象之间可以有多种交互方式。我在
attack
函数中传递另一个对象并开始与它交互,这是最简单的方法

我将按以下方式更改此代码:

class Man
    attr_accessor :name, :hp, :damage
    def initialize(name, hp, damage)
        @name = name
        @hp = hp
        @damage = damage
    end

    def attack opposite_team_man
        puts "#{self.name} attacks #{opposite_team_man.name}!"
        opposite_team_man.hp -= @damage
        puts opposite_team_man.hp
    end

end
class Player < Man
end

class Enemy < Man
end  

goodguy = Player.new("Nicehero", 15, 5)
badguy = Enemy.new("Eviljerk", 15, 5)

goodguy.attack badguy
class-Man
属性访问器:名称,:hp,:损坏
def初始化(名称、生命值、损坏)
@name=name
@马力=马力
@损坏=损坏
结束
def攻击对手队队员
放上“{self.name}攻击{covert\u team\u man.name}!”
对方团队人。生命-=@伤害
把对手放在队伍里
结束
结束
职业选手
结束
阶级仇人
结束
goodguy=玩家。新建(“Nicehero”,15,5)
坏人=敌人。新(“邪恶混蛋”,15,5)
好人,攻击坏人

正如@JacobM所提到的,您遇到的问题与您的类在没有将它们作为参数显式传递的情况下无法了解彼此的其他实例有关。虽然您最初使用全局变量来保存对敌人和玩家的引用是可行的,但强烈反对这种做法,因为它会在游戏的整个过程中“泄漏”程序的逻辑,这通常是不可取的(有关为什么要避免它们的详细解释,请参阅)

通过从代码中删除
$
player
attack
方法中定义时成为局部变量:

def attack
  puts "#{self.name} attacks #{goodguy.name}!"
  player.hp -= @damage
  puts player.hp
end
在这种构造中,要作为
player
类的实例引用的
player
变量实际上是在方法体中声明的未定义局部变量。因为你的
玩家
敌人
类的代码是相同的,我建议你创建一个超类来保存这个逻辑:

class Piece
  attr_accessor :name, :hp, :damage
  def initialize(name, hp, damage)
    @name = name
    @hp = hp
    @damage = damage
  end

  def attack(opponent)
    opponent.hp -= @damage
    puts "#{@name} attacks #{opponent.name}!"
    puts "#{opponent.name}'s HP: #{opponent.hp}"
  end
end
然后为
玩家
敌人
创建子类:

class Player < Piece
end

class Enemy < Piece
end
class-Player
使用此结构,您可以创建任意数量的敌人和碎片,并让它们彼此单独交互:

> hero = Player.new("Zeus", 1000, 100)
=> #<Player:0x007fbd33958498 @name="Zeus", @hp=1000, @damage=100> 
> goul = Enemy.new("Pariah", 400, 50)
=> #<Enemy:0x007fbd33949b78 @name="Pariah", @hp=400, @damage=50>
> ghost = Enemy.new("Bane", 600, 75)
=> #<Enemy:0x007fbd33937680 @name="Bane", @hp=600, @damage=75> 


> hero.attack(goul)
Zeus attacks Pariah!
Pariah's HP: 300
=> nil
英雄=Player.new(“宙斯”,1000100) => # >goul=敌人。新(“贱民”,400,50) => # >幽灵=敌人。新(“灾祸”,600,75) => # >英雄攻击(goul) 宙斯攻击贱民! 贱民的生命:300 =>零
这些类不会神奇地知道彼此的实例;一些实体必须告诉他们。一种常见的方法是使用另一个类来表示游戏或棋盘,该类负责对(比如)玩家说,“轮到你了,敌人来了,敌人做了什么,你会做什么?”谢谢@JacobM,你能举个例子说明如何使用父类执行此操作吗#{contract_team_man.name}!正在工作,但随后我得到了一个
未定义的#(nomethoderor)方法“hp”
当我尝试运行这个时。知道为什么吗?啊,因为,这应该是
属性访问器:name,:hp,:damage
,更新了答案。哎呀!我使用的是
,而不是
,这很有意义,它的工作原理与我想要的完全一样。谢谢你的帮助!
class Player < Piece
end

class Enemy < Piece
end
> hero = Player.new("Zeus", 1000, 100)
=> #<Player:0x007fbd33958498 @name="Zeus", @hp=1000, @damage=100> 
> goul = Enemy.new("Pariah", 400, 50)
=> #<Enemy:0x007fbd33949b78 @name="Pariah", @hp=400, @damage=50>
> ghost = Enemy.new("Bane", 600, 75)
=> #<Enemy:0x007fbd33937680 @name="Bane", @hp=600, @damage=75> 


> hero.attack(goul)
Zeus attacks Pariah!
Pariah's HP: 300
=> nil