Ruby Beginner - 访问另一个类对象

时间:2014-05-01 13:33:22

标签: ruby

我正在尝试在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."

然后,我将攻击转变为一个函数(我必须使变量全局化,因此函数可以看到它们):

$player = "goodguy"
$player_health = 15
$player_damage = 5

$enemy = "badguy"
$enemy_health = 15
$enemy_damage = 5

def player_attack
  puts "#{$player} attacks #{$enemy} and does #{$player_damage} damage."
  $enemy_health -= $player_damage
  puts "#{$enemy} has #{$enemy_health} health remaining."
  if $enemy_health <= 0
    puts "#{$enemy} died!"
  end    
end    

player_attack()

接下来,我将Player变成了一个类:

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 #{$enemy}!"
    $enemy_health -= @damage
    puts $enemy_health
  end
end

$enemy = "badguy"
$enemy_health = 15
$enemy_damage = 5    

me = Player.new("goodguy", 15, 5)

me.attack

这是我被卡住的地方。当我将Enemy转换为一个类(基本上在Player类之后完全建模)时,我无法弄清楚如何使两个对象相互交互。这段代码不起作用,但这是我尝试过的最后一段。 #{}变量更能显示我想要发生的事情而不是其他任何事情:

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 

基本上,我想要做的是使Player对象可以与Enemy对象进行交互。当我尝试让两个班级互相交流时,我似乎无法使其工作;另外,#{variable.name}并不是我试图让函数报告这些值的唯一方法,但我似乎无法找到如何实际引用该对象。

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

2 个答案:

答案 0 :(得分:4)

由于PlayerEnemy的所有代码都相同,我可以在父类中对它们进行建模(给它一个愚蠢的名字Man,你可以给它一些奇特的名字: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

答案 1 :(得分:4)

正如@JacobM所提到的,你遇到的问题与你的类无法在不明确地将它们作为参数传递的情况下知道彼此的其他实例有关。虽然您使用全局变量来保存对敌人和玩家的引用的初步解决方法是可行的,但强烈建议不要这样做,因为它会在整个游戏体中“泄漏”程序的逻辑,这通常是不受欢迎的(有关为何要避免它们的详细解释,请参阅Global Variables are Bad。)

从代码中删除$后,playerattack方法中定义后成为局部变量:

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

在此构造中,要作为player类的实例引用的Player变量实际上是您在方法体中声明的未定义局部变量。由于您的PlayerEnemy类的代码相同,我建议您创建一个超类来保存此逻辑:

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

然后为PlayerEnemy创建子类

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