Reputation: 189
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
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
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
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