Ruby Koans 182。重构帮助
你能帮我重构我为Ruby Koans#182提出的解决方案吗?这是koan,您在其中编写了一个分数方法来计算贪婪游戏的分数。以下代码有效,所有测试都通过 然而,它感觉很长,不像红宝石。我怎样才能做得更好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
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撰写),但你的答案对我来说很难理解。如果您能详细说明并提出意见,将不胜感激。