pythonalgorithmrecursionblackjackplaying-cards

Algorithm to find all possible blackjack hands


I'm trying to write a function in Python that takes a list of card values and a list of values in the players hand and will return a list of all possible hands that the player can end up with that have a value of 17 or higher. The cards are represented by an integer that corresponds with the value of the card (2-10, aces are always 11. All face cards are worth 10). This is the function I have tried to write. deck is a list of integers representing the cards that are still in the deck (3 cards are missing, 2 in the player's hand and one for the dealer). runninglist is a list of integers representing the cards in the player's hand. playerPossibilities is a list of hands that have a sum of 17 or higher.

def simPlayerHelper(deck, runningList, playerPossibilities):
    for card in deck:    
        runningList.append(card)
        if sum(runningList) > 16:
            temp_rl = runningList.copy()
            playerPossibilities.append(temp_rl)
            runningList.remove(card)
        else:
            deck.remove(card)
            simPlayerHelper(deck, runningList, playerPossibilities)
    for x in playerPossibilities:
        print(x)

The recursion is not working correctly. For example, if runningList starts with "10" and "2", then the first card in deck will be another 2. Another card is drawn, because we don't have 17 yet, and it's another 2. This is fine. We have 16 now, so another card is taken from the deck, which is the last 2 (the cards are in order). We now have 18, so [10,2,2,2,2] is added to playerPossibilities. Then [10,2,2,2,3] (four times for four 3's in the deck) is added, [10,2,2,2,4] (four times), and so on. That is fine. But now I need it to go back to the fourth card in the hand and fine all possibilities if that were to be a 3, then 4, then 5, and so on. And then back to the third card, and find the possibilities if that card were a 3, then 4, then 5, for all remaining cards in the deck. Right now, it is only looping through the last card in the hand, so all items in playerPossibilities start with 10,2,2,2.

I'm sorry if this explanation wasn't very clear. I'm stuck so any help on how I can get this recursion working properly would be greatly appreciated. Thank you!


Solution

  • There are a number of problems here.

    1. for card in deck - you are iterating over a list that you are then removing objects from. This is a good way to have things not work correctly.

    2. if // else - You draw a card, put it in your hand and check for your win condition. If above 16, record the answer, remove from your hand and continue. Great! If not above 16, do your recursion...but you have no mechanism for removing the card from your hand after the recursion is finished. (I believe this to be the source of your current bug)

    To solve this, for this kind of problem, you probably want to make a copy of "deck" in your recursive function so that child calls can't pull cards out of your parent deck (where you haven't checked them yet). You also want to make sure that the card is removed from your hand after each iteration. I would probably suggest doing your loop like this

    def run_sims(deck):
      current_deck = copy(deck)
      while current_deck:
        card = deck.pop()
        current_hand.append(card)
        # do logic / recurse
        current_hand.pop(card)