Skip to main content
GameDev.net gamedev.net
🔒 Locked

Java sort cards tips?

Started by loachman Jul 24, 2008 at 6:55 AM 17 replies 8.5k views
Original Post
loachman
loachman
Hi, I am making a card game (Poker) I have everything implemented up to the final sort. What I plan on doing is sorting the arrayList by numbers using substring, and then after the sort.Putting the suit into on array and the number into another. I was wondering the best way to go about this a bubble sort of some sort? Here is my psuedo code of sorts.

private void bubsort(){
     // I have an array List defined
     //private List<String> finalHand = new ArrayList<String>();
     //Which contains the following
     //{h9,c7,h13,h3,c2}
     //hearts=h,clubs=c,d=diamonds,spades=s although no spades or c in this hand
     I was wondering if I could bubble sort this using a substring(?,?)so I would sort the cards on only the numbers.

Then when I break it into two arrays would be
   array1=[c,h,c,h,h]
   array2=[2,3,7,9,13]
This makes is easy to check for flushes and straights etc....
Hope that makes sense. I know the basic theory to do this I think, Btw I am coming over to java from actionscript. Thanks
loachman
loachman
Hi,
Thanks for the reply. I had looked into the collections before.

public static void sort(List list,Comparator c)

But I am not clear on how it works? The comparator I assume is what I want to compare but how would I get it to compare by the numbers and not the aplha part ot the "string/card".

I think maybe I would have to do a cast to an int perhaps?

Thanks
DevFred
DevFred
A string is not a card. Maybe you should write a Card class first, or a Card enum.
loachman
loachman
I am too far into my game to re-write it really.

I am nearly finished. the reason I posted into the beginners forum was to get help with what I've got.

A know a String is not a card. But the string represents a card to me.

I simply want help to sort what I've got.

I'm not trying to sound rude but really this is for learning and I'll get to the card class eventually.


Thanks
DevFred
DevFred
Okay, I'm working on it. What happens if you have the same numbers of different suits, let's say four sevens. How must they be sorted, or does it not matter?
loachman
loachman
No it does not matter if I have four 7's. I just need them in order from lowest to highest.

Thanks
DevFred
DevFred
OK, then all you need is a custom comparator that only compares the numbers (which have to be parsed from the string), then you can use Collections.sort.
After that you can extract the relevant information into two arrays. Don't copy and paste, see if you can understand it and then write it yourself:

import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.Comparator;import java.util.List;class PokerComparator implements Comparator<String>{	public int compare(String s1, String s2)	{		int rank1 = Integer.parseInt(s1.substring(1));		int rank2 = Integer.parseInt(s2.substring(1));		return rank1 - rank2;	}}public class Poker{	public static void main(String[] args)	{		List<String> finalHand = new ArrayList<String>(Arrays.asList(new String[] { "h9", "c7", "h13", "h3", "c2" }));		Collections.sort(finalHand, new PokerComparator());		System.out.println(finalHand);		final int numberOfCards = finalHand.size();		char suits[] = new char[numberOfCards];		int ranks[] = new int[numberOfCards];		for (int i = 0; i < numberOfCards; ++i)		{			String s = finalHand.get(i);			suits = s.charAt(0);			ranks = Integer.parseInt(s.substring(1));		}	}}
OrangyTang
OrangyTang
Quote:
Original post by loachman
Hi,
Thanks for the reply. I had looked into the collections before.

public static void sort(List list,Comparator c)

But I am not clear on how it works? The comparator I assume is what I want to compare but how would I get it to compare by the numbers and not the aplha part ot the "string/card".

I think maybe I would have to do a cast to an int perhaps?

Thanks


You have to write a comparator which will compare the strings representing cards yourself. Something like:

class CardComparator implements Comparator{  public int compare(Object left, Object right)  {    String leftStr = (String)left;    String rightStr = (String)right;    int leftCardNum = Integer.parseString( leftStr.substr(1, 2);    int rightCardNum = Integer.parseString( rightStr.substr(1, 2);    return rightCardNum - leftCardNum;}Collections.sort(cardsList, new CardComparator());


(disclaimer: typed off the top of my head, probably doesn't work but should be enough to get you started)

Edit: I type too slowly. [grin]
Marmin
Marmin
Why not make an array [1..52] of a Byte. Representing the deck.
Sort these. http://www.gamedev.net/community/forums/topic.asp?topic_id=430793

A card has properties:
number
suit


Afterwards, you can set up data that points to these cards.
make a player class.

A player card has the properties:
pointer (to a card of the deck)
etc, etc.
loachman
loachman
Thanks both for your replys, I am sure I will get it sorted you're classes are very similiar.

Thanks

DevFred
DevFred
Quote:
Original post by OrangyTang
(disclaimer: typed off the top of my head, probably doesn't work but should be enough to get you started)

a) use generics
b) substring(1, 2) doesn't work for numbers above 9
c) your comparator will sort in descending order

But still not bad for off the top of your head ;)
loachman
loachman
Hi,

Fred I understand it now.

public static void sort(List list,Comparator c)

I was not aware that Comparator was a class or method or whatever. I simply thought I could pass a string and substring it.

Thanks!
OrangyTang
OrangyTang
Quote:
Original post by DevFred
Quote:
Original post by OrangyTang
(disclaimer: typed off the top of my head, probably doesn't work but should be enough to get you started)

a) use generics
b) substring(1, 2) doesn't work for numbers above 9
c) your comparator will sort in descending order

