问题
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