根据比较选择红宝石中的哈希值

时间:2011-03-13 03:50:08

标签: ruby-on-rails ruby

请看一下这段代码:

fighter =  [:str => 2, :dex => 3, :mag => 3, :acc => 2, :hp => 2]
ranger =   [:str => 3, :dex => 2, :mag => 3, :acc => 2, :hp => 2]
magician = [:str => 3, :dex => 3, :mag => 2, :acc => 2, :hp => 2]
rate = Hash.new

if user.first_class == 'Fighter' then rate = fighter end
if user.first_class == 'Ranger' then rate = magician end
if user.first_class == 'Magician' then rate = ranger end

cost = Hash.new
cost[:str] = (user.strength_points + 1) * rate[:str]
cost[:dex] = (user.dexterity_points + 1) * rate[:dex]
cost[:mag] = (user.magic_points + 1) * rate[:mag]
cost[:acc] = (user.accuracy_points + 1) * rate[:acc]
cost[:hp]  = (user.health_points + 1) * rate[:hp]
cost

这驻留在我已经创建的函数中,当我在Rails中执行它时,我得到一个“符号作为数组索引”。我猜这是因为率=战士,率=魔术师或率=游侠的可能性。也许我必须使用克隆。

我的问题是,基于if比较选择哈希的更好方法是什么,做上述事情?

4 个答案:

答案 0 :(得分:5)

您正在创建一个Array,其中一个条目是Hash

fighter =  [:str => 2, :dex => 3, :mag => 3, :acc => 2, :hp => 2]
=> [{:str=>2, :dex=>3, :mag=>3, :acc=>2, :hp=>2}]

您打算做的只是创建一个Hash

fighter = {:str => 2, :dex => 3, :mag => 3, :acc => 2, :hp => 2}
=> {:str=>2, :dex=>3, :mag=>3, :acc=>2, :hp=>2}

此外,使用if语句代替三个case语句:

rate = case user.first_class
  when "ranger"
    ranger
  when "magician"
    magician
  when "fighter"
    fighter
end

答案 1 :(得分:3)

这可能不是整理代码的最佳方式。我建议将用户的第一个类存储为执行计算的对象。这是一种更面向对象的方法:

class User
  def first_class= klass
    @first_class = klass.new(self)
  end

  def first_class
    @first_class
  end
end

class FirstClass
  attr_accessor :user

  def initialize user
    @user = user
  end

  def cost
    { :str => (user.strength_points + 1)*rate[:str],
      :dex => (user.dexterity_points + 1) * rate[:dex],
      :mag => (user.magic_points + 1) * rate[:mag],
      :acc => (user.accuracy_points + 1) * rate[:acc],
      :hp  => (user.health_points + 1) * rate[:hp] }
  end
end

然后,您可以定义第一类类型:

class Fighter < FirstClass
  def rate
    {:str => 2, :dex => 3, :mag => 3, :acc => 2, :hp => 2}
  end
end

class Magician < FirstClass
  def rate
    {:str => 3, :dex => 3, :mag => 2, :acc => 2, :hp => 2}
  end
end

class Ranger < FirstClass
  def rate
    {:str => 3, :dex => 2, :mag => 3, :acc => 2, :hp => 2}
  end
end

然后你可以调整你的功能:

user.first_class.cost

请记住,您还必须将第一个类设置为对象:

user.first_class = Fighter

但我认为这看起来更干净,更面向对象并大大降低了代码的复杂性。

答案 2 :(得分:1)

您遇到问题,因为您将战斗机/游侠/魔术师设置为单个元素哈希列表。

你想:

fighter =  {:str => 2, :dex => 3, :mag => 3, :acc => 2, :hp => 2}
ranger =   {:str => 3, :dex => 2, :mag => 3, :acc => 2, :hp => 2}
magician = {:str => 3, :dex => 3, :mag => 2, :acc => 2, :hp => 2}

答案 3 :(得分:1)

将汇率放入哈希值

rates = {
  "fighter" => { :str => 2, :dex => 3, :mag => 3, :acc => 2, :hp => 2 },
  "ranger" => { :str => 3, :dex => 2, :mag => 3, :acc => 2, :hp => 2 },
  "magician" => { :str => 3, :dex => 3, :mag => 2, :acc => 2, :hp => 2 }
}

rate = rates[user.first_class.downcase]

你也使用了方形而不是花括号,这使得数组而不是散列。

(另一个提示,你可以像以下那样更容易地执行单行if语句:my_number = 10 if my_number > 10