我如何摆脱所有这些重复代码?

How do I get rid of all this duplicate code?

    private Optional<Player> playerWithMostCards()
    {
        Player scoringPlayer = null;
        int maxCount = 0;

        for(Player p : players)
        {
            final int count = p.pile.size();

            if(count > maxCount)
            {
                scoringPlayer = p;
                maxCount = count;
            }
            else if(count == maxCount)
            {
                scoringPlayer = null;
            }
        }

        return Optional.ofNullable(scoringPlayer);
    }

    private Optional<Player> playerWithMostSevens()
    {
        Player scoringPlayer = null;
        int maxCount = 0;

        for(Player p : players)
        {
            int count = 0;

            for(Card c : p.pile)
            {
                if(c.is(Card.Value.SEVEN))
                {
                    count++;
                }
            }

            if(count > maxCount)
            {
                scoringPlayer = p;
                maxCount = count;
            }
            else if(count == maxCount)
            {
                scoringPlayer = null;
            }
        }

        return Optional.ofNullable(scoringPlayer);
    }

    private Optional<Player> playerWithMostSpades()
    {
        Player scoringPlayer = null;
        int maxCount = 0;

        for(Player p : players)
        {
            int count = 0;

            for(Card c : p.pile)
            {
                if(c.is(Card.Suit.SPADES))
                {
                    count++;
                }
            }

            if(count > maxCount)
            {
                scoringPlayer = p;
                maxCount = count;
            }
            else if(count == maxCount)
            {
                scoringPlayer = null;
            }
        }

        return Optional.ofNullable(scoringPlayer);
    }
    
    private Optional<Player> playerWithSevenOfSpades()
    {
        for(Player p : players)
        {
            for(Card c : p.pile)
            {
                if(c == new Card("7S"))
                {
                    return Optional.of(p);
                }
            }
        }

        return Optional.empty();
    }

    private void updateScores()
    {
        for(Player p : players)
        {
            p.score = p.scopas;
        }

        playerWithMostCards().ifPresent(p -> p.score += 1);
        playerWithMostSevens().ifPresent(p -> p.score += 1);
        playerWithMostSpades().ifPresent(p -> p.score += 1);
        playerWithSevenOfSpades().ifPresent(p -> p.score += 1);
    }

基本上,我正在制作纸牌游戏(称为 Scopa),当调用 updateScores() 时,应该更新每个玩家的分数。玩家可以通过持有最多的牌、最多的 7 或黑桃 7 来获得积分。确定谁拥有最多的牌、7 和黑桃的逻辑非常相似。如何避免在这三种方法中重复逻辑?谢谢。

对于最后两个,你可以做一个函数。我不熟悉您使用的编程语言(我什至不知道它是哪种语言 - 请下次标记您的问题),但它看起来像这样:

private Optional<Player> playerWithMostCards()
{
    Player scoringPlayer = null;
    int maxCount = 0;

    for(Player p : players)
    {
        final int count = p.pile.size();

        if(count > maxCount)
        {
            scoringPlayer = p;
            maxCount = count;
        }
        else if(count == maxCount)
        {
            scoringPlayer = null;
        }
    }

    return Optional.of(scoringPlayer);
}

private Optional<Player> playerWithMost([type] cvalue) // I don't know what the type of Card.[Value/Suit].[SEVEN/SPADES] is.
{
    Player scoringPlayer = null;
    int maxCount = 0;

    for(Player p : players)
    {
        int count = 0;

        for(Card c : p.pile)
        {
            if(c.is(cvalue))
            {
                count++;
            }
        }

        if(count > maxCount)
        {
            scoringPlayer = p;
            maxCount = count;
        }
        else if(count == maxCount)
        {
            scoringPlayer = null;
        }
    }

    return Optional.of(scoringPlayer);
}
private Optional<Player> playerWithSevenOfSpades()
{
    for(Player p : players)
    {
        for(Card c : p.pile)
        {
            if(c == new Card("7S"))
            {
                return Optional.of(p);
            }
        }
    }

    return Optional.empty();
}