But still not bad for off the top of your head ;)

Heh, unfortunately it looks like I'll be stuck in generic-less 1.4 land for a while - there's still a lot of macs out there that don't have 1.5 installed. [sad]

Good catch on the rest though, ta!

DevFred
DevFred
Back when I wrote a hearts clone, I represented a hand as one number of type long (64 bits) where I only used the lowest 52 bits. For every card that was in the hand, I simply set the corresponding bit. A few examples:

0 -> the empty hand
1 -> the 2 of diamonds
2 -> the 3 of diamonds
4 -> the 4 of diamonds
8 -> the 5 of diamonds
16 -> the 6 of diamonds
32 -> the 7 of diamonds
64 -> the 8 of diamonds
128 -> the 9 of diamonds
256 -> the jack of diamonds
...
25 -> 1 + 8 + 16 -> the 2, 5 and 6 of diamonds
...
4503599627370495 -> the full hand, all 52 cards

That way I saved a lot of space and didn't have to worry about sorting, because the hand is always sorted by definition :)
DevFred
DevFred
Hm, thinking more about your approach, I wouldn't explicitly sort the cards but define a sording order instead and use a data structure that is always sorted.

We need an enum Suit, an enum Card and a class Hand:

package cards;public enum Suit{	DIAMONDS, HEARTS, SPADES, CLUBS;		public final String string;		Suit()	{		string = name().toLowerCase();	}		public String toString()	{		return string;	}}


package cards;import java.util.Comparator;public enum Card{	D2, D3, D4, D5, D6, D7, D8, D9, D10, DJ, DQ, DK, DA,	H2, H3, H4, H5, H6, H7, H8, H9, H10, HJ, HQ, HK, HA,	S2, S3, S4, S5, S6, S7, S8, S9, S10, SJ, SQ, SK, SA,	C2, C3, C4, C5, C6, C7, C8, C9, C10, CJ, CQ, CK, CA;		public final Suit suit;	public final int rank;	public final String string;		Card()	{		suit = Suit.values()[ordinal() / 13];		int index = ordinal() % 13;		rank = 2 + index;		string = Dummy.ranks[index] + " of " + suit;	}	public String toString()	{		return string;	}}class Dummy{	// can't use static array within initializer of Card, dang...	public static final String[] ranks = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "jack", "queen", "king", "ace"};}class RankComparator implements Comparator<Card>{	public int compare(Card a, Card b)	{		if (a.rank != b.rank) return a.rank - b.rank;		else return a.suit.compareTo(b.suit); 	}}


package cards;import java.util.Collection;import java.util.Comparator;import java.util.Iterator;import java.util.TreeSet;public class Hand implements Iterable<Card>{	private Collection<Card> cards;	// normal constructor, natural ordering	public Hand(Card... start)	{		cards = new TreeSet<Card>();		for (Card card: start)			addCard(card);	}		// copy constructor, natural ordering	public Hand(Hand hand)	{		cards = new TreeSet<Card>();		for (Card card: hand)			addCard(card);	}		// normal constructor, custom ordering	public Hand(Comparator<Card> comparator, Card... start)	{		cards = new TreeSet<Card>(comparator);		for (Card card: start)			addCard(card);	}		// copy constructor, custom ordering	public Hand(Hand hand, Comparator<Card> comparator)	{		cards = new TreeSet<Card>(comparator);		for (Card card: hand)			addCard(card);	}		public boolean hasCard(Card card)	{		return cards.contains(card);	}		public void addCard(Card card)	{		assert !hasCard(card);		cards.add(card);	}	public void removeCard(Card card)	{		assert hasCard(card);		cards.remove(card);	}	// allows easy iteration over cards from hand	public Iterator<Card> iterator()	{		return cards.iterator();	}		// nice string representation of the hand	public String toString()	{		return cards.toString();	}}


Note how the client code gets much smaller:

package cards;public class Poker{	public static void main(String[] args)	{		Hand hand = new Hand(Card.H9, Card.C7, Card.HK, Card.H3, Card.C2);		System.out.println(hand);		Hand finalHand = new Hand(hand, new RankComparator());		System.out.println(finalHand);	}}


That should get you started towards a nice OO approach.
loachman
loachman
Hi,

Thanks for that I will definately look into it more

When I run the System.out.prinln(suits.toString()) and System.out.println(ranks.toString) it prints a bunch of gibberish like it wrote to unkown memory or something. Notice I I am declaring the finalHand.
public void sortFinal(){					finalHand.clear();				for(int i=0;i<5;i++){			finalHand.add(theCards.get(i));		}		Collections.sort(finalHand, new PokerComparator());				for (int i = 0; i < finalHand.size(); ++i)		{			String s = finalHand.get(i);			suits = s.charAt(0);			ranks = Integer.parseInt(s.substring(1));		}}

However System.out.println(finalHand.toString) works like expected they are in order.
Thanks
DevFred
DevFred
Quote:
Original post by loachman
When I run the System.out.prinln(suits.toString()) and System.out.println(ranks.toString) it prints a bunch of gibberish

That's because arrays don't override the toString() method inherited from Object. Simply loop over the arrays and print every element, or write:
System.out.println(java.util.Arrays.toString(suits));System.out.println(java.util.Arrays.toString(ranks));
loachman
loachman
Aha

Thanks!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.