# Play Cards

Posted by JH

## Play Cards

Card game rule: the hand is drawn from a pack of cards (no jokers).
Play cards ONLY when they are

3 of a kind (...AAA... ) or 4 of a kind(...AAAA...).

a straight flush of 3 or more cards(...JQK... or ...A23456…... in the same suit).

Find out whether the player will be able to play the whole hand drawn.

## Solution

For every card, we will try to play it by the rules given. If the way of playing does not work, backtrack to the previous state and try another way. For example,

Given hand
[Diamond A, Club A, Heart A, Spade A, Diamond 2, Diamond 3]

Return true on [Diamond A, Club A, Spade A] + [Heart A, Spade A, Club A].

Above is a simple example of backtracking of just 2 levels (level 0 and level 1). The more straight flushes and N of a kind there is in the hand, the more levels of recursion it needs.

Edge cases

A special case to look at is the card Ace. Ace can be in a straight of A, 2, 3..., or Q, K, A.
But there is no such thing like ...K, A, 2 ....

General cases

At every given card, we will try to find All combinations that starts with it. For example for Spade A, try for
3 types of 3 of a kind
[Spade A, Hearth A, Diamond A]
[Spade A, Club A, Diamond A]
[Spade A, Hearth A, Club A]

4 of a kind
[Spade A, Hearth A, Diamond A, Club A]

all the straight flushes with a length greater than 2
... all the way till Spade K if there is no missing rank in the middle
If a rank in middle is missing, stop searching for longer straights.

## Implementation

``````//input a 4X13 matrix with 4 suits and 13 ranks of cards. set cards[suit][rank] to 1 if this card in hand.
public static boolean handClear(int[][] cards, int hand) {
if(hand == 0) return true;
for(int rank = 12; rank >= 0; rank--) {
for(int suit = 0; suit < 4; suit++) {
if(cards[suit][rank] == 1) { //if cards[suit][rank] in hand
cards[suit][rank] = 0; hand--;
int smallerRank = rank == 0 ? 12: rank - 1; // look for straight flush that end with this card
// watch for Ace as a special case that ***QKA and A23*** both valid
if(cards[suit][smallerRank] == 1) {
cards[suit][smallerRank] = 0; hand--;
int r = smallerRank - 1;
for(; r >= 0 && cards[suit][r] == 1; r--) {   //try playing the straight flush found
cards[suit][r] = 0; hand--;
if(handClear(cards, hand)) return true;
}
r++;
for(; r <= smallerRank; r++) {  //backtrack if play did not work
cards[suit][r] = 1; hand++;
}
}
//look for 3/4 of a kind for cards[suit][rand]
int n = cards[0][rank] + cards[1][rank] + cards[2][rank] + cards[3][rank];
if(n == 3 || n == 2) {
int tmp1 = cards[(suit + 1) % 4][rank],
tmp2 = cards[(suit + 2) % 4][rank],
tmp3 = cards[(suit + 3) % 4][rank];
cards[(suit + 1) % 4][rank] = 0; //try playing the 3/4 of a kind
cards[(suit + 2) % 4][rank] = 0;
cards[(suit + 3) % 4][rank] = 0;
hand -= n;
if(handClear(cards, hand)) return true;
cards[(suit + 1) % 4][rank] = tmp1;   //backtrack if play did not work
cards[(suit + 2) % 4][rank] = tmp2;
cards[(suit + 3) % 4][rank] = tmp3;
hand += n;
}
cards[suit][rank] = 1; hand++;
}
}
}
return false;
}
``````