Poker question: How to give two values to the Ace
I'm dealing with a poker project and I'm finally at the final level. I need to program a straight ( for non-poker players, 5 cards where the order of their values is straight, ex 2,3,4,5,6). I think I got the logic pretty well except for the fact that I don't know what to do with the Ace. The ace has values 1 and 14 for convenience (ie, a straight could be A,2,3,4,5 and A,K,Q,J,10). I did 3 if statements and the program runs pretty well except that when I get an Ace the program crashes.
My idea was to do 3 ifs.
1. The first one uses the ace (and all numbers) as strings, put them in an array, sort them, and then allow the program to work with a,2,3,4,5 (as strings).
2. The second one was to use the ace as a string and allow the program to run with a,k,j,q,and ten. (also as strings).
3. Convert all of the other cards to ints, make an array of the ints, compute the following variables:
int a = numbers[4] - 1;
int b = numbers[3] - 1;
int c = numbers[2] - 1;
int d = numbers[1] - 1;
and then use the if statement:
else if (numbers[0].equals(d) && numbers[1].equals(c) && numbers[2].equals(b) && numbers[3].equals(a))
Could anyone give me an idea as to why the program crashes whenever I get an ace or give me an alternate solution to the problem?
Here is the full class (although it the focus should be in the addToTurnedCardsBuffer method):
Code :
import java.util.Arrays;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class StraightFlushLevel extends FullHouseLevel
{
// TRIO LEVEL: The goal is to find, on each turn, three cards with the same rank
protected StraightFlushLevel(TurnsTakenCounterLabel validTurnTime, JFrame mainFrame)
{
super(validTurnTime, mainFrame);
super.turnsTakenCounter.setDifficultyModeLabel("Straight Flush Level");
cardsToTurnUp = 5;
cardsPerRow = 10;
rowsPerGrid = 5;
}
@Override
protected void makeDeck()
{
// In Trio level the grid consists of distinct cards, no repetitions
ImageIcon cardIcon[] = this.loadCardIcons();
//back card
ImageIcon backIcon = cardIcon[TotalCardsPerDeck];
int cardsToAdd[] = new int[getRowsPerGrid() * getCardsPerRow()];
for(int i = 0; i < (getRowsPerGrid() * getCardsPerRow()); i++)
{
cardsToAdd[i] = i;
}
// randomize the order of the deck
this.randomizeIntArray(cardsToAdd);
// make each card object
for(int i = 0; i < cardsToAdd.length; i++)
{
// number of the card, randomized
int num = cardsToAdd[i];
// make the card object and add it to the panel
String rank = cardNames[num].substring(0, 1);
if(rank.equals("t"))
{
rank = "10";
}
else if (rank.equals("j"))
{
rank = "11";
}
else if (rank.equals("q"))
{
rank = "12";
}
else if (rank.equals("k"))
{
rank = "13";
}
String suit = cardNames[num].substring(1, 2);
this.grid.add( new Card(this, cardIcon[num], backIcon, num, rank, suit));
}
}
@Override
protected boolean addToTurnedCardsBuffer(Card card)
{
// add the card to the list
this.turnedCardsBuffer.add(card);
if(this.turnedCardsBuffer.size() == getCardsToTurnUp())
{
// We are uncovering the last card in this turn
// Record the player's turn
this.turnsTakenCounter.increment();
// get the other card (which was already turned up)
Card otherCard1 = (Card) this.turnedCardsBuffer.get(0);
Card otherCard2 = (Card) this.turnedCardsBuffer.get(1);
Card otherCard3 = (Card) this.turnedCardsBuffer.get(2);
Card otherCard4 = (Card) this.turnedCardsBuffer.get(3);
String value1 = card.getRank();
String value2 = otherCard1.getRank();
String value3 = otherCard2.getRank();
String value4 = otherCard3.getRank();
String value5 = otherCard4.getRank();
Integer num1 = Integer.parseInt(value1);
Integer num2 = Integer.parseInt(value2);
Integer num3 = Integer.parseInt(value3);
Integer num4 = Integer.parseInt(value4);
Integer num5 = Integer.parseInt(value5);
String[] cards = {value1, value2, value3, value4, value5};
Integer[] numbers = {num1, num2, num3, num4, num5};
Arrays.sort(cards);
Arrays.sort(numbers);
int a = numbers[4] - 1;
int b = numbers[3] - 1;
int c = numbers[2] - 1;
int d = numbers[1] - 1;
if( cards[0] == "2" && cards[1] == "3" && cards[2] == "4" && cards[3] == "5" && cards[4] == "a" )
{
this.turnedCardsBuffer.clear();
}
else if(cards[0] == "a" && cards[1] == "j" && cards[2] == "k" && cards[3] == "q" && cards[4] == "t")
{
this.turnedCardsBuffer.clear();
}
else if (numbers[0].equals(d) && numbers[1].equals(c) && numbers[2].equals(b) && numbers[3].equals(a))
{
this.turnedCardsBuffer.clear();
}
else
{
// The cards do not match, so start the timer to turn them down
this.turnDownTimer.start();
}
}
return true;
}
}
--- Update ---
Wow, just realized I made the mistake of naming local variable a just like the name of the card a. (int a = numbers[4] - 1;). I renamed it to aa but I still get an error. Here is the new code:
Code :
import java.util.Arrays;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class StraightFlushLevel extends FullHouseLevel
{
private String ace;
// TRIO LEVEL: The goal is to find, on each turn, three cards with the same rank
protected StraightFlushLevel(TurnsTakenCounterLabel validTurnTime, JFrame mainFrame)
{
super(validTurnTime, mainFrame);
super.turnsTakenCounter.setDifficultyModeLabel("Straight Flush Level");
cardsToTurnUp = 5;
cardsPerRow = 10;
rowsPerGrid = 5;
}
@Override
protected void makeDeck()
{
// In Trio level the grid consists of distinct cards, no repetitions
ImageIcon cardIcon[] = this.loadCardIcons();
//back card
ImageIcon backIcon = cardIcon[TotalCardsPerDeck];
int cardsToAdd[] = new int[getRowsPerGrid() * getCardsPerRow()];
for(int i = 0; i < (getRowsPerGrid() * getCardsPerRow()); i++)
{
cardsToAdd[i] = i;
}
// randomize the order of the deck
this.randomizeIntArray(cardsToAdd);
// make each card object
for(int i = 0; i < cardsToAdd.length; i++)
{
// number of the card, randomized
int num = cardsToAdd[i];
// make the card object and add it to the panel
String rank = cardNames[num].substring(0, 1);
if(rank.equals("t"))
{
rank = "10";
}
else if (rank.equals("j"))
{
rank = "11";
}
else if (rank.equals("q"))
{
rank = "12";
}
else if (rank.equals("k"))
{
rank = "13";
}
String suit = cardNames[num].substring(1, 2);
this.grid.add( new Card(this, cardIcon[num], backIcon, num, rank, suit));
}
}
@Override
protected boolean addToTurnedCardsBuffer(Card card)
{
// add the card to the list
this.turnedCardsBuffer.add(card);
if(this.turnedCardsBuffer.size() == getCardsToTurnUp())
{
// We are uncovering the last card in this turn
// Record the player's turn
this.turnsTakenCounter.increment();
// get the other card (which was already turned up)
Card otherCard1 = (Card) this.turnedCardsBuffer.get(0);
Card otherCard2 = (Card) this.turnedCardsBuffer.get(1);
Card otherCard3 = (Card) this.turnedCardsBuffer.get(2);
Card otherCard4 = (Card) this.turnedCardsBuffer.get(3);
String value1 = card.getRank();
String value2 = otherCard1.getRank();
String value3 = otherCard2.getRank();
String value4 = otherCard3.getRank();
String value5 = otherCard4.getRank();
Integer num1 = Integer.parseInt(value1);
Integer num2 = Integer.parseInt(value2);
Integer num3 = Integer.parseInt(value3);
Integer num4 = Integer.parseInt(value4);
Integer num5 = Integer.parseInt(value5);
String[] cards = {value1, value2, value3, value4, value5};
Integer[] numbers = {num1, num2, num3, num4, num5};
Arrays.sort(cards);
Arrays.sort(numbers);
int aa = numbers[4] - 1;
int b = numbers[3] - 1;
int c = numbers[2] - 1;
int d = numbers[1] - 1;
final String ace;
if( cards[0] == "2" && cards[1] == "3" && cards[2] == "4" && cards[3] == "5" && cards[4] == "a" )
{
this.turnedCardsBuffer.clear();
}
else if(cards[0] == "a" && cards[1] == "j" && cards[2] == "k" && cards[3] == "q" && cards[4] == "t")
{
this.turnedCardsBuffer.clear();
}
else if (numbers[0].equals(d) && numbers[1].equals(c) && numbers[2].equals(b) && numbers[3].equals(aa))
{
this.turnedCardsBuffer.clear();
}
else
{
// The cards do not match, so start the timer to turn them down
this.turnDownTimer.start();
}
}
return true;
}
}
Re: Poker question: How to give two values to the Ace
Re: Poker question: How to give two values to the Ace
Here's my take on the "Ace" issue. This is not specific to your code or your scheme for representing cards, but is a more general programming issue:
Sooner or later you are going to have a way of comparing hands that depends on rank of cards.
Ten-high straight beats 6-high straight.
K,5, 4,3,2 of Clubs beats Q,J,10,9,7 of Spades. Stuff like that.
Except for a "baby straight" where the Ace is low, every other standard poker hand will treat the Ace as highest rank. (Pair of Aces beats pair of deuces.)
Therefore: Let "Ace" be highest rank (14 in your scheme). The only time you have to do something "special" with an Ace is when you are checking to see whether the hand is a straight.
Note that for my program I would define the rank to have an integer value, not a String. Makes numeric comparisons more reasonable (to my way of thinking).
Anyhow...
When checking for a straight, sort the cards according to rank. Then it's easy to check whether the the values occur as five sequential numbers, in which case it's a "normal" straight. If it's not a "normal" straight, check for "baby straight" in a separate function (or a separate logical branch of the straight checker) that tests specifically for the sorted ranks being 2,3,4,5,14.
An evaluation of the numerical value of a baby straight would, somehow, have to yield a smaller value than any normal straight but higher than three-of-a-kind.
Cheers!
Z