重构Ruby二十一点游戏方法:通过Rubocop测试并保持DRY
重构思路与解决方案
首先,你的代码核心问题在于重复处理玩家和庄家的卡牌逻辑,这不仅违反DRY原则,还导致了Rubocop检测到的圈复杂度超标。我们可以通过提取通用的点数计算逻辑,将重复的代码抽象为可复用的辅助方法,同时合并冗余的步骤。
步骤1:提取通用点数计算方法
先写一个单独的方法,负责计算一组卡牌值(不管是玩家还是庄家的)对应的点数,把face card(J/Q/K)和整数卡牌的处理逻辑整合到一起:
def calculate_points(card_values) card_values.sum do |card| if %w[jack queen king].include?(card) 10 elsif card.is_a?(Integer) card else 0 # A的处理你提到单独进行,这里先返回0不影响后续单独计算 end end end
这里用Ruby的sum方法替代手动累加,代码更简洁,sum可以直接处理块返回的数值,比手动初始化变量再累加更符合Ruby风格。
步骤2:重构原有方法为单一更新逻辑
原来的convert_face_cards和add_integer_points其实是在完成同一个目标:计算并更新玩家和庄家的总点数。我们可以把它们合并成一个方法,直接调用上面的辅助方法:
def update_player_and_dealer_points(keep_score) keep_score['player_points'] = calculate_points(keep_score['player_card_values']) keep_score['dealer_points'] = calculate_points(keep_score['dealer_card_values']) end
为什么这样改进?
- 遵循DRY原则:玩家和庄家的点数计算逻辑完全复用同一个辅助方法,消除了重复的循环和条件判断。
- 降低圈复杂度:原来的
convert_face_cards有两个循环+两个条件判断,圈复杂度超标;现在辅助方法只有一个条件分支,主方法只是两次调用辅助方法,圈复杂度直接降到符合Rubocop 0.85.0的要求(≤6)。 - 代码可读性更高:方法名
update_player_and_dealer_points清晰表达了功能,辅助方法calculate_points的职责也单一明确。
替换原有代码
现在你可以移除原来的convert_face_cards和add_integer_points方法,在需要更新点数的地方调用update_player_and_dealer_points(keep_score)即可。如果A的点数处理需要单独调整,只需要在这个方法执行后,再添加处理A的逻辑即可(比如遍历卡牌值中的"A",根据当前点数调整加1还是11)。
内容的提问来源于stack exchange,提问作者Weston
相关产品推荐
相关产品推荐

