2011-12-07 45 views
2

我試圖擺脫我的代碼中的重複。我有一個填充有跳棋棋盤的方法:Ruby:重構複雜的嵌套循環方法

def populate_checkers 
    evens = [0, 2, 4, 6] 
    odds = [1, 3, 5, 7] 

    0.upto(2) do |x_coord| 
    if x_coord.even? 
     evens.each do |y_coord| 
     red_checker = Checker.new(x_coord, y_coord, :red) 
     @board[x_coord][y_coord] = red_checker 
     end 
    elsif x_coord.odd? 
     odds.each do |y_coord| 
     red_checker = Checker.new(x_coord, y_coord, :red) 
     @board[x_coord][y_coord] = red_checker 
     end 
    end 
    end 

    5.upto(7) do |x_coord| 
    if x_coord.even? 
     evens.each do |y_coord| 
     black_checker = Checker.new(x_coord, y_coord, :black) 
     @board[x_coord][y_coord] = black_checker 
     end 
    elsif x_coord.odd? 
     odds.each do |y_coord| 
     black_checker = Checker.new(x_coord, y_coord, :black) 
     @board[x_coord][y_coord] = black_checker 
     end 
    end 
    end 
end 

如何刪除重複的,仍然可以得到精確的行爲,我需要什麼?

+0

備註:從功能編程的角度來看,這種代碼非常非常糟糕。你調用一個方法,並且「神奇地」一些實例變量(@board)被填充,唉,參考透明度會下山。更好的編寫獲取參數並返回內容的方法:'@board = build_board'。更多關於使用Ruby的FP:http://www.slideshare.net/tokland/functional-programming-with-ruby-9975242 – tokland

回答

3

你可以嘗試提取的方法,然後提取塊入λ。那麼你的代碼將是可讀的,鬆散的複製

def populate_checkers 
    0.upto(2) do |x_coord| 
    populate_checker(x_coord, :red) 
    end 

    5.upto(7) do |x_coord| 
    populate_checker(x_cord, :black) 
    end 
end 

def populate_checker(x_coord, color) 
    evens = [0, 2, 4, 6] 
    odds = [1, 3, 5, 7] 

    apply_checker = lambda do |y_coord| 
    checker = Checker.new(x_coord, y_coord, color) 
    @board[x_coord][y_coord] = checker 
    end 

    if x_coord.even? 
    evens.each(&apply_checker) 
    elsif x_coord.odd? 
    odds.each(&apply_checker) 
    end 
end 
2
def populate_checkers 
    evens = [0, 2, 4, 6] 
    odds = [1, 3, 5, 7] 

    [0.upto(2), 5.upto(7)].each_with_index do |enum, i| 
    enum.each do |x_coord| 
     (x_coord.even? ? evens : odds).each do |y_coord| 
     checker = Checker.new(x_coord, y_coord, i == 0 ? :red : :black) 
     @board[x_coord][y_coord] = checker 
     end 
    end 
    end 
end 

可能有更好的方法來做計數位,但這就是我得到的。

這裏有一個可能是更好的解決方案...

def populate_checkers 
    { :red => (0..2), :black => (5..7) }.each do |color, range| 
    range.each do |x_coord| 
     (x_coord.even? ? 0 : 1).step(7, 2) do |y_coord| 
     checker = Checker.new(x_coord, y_coord, color) 
     @board[x_coord][y_coord] = checker 
     end 
    end 
    end 
end 
1
0.upto(2) do |x| 
    0.upto(7) do |y| 
    @board[x][y]=Checker.new(x, y, :red) if (x+y).even? 
    end 
end 

這僅僅是紅魔的。