0

I'm stuck on this question where I need to compare two card objects based upon what rank and suit they are. Heart being the lowest suit, Spades the highest. And for Rank, One the lowest and Ace the highest. And 5 Spades being > 2 Hearts. These values are stored in two enums of their respective type. With Heart being the first ordinal and Spades the last ordinal.

@Override
    public int compareTo(Card o) {
        
        if(this.rank.ordinal() > o.rank.ordinal()) {
            return 1;
        }
        if (this.rank.ordinal() < o.rank.ordinal()) {
            return -1;
        } 
        else {
            return 0;
        }

In my comapreTo() I've implemented the comparing of the rank, but I'm stuck on THEN comparing the suit to find the greater card. This code fails once it goes past Ace of Hearts as it thinks 1 of clubs is higher. I've tried a bunch of different methods using if's but it just becomes convoluted and ugly and doesn't work anyways. Does anyone have any suggestions?

acidic231
  • 45
  • 6
  • 2
    Generally, you want to *first* compare the highest-relevance one (which seems to be rank) and *if* that is equal, then compare the next one (and so on, if there's more than two). So instead of `return 0` you just start another `if-then`-cascade comparing `suit`. Also: Using `Integer.compareTo` can simplify your code: `int result = Integer.compareTo(this.rank.ordinal(), o.rank.ordinal()); if (result == null) { /* further tests, assigning to result */ }; return result;` – Joachim Sauer May 12 '23 at 08:51
  • 2
    @JoachimSauer `result == null` always evaluates to false. I suppose you wanted `0`. – Hulk May 12 '23 at 08:55
  • @Hulk: absolutely, that was a brain-fart. – Joachim Sauer May 12 '23 at 09:05

3 Answers3

1

An alternative way would be to use the Comparator interface and its static factory methods introduced in Java8:

private final Comparator<Card> comparator = Comparator.comparingInt((Card card) -> card.rank.ordinal())
        .thenComparing((Card card) -> card.suit.ordinal());

You can then use this comparator directly, or through the overridden compareTo method:

@Override
public int compareTo(Card other) {
    return comparator.compare(this, other);
}

Since this question is also tagged with oop, I'll add that the whole comparison logic should belong to a card game, not to the card itself.

In other words, if this comparison is game-specific, you should avoid putting it inside your entity/model. Asa result, you'll be able to easily reuse the Card object for different card games.

Emanuel Trandafir
  • 1,526
  • 1
  • 5
  • 13
0

You can use Comparator.comparing:

I understand rank is having priority over the suit, so it can be done like:

import java.util.Comparator;

public class Cards {

  enum Suit {hearts, clubs, diamonds, spades}

  enum Rank {_2, _3, _4, _5, _6, _7, _8, _9, _10, joker, queen, king, ace,}

  record Card(Suit suit, Rank rank) implements Comparable<Card> {
    @Override
    public int compareTo(Card o) {
      return Comparator.comparing(Card::rank).thenComparing(Card::suit).compare(this, o);
    }
  }

  public static void main(String[] args) {
    var c1 = new Card(Suit.hearts, Rank.ace);
    var c2 = new Card(Suit.spades, Rank._2);
    System.out.println(c1.compareTo(c2));
  }
}
Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56
0

You can add the further comparison into the else:

@Override
    public int compareTo(Card o) {
        
        if(this.rank.ordinal() > o.rank.ordinal()) {
            return 1;
        }
        else if (this.rank.ordinal() < o.rank.ordinal()) {
            return -1;
        } 
        else {
            if (this.suit.ordinal() > o.suit.ordinal()) {
                return 1;
            }
            else if (this.suit.ordinal() < o.suit.ordinal()) {
                return -1;
            }
        }

        return 0;
    }

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175