如何重构Ruby方法以通过Rubocop测试,同时保持干燥

如何重构Ruby方法以通过Rubocop测试,同时保持干燥,ruby,refactoring,Ruby,Refactoring,作为Launch学校课程的一部分,我正在制作一款21人游戏(可以将该游戏想象为21点的轻量级版本) 我需要正确地重构我自己的代码,以保持其干燥,同时通过所有Rubocop测试。我目前正在使用Rubocop版本0.85.0(本课程要求使用此版本) 在我的游戏中,我将所有数据存储在一个名为Keep Score的散列中: keep_score = { 'player_cards' => [], \ 'dealer_cards' => [], \

作为Launch学校课程的一部分,我正在制作一款21人游戏(可以将该游戏想象为21点的轻量级版本)

我需要正确地重构我自己的代码,以保持其干燥,同时通过所有Rubocop测试。我目前正在使用Rubocop版本0.85.0(本课程要求使用此版本)

在我的游戏中,我将所有数据存储在一个名为Keep Score的散列中:

keep_score = { 'player_cards' => [], \
               'dealer_cards' => [], \
               'player_card_values' => [], \
               'dealer_card_values' => [], \
               'player_points' => 0, \
               'dealer_points' => 0, \
               'player_move' => '', \
               'dealer_move' => '', \
               'end_game' => false }
到目前为止,我的代码可以正常工作,到目前为止,我已经做了很多重构,但是我需要进一步重构这两种方法,使代码更加枯燥,同时仍然通过Rubocop测试

我有两种方法,一种是
convert_face_cards
,它可以转换国王、王后和杰克(分别处理王牌)。然后有一个单独的方法,
添加整数值\u点
来处理卡片上的整数值:

def convert_face_cards(keep_score)
  keep_score['player_points'] = 0
  keep_score['dealer_points'] = 0

  keep_score['player_card_values'].each do |card|
    if card == "jack" || card == "queen" || card == "king"
      keep_score['player_points'] += 10
    end
  end
  keep_score['dealer_card_values'].each do |card|
    if card == "jack" || card == "queen" || card == "king"
      keep_score['dealer_points'] += 10
    end
  end
end

def add_integer_points(keep_score)
  keep_score['player_card_values'].each do |card|
    if card.is_a? Integer
      keep_score['player_points'] += card
    end
  end
  keep_score['dealer_card_values'].each do |card|
    if card.is_a? Integer
      keep_score['dealer_points'] += card
    end
  end
end
虽然这段代码从技术角度来看是有效的,但我没有通过Rubocop测试。
convert\u face\u cards
方法返回错误:
convert\u face\u cards的圈复杂度太高。[7/6]

我的代码显然没有可能的那么枯燥。例如,在
convert\u face\u cards
方法中,我基本上在
player\u card\u值
散列键和
dealer\u card\u值
散列键上以相同的方式运行
each
方法


但我不知道如何进一步浓缩这些方法。感谢您的帮助和指导

因为无论是玩家还是庄家,计算脸牌的逻辑都是相同的,所以你可以将其提取到自己的方法中,使事情变得更干枯

def convert_face_cards(keep_score)
  players = keep_score['player_card_values'].select { |card| card == "jack" || card == "queen" || card == "king" }
  dealers = keep_score['dealer_card_values'].select { |card| card == "jack" || card == "queen" || card == "king" }

  keep_score['player_points'] = players.length * 10
  keep_score['dealer_points'] = dealers.length * 10
end
def convert_face_cards(keep_score)
  keep_score['player_points'] = count_faces(keep_score['player_card_values'])
  keep_score['dealer_points'] = count_faces(keep_score['dealer_card_values'])
end

def sum_faces(cards)
  faces = cards.select { |card| face?(card) }
  faces.length * 10
end

def face?(card)
  %w[jack queen king].include?(card)
end

您不应该使用散列来存储此数据,也不应该编写在散列上循环的代码。您应该使用包含这些知识的数据结构作为方法

例如:

Card = Struct.new(:value) do
  def score
    case value
    when :king, :queen, :jack
      10
    when :ace
      1
    else
      value
    end
  end
end

CARDS = [
  :ace,
  :king,
  :queen,
  :jack,
  10,
  ... # other cards here
  2
].map { |card| Card.new(card) }

player_cards = []
dealer_cards = []

def score(cards)
  cards.sum(&:score)
end

这可能更简单,我们可以将卡片类型放入一个变量:。。。卡牌类型=%w(杰克·奎因·金)玩家=保留分数['player_card_values']。选择{卡牌{卡牌类型。包括?卡牌}。。。