Java开发Scopa卡牌游戏时如何消除玩家统计逻辑的重复代码
解决方法
你三个方法的核心差异仅为每个玩家的计数规则,遍历玩家、比较最大值、平局返回空的逻辑完全一致,只需要把可变的计数规则抽为参数传入通用方法即可消除重复。
步骤1:抽取通用查询方法
Java 8及以上版本可以直接使用java.util.function.ToIntFunction作为计数规则的参数类型:
import java.util.function.ToIntFunction; // 通用方法:按传入的计数规则返回唯一最高计数的玩家,平局返回空 private Optional<Player> playerWithHighestCount(ToIntFunction<Player> countCalculator) { Player scoringPlayer = null; int maxCount = 0; for (Player p : players) { final int count = countCalculator.applyAsInt(p); if (count > maxCount) { scoringPlayer = p; maxCount = count; } else if (count == maxCount) { scoringPlayer = null; } } return Optional.ofNullable(scoringPlayer); }
如果需要兼容Java 8以下版本,可以自定义函数式接口替代:
// 自定义计数规则接口 @FunctionalInterface interface PlayerCountCalculator { int getCount(Player p); } // 对应通用方法参数换成自定义接口即可 private Optional<Player> playerWithHighestCount(PlayerCountCalculator calculator) { // 内部逻辑和上面完全一致 }
步骤2:简化原有三个方法
直接调用通用方法传入对应计数规则即可,原有逻辑完全不变:
private Optional<Player> playerWithMostCards() { return playerWithHighestCount(p -> p.pile.size()); } private Optional<Player> playerWithMostSevens() { return playerWithHighestCount(p -> { int count = 0; for (Card c : p.pile) { if (c.is(Card.Value.SEVEN)) count++; } return count; }); } private Optional<Player> playerWithMostSpades() { return playerWithHighestCount(p -> { int count = 0; for (Card c : p.pile) { if (c.is(Card.Suit.SPADES)) count++; } return count; }); }
如果允许用Stream语法,计数部分还可以进一步简化:
// 最多7点的实现可简化为 return playerWithHighestCount(p -> (int)p.pile.stream().filter(c -> c.is(Card.Value.SEVEN)).count()); // 最多黑桃的实现可简化为 return playerWithHighestCount(p -> (int)p.pile.stream().filter(c -> c.is(Card.Suit.SPADES)).count());
效果
原有updateScores方法无需任何修改,所有业务逻辑和之前完全一致,后续新增同类最高计数加分规则时,仅需新增一行调用通用方法的代码即可,无需重复编写遍历比较逻辑。
内容的提问来源于stack exchange,提问作者Picarrow
相关产品推荐
相关产品推荐

