Implement comparable with 2 Enums

冷暖自知 提交于 2020-01-17 09:11:11

问题


I'm creating a Java program that simulates a game of Hearts. I have a Card class that I created for another card game simulation:

public abstract class Card  implements Comparable<Card>{

    public enum Suits {
        SPADES,
        CLUBS,
        HEARTS,
        DIAMONDS
    }

    public enum Values {
        TWO,
        THREE,
        FOUR,
        FIVE,
        SIX,
        SEVEN,
        EIGHT,
        NINE,
        TEN,
        JACK,
        QUEEN,
        KING,
        ACE, 
    }

    private Suits suit;
    private Values value;

    public Card(final Values value, final Suits suit) {
        this.value = value;
        this.suit = suit;
    }

    public Values getValue() {
        return value;
    }

    public Suits getSuit() {
        return suit;
    }

    public void showCard() {
        value = getValue();
        suit = getSuit();

        System.out.println(value + " of " + suit);
    }

    private int compareTo(final Card comparedToCard) {
        //code here
    }

}

I need some assistance implementing the compareTo method. I have experience using this method, and how it should return 1, 0, or -1 based on how you want to compare you objects. However, I have never implemented it using enums before. I know the Enum class implements comparable but even after looking at API documentation I don't know how to compare two enums.

My desired result would be to sort an ArrayList<Card> in such a way that they would be sorted first by Suit: Club -> Diamond -> Spade -> Heart, and to also have them sorted by Value so: Club(2->Ace), Diamond(2->Ace), ect...

Any help would be much appreciated


回答1:


Enum already has a compareTo. This one depends on the ordinal value of the enum constant. The ordinal is given to enums in order of appearance.

For hearts and many games, the value of a card is however dependent on the state of the game. So although you can use the default compareTo of Values to compare cards of the same color, you still need to determine the actual value of a card within a turn. It doesn't make sense in hearts to use the order within the color. You certainly should not create a compareTo within the card class.

For card games, compareTo should be used with care, and should not be made dynamic. If the order is anything other than the default order in your question, then don't use it at all. Remember, compareTo is for comparisons within a set of elements with a natural order. In many card games the value of the cards fluctuate with the game, so there is no such natural order.


If you must, you can create a new Comparator for each turn though, this one simply favors any card that is of the same suite as the first card. As the first card should always be in the list of cards that are checked, there should always be a winner for a single pack of cards.

public class TurnComparator implements Comparator<Card> {
    private final Suits firstCardSuite;

    TurnComparator(Suits firstCardSuite) {
        this.firstCardSuite = firstCardSuite;
    }

    @Override
    public int compare(Card o1, Card o2) {
        if (o1.suit != firstCardSuite && o2.suit != firstCardSuite) {
            return 0;
        }

        if (o1.suit != firstCardSuite && o2.suit == firstCardSuite) {
            return -1;
        }


        if (o1.suit == firstCardSuite && o2.suit != firstCardSuite) {
            return 1;
        }

        return o1.value.compareTo(o2.value);
    }
}



回答2:


Every enum constant in Java as an associated ordinal value. This value can be accessed by invoking the ordinal() method on the constant, e.g. SPADE.ordinal().

Once all enum contacts have been arranged in ascending order of their value we can use ordinal to perform the kind of comparison you require.




回答3:


Enums have a natural order, so compare by the suit property and then by the value:

@Override
public int compareTo(Card o)
{
    return Comparator.comparing(Card::getSuit)
                     .thenComparing(Card::getValue)
                     .compare(this, o);
}

Or if you want a comparator:

Comparator<Card> comp = Comparator.comparing(Card::getSuit)
                                  .thenComparing(Card::getValue);


来源:https://stackoverflow.com/questions/27096288/implement-comparable-with-2-enums

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!