Search code examples
arraysactionscript-3sequencepoker

How to find all sequences of three in an array of values


first question ever here... I am coding a simple 3-card poker hand evaluator and am having problems finding/extracting multiple "straights" (sequential series of values) from an array of values.

I need to extract and return EVERY straight the array possibly has. Here's an example:

(assume array is first sorted numerically incrementing)

myArray = [1h,2h,3c,3h,4c]

Possible three-value sequences are: [1h,2h,3c] [1h,2h,3h] [2h,3c,4c] [2h,3h,4c]

Here is my original code to find sequences of 3, where the array contains card objects with .value and .suit. For simplicity in this question I just put "2h" etc here:

private var _pokerHand = [1h,2h,3c,3h,4c];
private function getAllStraights(): Array 
{
    var foundStraights:Array = new Array();
    for (var i: int = 0; i < (_handLength - 2); i++) 
    {
        if ((_pokerHand[i].value - _pokerHand[i + 1].value) == 1 && (_pokerHand[i + 1].value - _pokerHand[i + 2].value) == 1) 
        {
            trace("found a straight!");
            foundStraights.push(new Array(_pokerHand[i], _pokerHand[i + 1], _pokerHand[i + 2]));
        }
    }
    return foundStraights;
}

but it of course fails when there are value duplicates (like the 3's above). I cannot discard duplicates because they could be of different suits. I need every possible straight as in the example above. This allows me to run the straights through a "Flush" function to find "straight flush".

What array iteration technique am I missing?


Solution

  • This is an interesting problem. Given the popularity of poker games (and Flash) I'm sure this has been solved many times before, but I couldn't find an example online. Here's how I would approach it:

    • Look at it like a path finding problem.
    • Begin with every card in the hand as the start of a possible path (straight).
    • While there are possible straights:
      • Remove one from the list.
      • Find all the next valid steps, (could be none, or up to 4 following cards with the same value), and for each next valid step:
        • If it reaches the goal (completes a straight) add it to a list of found straights.
        • Otherwise add the possible straight with the next step back to the stack.

    This seems to do what you want (Card object has .value as int):

    private function getAllStraights(cards:Vector.<Card>, straightLength:uint = 3):Vector.<Vector.<Card>> {
        var foundStraights:Vector.<Vector.<Card>> = new <Vector.<Card>>[];
    
        var possibleStraights:Vector.<Vector.<Card>> = new <Vector.<Card>>[];
        for each (var startingCard:Card in cards) {
            possibleStraights.push(new <Card>[startingCard]);
        }
    
        while (possibleStraights.length) {
            var possibleStraight:Vector.<Card> = possibleStraights.shift();
            var lastCard:Card = possibleStraight[possibleStraight.length - 1];
            var possibleNextCards:Vector.<Card> = new <Card>[];
            for (var i:int = cards.indexOf(lastCard) + 1; i < cards.length; i++) {
                var nextCard:Card = cards[i];
                if (nextCard.value == lastCard.value)
                    continue;
                if (nextCard.value == lastCard.value + 1)
                    possibleNextCards.push(nextCard);
                else
                    break;
            }
            for each (var possibleNextCard:Card in possibleNextCards) {
                var possibleNextStraight:Vector.<Card> = possibleStraight.slice().concat(new <Card>[possibleNextCard]);
                if (possibleNextStraight.length == straightLength)
                    foundStraights.push(possibleNextStraight);
                else
                    possibleStraights.push(possibleNextStraight);
            }
        }
    
        return foundStraights;
    }
    

    Given [1♥,2♥,3♣,3♥,4♣] you get: [1♥,2♥,3♣], [1♥,2♥,3♥], [2♥,3♣,4♣], [2♥,3♥,4♣]

    It gets really interesting when you have a lot of duplicates, like [1♥,1♣,1♦,1♠,2♥,2♣,3♦,3♠,4♣,4♦,4♥]. This gives you:

    [1♥,2♥,3♦], [1♥,2♥,3♠], [1♥,2♣,3♦], [1♥,2♣,3♠], [1♣,2♥,3♦], [1♣,2♥,3♠], [1♣,2♣,3♦], [1♣,2♣,3♠], [1♦,2♥,3♦], [1♦,2♥,3♠], [1♦,2♣,3♦], [1♦,2♣,3♠], [1♠,2♥,3♦], [1♠,2♥,3♠], [1♠,2♣,3♦], [1♠,2♣,3♠], [2♥,3♦,4♣], [2♥,3♦,4♦], [2♥,3♦,4♥], [2♥,3♠,4♣], [2♥,3♠,4♦], [2♥,3♠,4♥], [2♣,3♦,4♣], [2♣,3♦,4♦], [2♣,3♦,4♥], [2♣,3♠,4♣], [2♣,3♠,4♦], [2♣,3♠,4♥]

    I haven't checked this thoroughly but it looks right at a glance.