# Ehem... Gin Rummy hand counting...

## Recommended Posts

trellend    122
I'm making a gin rummy game, and I gotta get it live super fast, my players are going nuts... I ran into a problem.

333 789 KKKK - It calculates it just fine but if I have this:

5556789JQK - it calculates the run as 56789 leaving the 2 5's as non meld.

The way I do it is simple, and I'm looking for a better method.

Step 1: Remove the runs from the hand
Step 2: Remove the pairs (of 3-4) from the hand

I suppose its such a simple case I could reverse the process, and see what is lower, but I'm sure there is a split case where both ways wont work. Haven't found it yet.

Any ideas on a method to figure this out? Lang is java, but that dont matter if it's c/c++/c#/pascal, etc.

[Edited by - trellend on November 12, 2010 11:16:28 AM]

##### Share on other sites
I think what you'll need to do is identify cards that could be part of either a run or a group of 3/4 matching cards. You then need to try both options for each of those cards, and pick the best case.

Your worst case hand will probably be something like: 2223334445 which gives 3 cards that need to be tried both ways giving a total of 8 possibilities.

To save the need to detect which cards could be used either way up front, you could simply run through all 1024 ways of deciding between runs or pairs for each card.

##### Share on other sites
trellend    122
That sounds like the best way. Increment a counter, 0 is a run, 1 is a pair and then have each routine (run/pair) count the cards for the appropriate bit sequence, skip the others, then take lowest value of all 1024, and in some cases 2048.

Then I can optimize and take out all cases where there are not at least three bits as 1 or three bits as 0, knocking it down to 256 or 512.

That will work for now, good idea. Brute force, but hey it's java, it runs on the client...

moveOutRuns and moveOutPairs just move the cards if the find a run or pair. I left it as is and added this, and now I'm scoring properly. Thank you!

It's pretty slow, but it doesn't run often. The speed part of this was getting it up and running fast, not making the code actually execute fast...

    public static Point count(ArrayList<Card> icards, Card remove) {        ArrayList<Card> cards = new ArrayList<Card>();        ArrayList<Card> good = new ArrayList<Card>();        ArrayList<Card> cards4Pairs = new ArrayList<Card>();        ArrayList<Card> cards4Runs = new ArrayList<Card>();        cards.addAll(icards);        //Get rid of optional card to remove.        if (remove != null) {            cards.remove(remove);        }        Comparator<Card> ndo = new Gin.byNewDeckOrder();        Comparator<Card> ro = new Gin.byRankOrder();        int bestDead = 1000;        int bestScore = 0;        int max = 1 << cards.size();        int len = cards.size();        //This will loop 1024, more on 11 cards        for (int i = 0; i < max; i++) {            cards4Pairs.clear();            cards4Runs.clear();            good.clear();            //Split them into two sets of cards            for (int c = 0; c < len; c++) {                if ((i & (1 << c)) >= 1) {                    cards4Pairs.add(cards.get(c));                } else {                    cards4Runs.add(cards.get(c));                }            }            //Move out the runs, sort if 3+            if (cards4Runs.size() >= 3) {                Collections.sort(cards4Runs, ndo);                while (moveOutRuns(cards4Runs, good)) {                }            }            //Move out the pairs, sort if 3+            if (cards4Pairs.size() >= 3) {                Collections.sort(cards4Pairs, ro);                while (moveOutPairs(cards4Pairs, good)) {                }            }            //Calculate the deadwood            int deadwood = 0;            for (Card c : cards4Runs) {                deadwood += c.cardValue;            }            for (Card c : cards4Pairs) {                deadwood += c.cardValue;            }            //Now the score            int score = 0;            for (Card c : good) {                score += c.cardValue;            }            //Update the bestScore/bestDead            if (deadwood < bestDead) {                if (score > bestScore) {                    bestDead = deadwood;                    bestScore = score;                }            }        }        return new Point(bestDead, bestScore);    }

[Edited by - trellend on November 12, 2010 1:23:20 PM]