03-23-2005, 10:30 AM | #1 (permalink) |
Guest
|
[java] Contiguous Array Test
I'm writing a client-server poker-tournament game (which I later want to extend to playing other games) and have started on the part where the system analyses the hand a given player has.
I have a jCard object that represents a card. A player's hand is represented by a jHand object that contains a Stack, which contains a set of jCards. jCard properties are: String suit; (Text version of suit, i.e. "Clubs", "Diamonds" etc) String code; (2 char code 1st Char = suit, 2nd char = value - i.e. HK = King of Hearts) int value; 1-13 (Aces through Kings) So, I've another object called a jHandAnalyser that has a number of methods for checking what a hand might be worth. The main property of this object is a jHand reference called myHand. Calling the constructor of jHandAnalyser passes in the hand you want to analyse. e.g. jHandAnalyser aPlayer = new jHandAnalyser(aHand); This jHandAnalyser needs to look at the jHand object it's given and decide what the hand is worth. So far I have a method called isFlush() that returns true if the cards are all of the same suit, but am wondering how to implement the isStrait (sp?) method. i.e. I want to check that all the cards are in a sequential run. Has anyone got any ideas how I can do this nice and cleanly? |
03-23-2005, 11:12 AM | #2 (permalink) |
Once upon a time...
|
you could make sure the cards are always sorted,
then check the run length from [0] to length.
__________________
-- Man Alone ======= Abstainer: a weak person who yields to the temptation of denying himself a pleasure. Ambrose Bierce, The Devil's Dictionary. |
03-23-2005, 11:34 AM | #4 (permalink) |
Tilted
|
I would say if you sort the hand it may be easier, but here is a non-sorted method I came up with, in honor of the IOCCC -- meaning it isn't obvious what I'm doing, maybe you can figure it out.
This is assuming a 5 card hand, if you are doing other sized hands You'll need to modify the check phase steps 7+. I haven't tested this, but I think it is correct Code:
1. int val = 0; 2. int lowest = Integer.MAX_VALUE; 3. for each card value { 4. val = val | (1 << card.value); 5. lowest = Math.min(card.value, lowest); 6. } 7. if (val == 0x3C02) return true; 8. val = val >> lowest; 9. return val == 0x1F; |
03-23-2005, 11:45 AM | #6 (permalink) |
Guest
|
it can't be high and low in a straight, but it can be high or low in a hand - so A2345 and TJQKA could both be valid straights.
If an ace is given value 1 (i.e. aces are low), then i can start increment-testing my card-values from 1, it it's high, then I can assume a value of 14, and expect it at the end of any straights - but if it's simultaneously 1 and 14, I'm going to need to do some special coding for it (which I'd rather avoid, but which looks unavoidable at the mometn) a-j is that bit-shifting you're doing there? That's not a bad idea at all - any hand could be held as a 52 bit bitmask. The only problem is squeezing in cards of the same value but different suits... |
03-23-2005, 12:03 PM | #7 (permalink) |
Guest
|
I've just gone away and had a think about this, and think that using a bitmask is genius!
so each card value is assigned a bit i.e. Code:
[ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][1] = Ace [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][1][ ] = Duece [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][1][ ][ ] = 3 [ ][ ][ ][ ][ ][ ][ ][ ][ ][1][ ][ ][ ] = 4 [ ][ ][ ][ ][ ][ ][ ][ ][1][ ][ ][ ][ ] = 5 [ ][ ][ ][ ][ ][ ][ ][1][ ][ ][ ][ ][ ] = 6 [ ][ ][ ][ ][ ][ ][1][ ][ ][ ][ ][ ][ ] = 7 [ ][ ][ ][ ][ ][1][ ][ ][ ][ ][ ][ ][ ] = 8 [ ][ ][ ][ ][1][ ][ ][ ][ ][ ][ ][ ][ ] = 9 [ ][ ][ ][1][ ][ ][ ][ ][ ][ ][ ][ ][ ] = 10 [ ][ ][1][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ] = Jack [ ][1][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ] = Queen [1][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ] = King Then, all the cards in a hand are ORed into a hand array [ ][ ][ ][ ][ ][ ][1][ ][ ][ ][ ][ ][ ] = 7 [ ][ ][ ][ ][ ][1][ ][ ][ ][ ][ ][ ][ ] = 8 [ ][ ][ ][ ][1][ ][ ][ ][ ][ ][ ][ ][ ] = 9 [ ][ ][ ][1][ ][ ][ ][ ][ ][ ][ ][ ][ ] = 10 [ ][ ][1][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ] = Jack [ ][ ][1][1][1][1][1][ ][ ][ ][ ][ ][ ] = All Cards Now by finding the first 1 and the last one, and filling in the gaps, I should be able to make a mask. [ ][ ][1][1][1][1][1][ ][ ][ ][ ][ ][ ] = Mask Now if I XOR the mask and the card array, I should always get zero if there is a straight, or something else if not. |
03-24-2005, 09:40 AM | #11 (permalink) |
Guest
|
OK, I've got it to work and put in an acesHiLow variable (-1 for low, 0 for either or 1 for high) and this should work as a test to see if all the cards in a given hand are in a run.
Where aces are high or low, the thing only works for 5-card hands, but hopefully I'll work out a way to fix it so it will work for any number of cards. Code:
public boolean isStrait(int acesHiLow){ boolean isstrait = false; int maskval = 1; int val = 0; int lowest = Integer.MAX_VALUE; for (int i = 0; i< myHand.size();i++) { if (acesHiLow == -1 || myHand.card(i).value != 1){ val = val | (1 << myHand.card(i).value); maskval = maskval << 1; lowest = Math.min(myHand.card(i).value, lowest);} if (acesHiLow == 0 && myHand.card(i).value == 1){ val = val | (1 << myHand.card(i).value); val = val | (1 << 14); maskval = maskval << 1; maskval = maskval << 1; lowest = Math.min(myHand.card(i).value, lowest);} if (acesHiLow == 1 && myHand.card(i).value == 1){ val = val | (1 << 14); maskval = maskval << 1; lowest = Math.min(14, lowest);} } val = val >> lowest; if (val + 1 == maskval){return true;} if ((acesHiLow == 0 && val == 8223) || (acesHiLow == 0 && val == 15873)){return true;} // System.out.println(val + " " + maskval ); return false; } |
Tags |
array, contiguous, java, test |
|
|