2011-07-18 71 views
2

你能幫我重構我爲Ruby Koans#182提出的解決方案嗎?這是你寫一個評分方法來計算貪婪遊戲點數的公文。以下代碼工作並通過所有測試。Ruby Koans 182.重構幫助

但是,它感覺很長並且非紅寶石般。我怎樣才能讓它變得更好?

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 
+0

會更主題在這裏:http://codereview.stackexchange.com/ –

+0

謝謝,我不知道codereview網站。不過,它看起來仍然處於測試階段。 – Alper

回答

6

我已經在https://gist.github.com/1091265上安排了重構演練。最終的解決方案是這樣的:

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

+0

看起來不錯。感謝您花時間分享您的重構。 – Alper

+0

我是一個蹩腳的程序員。你可以給我一個「骰子」參數的例子,以及「dice.count(roll)」會給你什麼?我理解(1..6).collect等的使用。我很困惑,因爲在我看來,(1..6).collect和骰子參數正在做同樣的事情。請注意,我瞭解更長的答案(由Eric Hutzleman提供),但你對我來說非常密集。如果你能評論一下,我們將不勝感激。 – Leahcim

3

你可以把rollRollCount放在第一個「each」裏面,對不對?然後你不必迭代(1..6)兩次。

+0

啊是的。謝謝Wes。 – Alper

2

的代名詞這裏的另一個走就可以了,提取方法變成自己的類。一個小長篇大論,但容易閱讀和理解:

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 
+0

這絕對是更容易閱讀。謝謝埃裏克。 – Alper

+0

謝謝你。 – Leahcim

1

這裏是我的方法。假設骰子的數量可能很大,我使用散列表示性能。另外,我喜歡儘可能使用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