private void updateScores()
{
    for(Player p : players)
    {
        p.score = p.scopas;
    }

    playerWithMostCards().ifPresent(p -> p.score += 1);
    playerWithMost(Card.Value.SEVEN).ifPresent(p -> p.score += 1);
    playerWithMost(Card.Suit.SPADES).ifPresent(p -> p.score += 1);
    playerWithSevenOfSpades().ifPresent(p -> p.score += 1);
}

我不确定如何将最上面的那个集成到函数中。

另一种解决方案是只做一个函数来计算分数。您循环播放玩家列表 4 次,循环播放卡片 3 次。你只需要一个玩家循环和一个卡片循环来检查所有内容。

像这样:

private void updateScores()
    {
        Player playerWithMostCards = null;
        Player playerWithMostSevens = null;
        Player playerWithMostSpades = null;
        int mostCards = 0;
        int mostSevens = 0;
        int mostSpades = 0;

        for(Player p : players)
        {
            // Most cards
            final int playerPileSize = p.pile.size();            

            if(playerPileSize > mostCards)
            {
              playerWithMostCards = p;
              mostCards = playerPileSize;
            }
            else if(playerPileSize == mostCards)
            {
              playerWithMostCards = null;
            }

            // NumberOfSevens and Spades
            int numberOfSevens = 0
            int numberOfSpades = 0

            for(Card c : p.pile)
            {
                if(c.is(Card.Value.SEVEN))
                {
                  numberOfSevens++;
                }

                if(c.is(Card.Suit.SPADES))
                {
                    numberOfSpades++;
                }
            }

            if (numberOfSevens > maxSevens) {
              playerWithMostSevens = p
              mostSevens = numberOfSevens              
            } else if (numberOfSevens == maxSevens) {
              playerWithMostSevens = null
            }

             if (numberOfSpades > maxSpades) {
              playerWithMostSpades = p
              mostSevens = numberOfSpades              
            } else if (numberOfSpades == maxSpades) {
              playerWithMostSpades = null
            }
        }

        playerWithMostCards.score += 1;
        playerWithMostSevens.score += 1;
        playerWithMostSpades.score += 1;      

    }

我还没有测试过这个,但这显示了粗略的想法。你可以通过添加最后一个功能来练习。

我不喜欢我想出的方法的名称,但这是我经过一段时间后得出的结果。它大大减少了我拥有的代码量,并且具有同样多的灵活性,如果不是更多的话。如果您能为“playerBestMatching”想出一个更好的名称,请告诉我,我可以对此进行编辑。

编辑:“playerBestMatching”现在是“playerWithMostCardsMatching”

    private Optional<Player> playerWithMostCardsMatching(
        final Predicate<Card> predicate)
    {
        Player scoringPlayer = null;
        int maxCount = 0;

        for(Player p : players)
        {
            final int count = (int)p.pile.stream()
                                         .filter(predicate)
                                         .count();

            if(count > maxCount)
            {
                scoringPlayer = p;
                maxCount = count;
            }
            else if(count == maxCount)
            {
                scoringPlayer = null;
            }
        }

        return Optional.ofNullable(scoringPlayer);
    }

    private void updateScores()
    {
        for(Player p : players)
        {
            p.score = p.scopas;
        }

        playerWithMostCardsMatching(c -> true).ifPresent(p -> p.score += 1);
        playerWithMostCardsMatching(c -> c.is(Card.Value.SEVEN)).ifPresent(p -> p.score += 1);
        playerWithMostCardsMatching(c -> c.is(Card.Suit.SPADES)).ifPresent(p -> p.score += 1);
        playerWithMostCardsMatching(c -> c == new Card("7S")).ifPresent(p -> p.score += 1);
    }