Ruby Koans 182。重构帮助

Ruby Koans 182。重构帮助,ruby,Ruby,你能帮我重构我为Ruby Koans#182提出的解决方案吗?这是koan,您在其中编写了一个分数方法来计算贪婪游戏的分数。以下代码有效,所有测试都通过 然而,它感觉很长,不像红宝石。我怎样才能做得更好 def score(dice) rollGreedRoll = Hash.new rollRollCount = Hash.new (1..6).each do |roll| rollGreedRoll[roll] = roll == 1 ? GreedRoll.new(1000, 10

你能帮我重构我为Ruby Koans#182提出的解决方案吗?这是koan,您在其中编写了一个分数方法来计算贪婪游戏的分数。以下代码有效,所有测试都通过

然而,它感觉很长,不像红宝石。我怎样才能做得更好

def score(dice)
rollGreedRoll = Hash.new
rollRollCount = Hash.new
(1..6).each do |roll|
    rollGreedRoll[roll] = roll == 1 ? GreedRoll.new(1000, 100) :
            GreedRoll.new(  100 * roll, roll == 5 ? 50 : 0)
    rollRollCount[roll] = dice.count { |a| a == roll }
end


  score =0 


  rollRollCount.each_pair do |roll, rollCount|
    gr = rollGreedRoll[roll]  
    if rollCount < 3
        score += rollCount * gr.individualPoints
    else
        score += gr.triplePoints + ((rollCount - 3) * gr.individualPoints)

    end 
  end

  return score
end

class GreedRoll
    attr_accessor :triplePoints
    attr_accessor :individualPoints

    def initialize(triplePoints, individualPoints)
        @triplePoints = triplePoints
        @individualPoints = individualPoints
    end
end
def分数(骰子)
rollGreedRoll=Hash.new
rollcount=Hash.new
(1..6).每个都要滚动|
rollGreedRoll[roll]=roll==1?GreedRoll.新(1000100):
GreedRoll.new(100*roll,roll==5?50:0)
ROLLCOUNT[roll]=dice.count{| a | a==roll}
结束
分数=0
rollCount。每对都要滚动,滚动计数|
gr=rollGreedRoll[roll]
如果rollCount<3
分数+=滚动计数*gr.individualPoints
其他的
分数+=gr.triplePoints+((滚动计数-3)*gr.individualPoints)
结束
结束
回击得分
结束
格里德罗尔级
属性存取器:三个点
属性存取器:个人点
def初始化(三点、单个点)
@三点=三点
@单个点=单个点
结束
结束

您可以将RollCount放在第一个“each”中,不是吗?这样,您就不必在(1..6)上迭代两次。

我已经在上展示了重构的演练。最终解决方案如下所示:

def score(dice)
  (1..6).collect do |roll|
    roll_count = dice.count(roll)
    case roll
      when 1 : 1000 * (roll_count / 3) + 100 * (roll_count % 3)
      when 5 : 500 * (roll_count / 3) + 50 * (roll_count % 3)
      else 100 * roll * (roll_count / 3)
    end
  end.reduce(0) {|sum, n| sum + n}
end
注:
.reduce
的同义词。inject

下面是对它的另一种理解,将方法提取到它自己的类中。有点冗长,但易于阅读和理解:

def score(dice)
  GreedScore.new(dice).calculate
end
以及实施:

class GreedScore
  def initialize(dice)
    @values = dice.sort
  end

  def calculate
    @score = 0
    score_triples
    score_singles
    @score
  end

  private

  def score_triples
    (1..6).each do |match|
      if @values.count(match) >= 3
        @score += match * (match == 1 ? 1000 : 100)
        @values = @values.drop(3)
      end
    end
  end

  def score_singles
    @values.each do |value|
      @score += 100 if value == 1
      @score += 50 if value == 5
    end
  end
end

这就是我的方法。我使用了一个散列来表示性能,假设骰子的数量可以很大。另外,我喜欢尽可能使用
inject

def score(dice)
  tally = 0

  return tally if dice.length == 0

  hash = dice.inject(Hash.new(0)) { |h,v| h[v] += 1; h }

  (1..6).collect do |roll|
    case roll
    when 5
      tally += (hash[roll] / 3) * 500 + (hash[roll] % 3) * 50
    when 1
      tally += (hash[roll] / 3) * 1000 + (hash[roll] % 3) * 100
    else
      tally += (hash[roll] / 3) * roll * 100
    end
  end

  ap "dice = #{dice}, " + "hash = #{hash}, " + "tally = #{tally}"

  tally
end

这里会有更多的话题:谢谢,我不知道codereview网站。然而,它看起来仍然是测试版。看起来很棒。谢谢你花时间分享你的重构。我是个差劲的程序员。你能给我举个例子说明“骰子”参数是什么,以及“骰子数(掷)”会给你什么?我理解(1..6).collect等的用法。我很困惑,因为在我看来,(1..6).collect和dice参数在做同样的事情。请注意,我理解较长的答案(由Eric Hutzleman撰写),但你的答案对我来说很难理解。如果您能详细说明并提出意见,将不胜感激。