Cola4ever
Cola4ever

Reputation: 189

Sorting deck of Cards using custom sorting algorithms

I am trying to implement different sorting algorithms on a deck of cards. I've implemented a base card class using enums to build the suits and faces. My class is based on Dietel's & Dietel's Java Book. However, I am struggling in passing the deck of cards into the sorting algorithms I implemented as I am not able to pass in an array which I can sort. I don't know if my approach is correct, I've read many of the posts on stackexchange where some recommend using Comparable (Implementing a Deck of Cards in Java) which I can't see working with my sorting algorithms. See (How to Sort the Cards. (Is my code wrong?)) and (Implementing a Deck of Cards in Java) and (Java Sorting object in ArrayList). By having the DeckOfCards return a sequence of numbers e.g. 1.1, 1.2, 1.3, I think I have a sequence which can be sorted. I also read about ordinals but all the comments on those seemed to oppose the approach. Appreciate any help on this attempt. Kindly note, that I've implemented merge sort and selection sort in the same way and its the same problem - I am clearly missing something here!

Below is my code:

//Card class

class Card
{    
     //public static enum Face {Ace, Deuce, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King};
     public static enum Face {Ace(1), King(2), Queen(3), Jack(4), Ten(5), Nine(6), Eight(7), Seven(8), Six(9), Five(10), Four(11), Three(12), Deuce(13);
     int rank;
     Face(int r){ rank = r;}
     int getRank() {return rank;}
}
//public static enum Suit {Clubs, Diamonds, Hearts, Spades };
public static enum Suit {Spades(1), Hearts(2), Diamonds(3), Clubs(4);
   int order;
   Suit(int o){ order = o;}
   int getOrder() {return order;}
}

private final Face face; // face of card
private final Suit suit; // suit of card

// two-argument constructor
public Card( Face cardFace, Suit cardSuit ) 
{   
    face = cardFace; // initialize face of card
    suit = cardSuit; // initialize suit of card
}

// return face of the card
public Face getFace() { return face;}

// return suit of Card
public Suit getSuit() { return suit;}

// return String representation of Card
public String toString()
{
   //return String.format( "%s.%s", suit.getOrder(), face.getRank() );
   return String.format( "%s.%s", suit, face );
}
}

 // class DeckOfCards declaration
 public class DeckOfCards 
{
   private List< Card > list; // declare List that will store Cards

   // set up deck of Cards and shuffle
   public DeckOfCards()
  {
     Card[] deck = new Card[ 52 ];
     int count = 0; // number of cards

     // populate deck with Card objects
     for ( Card.Suit suit : Card.Suit.values() )  
     {
         for ( Card.Face face : Card.Face.values() )   
        {
            deck[ count ] = new Card( face.getRank(), suit.getOrder() );
            count++;
        }
     }

     list = Arrays.asList( deck ); // get List
     //Collections.shuffle( list );  // shuffle deck
   }

   // output deck
   public void printCards()
  {
      // display 52 cards in two columns
      for ( int i = 0; i < list.size(); i++ )
      System.out.printf( "%-20s%s", list.get( i ),
          ( ( i + 1 ) % 2 == 0 ) ? "\n" : "" );
  }

  public static void main( String[] args )
 {
     DeckOfCards cards = new DeckOfCards();
     cards.printCards();
    //cards.InsertionSort();    
 }
 }

//Insertion Sort

public static void insertionSort(DeckOfCards[] listToSort) 
{
    for (int i = 0; i < listToSort.length-1; i++) 
    {
        for (int k = i+1; k>0; k--) 
       {
           if(listToSort[k] < listToSort[k-1]) //Code breaks here
           {
                swap(listToSort, k, k-1);
            }
            else 
            {
                break;
            }
            print(listToSort);
        }
    }
}

Upvotes: 1

Views: 11667

Answers (3)

parthibd
parthibd

Reputation: 1

The proper approach would be to split the whole deck into suits and then sort each suite individually. Your version of insertion sort is not working because the sorting is done using the face values i.e aces, 2,3,4 ... And I wouldn't count this as sorting a deck .

private HashMap<Suite,ArrayList<Cards>> deck ;

//scan through the whole deck

for(int i = 0;i < 52; ++i) {

    `switch(cards[i]) {`

      `case Aces :`
        deck.put(Suite.Aces,cards[i]) ;
        break;
    .....
}

}

//Now sort

sort(deck.get(Suite.Aces)) ;

sort(deck.get(Suite.Diamond)) ;

Upvotes: -1

avojak
avojak

Reputation: 2360

The issue is that listToSort[k] < listToSort[k-1] is attempting to compare two DeckOfCards objects using the < operator, which is not allowed in Java - See: Compare two objects with or operators in Java.


As that post points out, you should instead be using a Comparator for the Card objects.

public class CardComparator implements Comparator<Card> {
    @Override
    public int compare(Card o1, Card o2) {
        // ...
        // Use Card.getFace().getRank() and Card.getSuit().getOrder()
        // ...
    }
}

In your DeckOfCards class, I'd also recommend adding a method such as:

public List<Card> getCards() { ... }

which returns a List of the cards in the deck. Then, in your insertionSort method, instead of listToSort[k], you would have listToSort.getCards().get(k). Also, instead of using < you can use a new instance of your CardComparator to determine whether or not to swap the cards.

public static void insertionSort(DeckOfCards cardsToSort) {
    final Comparator cardComparator = new CardComparator();
    for (int i = 0; i < cardsToSort.size() - 1; i++) {
        for (int k = i + 1; k > 0; k--) {
            final Card card1 = cardsToSort.getCards().get(k);
            final Card card2 = cardsToSort.getCards().get(k - 1);
            if(cardComparator.compare(card1, card2) < 0) {
                swap(cardsToSort, k, k-1);
            } else {
                break;
            }
        }
    }
} 

Upvotes: 3

Tom
Tom

Reputation: 1221

listToSort is an array of DeckOfCards. On the line indicated with //Code breaks here you're trying to compare two DeckOfCards objects, which you just can't do in java (Operator overloading in other languages would allow you do do this).

How about you write a method, such as .getSortValue() to give you a value to sort it by. Alternatively you could write something to compare the values within the card like:

if(listToSort[k].getSuit().getOrder()*13+listToSort[k].getFace().getOrder() < listToSort[k- 1].getSuit().getOrder()*13+listToSort[k-1].getFace().getOrder())

...which is a bit long, but I would assume does what you want.

Note the *13 means that each combination of suit and face is unique

TLDR: If you want to sort it in any other order, you'll have to come up with a value from each card that you can compare properly

Upvotes: 1

Related Questions