0
\$\begingroup\$

I'm very new to python (been coding for about two days) and have created a programme that simulates blackjack games so that I can work out optimal strategy over many iterations.

The problem is that when I run it, my CPU goes to about 99.8% and it freezes (I run in terminal) - Does anybody have any suggestions on how I can change my code so that it is less CPU intensive? - I'm looking to learn about what I've done wrong, the code is just a bit of fun!

As I said I'm new to this and as such the code isn't very elegant, but it works just fine.

import random
q = 0

#simple counter that will record the score of games over time
win_count = 0
draw_count = 0
lose_count = 0
bust_count = 0

#User input for when the game is run, it will allow them to choose the number of games to be played (iterations) and also the score at which the player will hold.
iterations = input('Number of iterations: ')
hold_score = input('Hold score for the player: ')

#defining the card values, suits and decks.
for x in range(0, iterations):
    s2 = 2
    s3 = 3
    s4 = 4
    s5 = 5
    s6 = 6
    s7 = 7
    s8 = 8
    s9 = 9
    s10 = 10
    sj = 10
    sq = 10
    sk = 10
    sa = 11
    c2 = 2
    c3 = 3
    c4 = 4
    c5 = 5
    c6 = 6
    c7 = 7
    c8 = 8
    c9 = 9
    c10 = 10
    cj = 10
    cq = 10
    ck = 10
    ca = 11
    d2 = 2
    d3 = 3
    d4 = 4
    d5 = 5
    d6 = 6
    d7 = 7
    d8 = 8
    d9 = 9
    d10 = 10
    dj = 10
    dq = 10
    dk = 10
    da = 11
    h2 = 2
    h3 = 3
    h4 = 4
    h5 = 5
    h6 = 6
    h7 = 7
    h8 = 8
    h9 = 9
    h10 = 10
    hj = 10
    hq = 10
    hk = 10
    ha = 11


    spades = [s2, s3, s4, s5, s6, s7, s8, s9, s10, sj, sq, sk, sa]
    clubs = [c2, c3, c4, c5, c6, c7, c7, c8, c9, c10, cj, cq, ck, ca]
    diamonds = [d2, d3, d4, d5, d6, d7, d8, d9, d10, dj, dq, dk, da]
    hearts = [h2, h3, h4, h5, h6, h7, h8, h9, h10, hj, hq, hk, ha]
    deck = [s2, s3, s4, s5, s6, s7, s8, s9, s10, sj, sq, sk, sa, c2, c3, c4, c5, c6, c7, c8, c9, c10, cj, cq, ck, ca, d2, d3, d4, d5, d6, d7, d7, d8, d9, d10, dj, dq, dk, da, h2, h3, h4, h5, h6, h7, h8, h9, h10, hj, hq, hk, ha]
    deck_standard = [s2, s3, s4, s5, s6, s7, s8, s9, s10, sj, sq, sk, sa, c2, c3, c4, c5, c6, c7, c8, c9, c10, cj, cq, ck, ca, d2, d3, d4, d5, d6, d7, d7, d8, d9, d10, dj, dq, dk, da, h2, h3, h4, h5, h6, h7, h8, h9, h10, hj, hq, hk, ha]

#List for the cards the dealer and player holds

    dealer = []
    user_1 = []

#Randomly gives the player and dealer two cards each - and then remove these cards from the deck of cards so it cannot be used again.

    card_1 = random.choice(deck)
    deck.remove(card_1)
    user_1.append(card_1)

    card_2 = random.choice(deck)
    deck.remove(card_2)
    dealer.append(card_2)

    card_3 = random.choice(deck)
    deck.remove(card_3)
    user_1.append(card_3)

    card_4 = random.choice(deck)
    deck.remove(card_4)
    dealer.append(card_4)

#Calculates the number of cards the player/dealer has - also defines their scores to be zero.
    dealer_card_count = len(dealer)
    user_1_card_count = len(user_1)
    dealer_score = 0
    user_1_score = 0


#Looks at the two cards each player has and calculates their score - then adds this score to their score.
    for x in range(0, dealer_card_count):
        dealer_score = dealer_score + int(dealer[x])

    for x in range(0, user_1_card_count):
        user_1_score = user_1_score + int(user_1[x])

#code to say that if the user has less cards than the pre-defined hold score - give them another card and add that card to their score.

    while (int(user_1_score) <= int(hold_score)):
        if (int(user_1_card_count)<6):
            card_5 = random.choice(deck)
            deck.remove(card_5)
            user_1.append(card_5)
            user_1_score = 0
            user_1_card_count = len(user_1)
            for x in range(0, user_1_card_count):
                user_1_score = user_1_score + int(user_1[x])

# sets the hold score for the dealer as that of the user (so that the dealer knows how high he has to aim for)

    hold_score_dealer = user_1_score

# Same  as above - but for the dealer.
    if (int(user_1_score) < int(21)):
        while (int(dealer_score) <= int(hold_score_dealer)):
            if (int(dealer_card_count)<6):
                card_6 = random.choice(deck)
                deck.remove(card_6)
                dealer.append(card_6)
                dealer_score = 0
                dealer_card_count = len(dealer)
                for x in range(0, dealer_card_count):
                    dealer_score = dealer_score + int(dealer[x])


#code so that if the user or the dealer have 5 cards they win automatically (5 card rule)
    if (int(user_1_card_count) ==5):
        if (int(dealer_card_count) !=5):
            if (int(user_1_score)) <22:
                win_count = win_count + 1

    if (int(user_1_card_count) == 5):
        if (int(dealer_card_count) == 5):
            if (int(user_1_score) < 22):
                if (int(dealer_score) <22):
                    draw_count = draw_count + 1
            elif (int(user_1_score) > 22):
                bust_count = bust_count + 1

    if (int(dealer_card_count) == 5):
        if(int(user_1_card_count) != 5):
            if (int(dealer_score) <22):
                lose_count = lose_count + 1


#Code to deal with all possible outcomes (assuming they don't have 5 cards) - and add to the counter.
    if (int(user_1_card_count) != 5):
        if (int(dealer_card_count) != 5):
                if (int(user_1_score) > int(dealer_score)):
                        if (int(user_1_score) < int(22)):
                                win_count = win_count + 1
                        elif (int(user_1_score) > int(21)):
                            if (int(dealer_score) < int(22)):
                                lose_count = lose_count + 1
                            elif (int(user_1_score) > int(21)):
                                if (int(dealer_score) > int (21)):
                                        draw_count = draw_count + 1
                                        bust_count = bust_count + 1
                elif (int(user_1_score) < int(dealer_score)):
                    if(int(user_1_score) > 21):
                        draw_count = draw_count + 1
                        bust_count = bust_count + 1



    if (int(user_1_card_count) != 5):
        if (int(dealer_card_count) != 5):
                if (int(user_1_score) == int(dealer_score)):
                    if (int(user_1_score)) < int(22):
                        draw_count = draw_count + 1
                    elif (int(user_1_score) > 21):
                            draw_count = draw_count + 1
                            bust_count = bust_count + 1

    if (int(user_1_card_count) != 5):
        if (int(dealer_card_count) != 5):
                if (int(user_1_score) < int(dealer_score)):
                        if (int(dealer_score) < int(22)):
                                lose_count = lose_count + 1
                        elif (int(dealer_score) > int(21)):
                            if (int(user_1_score) < int(22)):
                                win_count = win_count + 1

#Code to print the progress of the iterations over time
    if (q == iterations * 0.2):
        print "20%"
    if (q == iterations * 0.4):
        print "40%"
    if (q == iterations * 0.6):
        print "60%"
    if (q == iterations * 0.8):
        print "80%"
    if (q == iterations * 1):
        print "100%"
    gc.collect()
    print q
    q = q + 1

# Code to print the final scores after all iterations are complete.
print "Total iterations: " + str(iterations)
print "*****"
print "Win count  : " + str(win_count) +" ("+ str((float(win_count))/float(iterations)*100) +"%)"
print "Draw count : " + str(draw_count) +" ("+ str((float(draw_count))/float(iterations)*100) +"%)"
print "Lose count : " + str(lose_count) +" ("+ str((float(lose_count))/float(iterations)*100) +"%)"
print "Bust count : " + str(bust_count) +" ("+ str((float(bust_count))/float(iterations)*100) +"%)"
print ""
\$\endgroup\$

migrated from superuser.com Aug 11 '18 at 17:22

This question came from our site for computer enthusiasts and power users.

1
\$\begingroup\$

Take a look at these lines:

while (int(user_1_score) <= int(hold_score)):
    if (int(user_1_card_count)<6):

what happens if the player draws six cards and their score is still less than or equal to the hold score? For example, suppose the hold score is 15 and they draw 2♣ 2♦ 2♥ 2♠ 3♣ 3♦ so that their score is 14. What happens next?

\$\endgroup\$
0
\$\begingroup\$

In both the code listings I see so far, both yours OP, and vash_the_stampede’s code, all I see is an arbitrary card game that looks kinda like blackjack. Neither of which models it the same way. But I guess that’s me being pedantic since I actually dealt the game.

As in vash’s code, it would be advisable to use a generating method to populate the deck. But I would do it a little differently than in their code. First of all, instead of just storing a number for the card in the array, I would at the very least also store a ‘isUsed’ flag that you toggle to take the card out of play, then you can just iterate over the deck setting all the ‘isUsed’ to false. This would save the memory allocation/deallocation every time you create or replenish a deck.

Second, I would take advantage of the fact that you would be storing multiple pieces of information about the cards in the list, and make them into a class so that you can store a few things about the card, like suit, value, used, representation, and any more you can think of that may be of use. This will aid you in developing the program further, like making a graphical version of it for a screensaver ;)

Third, the rules of blackjack:

Each player is dealt 2 cards at the beginning of each hand, one at a time in order around the table starting with the player in the first position, and ending with the dealer. The dealer deals the first card face up, the second face down

The player cards are added together, faces counted as 10, aces counted as either 11, or 1.

When a player has an ace plus a face (counting 10s), they have a blackjack, which is paid 3 to 2. If the player has a blackjack and the dealer has an ace showing, offer insurance which costs the same as their original bet, if they take insurance and the dealer also has a blackjack, they are paid 1 to 1, else they lose the bet and the insurance. The dealer checks for blackjack. in this situation if they have a blackjack it is revealed, insurance pays, and all other hands lose. If they do not have blackjack, the insurance is forfeit, and play continues normally for the rest of the hand.

When the dealer has an ace showing, and no players have a blackjack, they will check the hidden card without showing it, to see if they have a blackjack. If the dealer has a blackjack, all currently active hands lose.

Starting with the first remaining player closest to the player 1 position, play resumes. The values of the players showing cards are added together, and the player is asked to either hit or stand, except in the special case which is below. Each time the player hits, they are given another card, which is added to their total. If the player busts (goes over 21), they lose immediately. If they hit 21, they cannot take any more cards, once they meet one of the preceding conditions, or have 5 cards the action goes to the next player. (Where I dealt, there is no 5 card rule)

If a player has two of the same cards considering their card rank (Kings only count with other Kings, tens only other tens...) they may opt to split the cards by putting up another bet equal to the original bet, each split hand is played as a separate hand, and the player may have up to 4 hands. Any split then busted hands count towards this total.

Once all the players hands have been played, and every player has opted to stand ending their action turn, it is the dealers action. The dealer reveals their face down card and plays according to a specific rule set:

If the dealer shows a hard 17 or above (any hand that uses an ace as 11 is soft, any hand that uses aces only as 1s, or does not include an ace is hard. Aces can be demoted from 11 to 1 mid hand) the dealer will stand. If they show a soft 17 or below they will take another card. Also up to 5 cards total. If the dealer busts at this point, all remaining active hands are paid out 1 to 1.

Once the dealer has reached a stand, their total is compared to each players showing value, in the opposite order of dealing. If the dealers total is higher, the hand loses and the bet is taken. If the dealers and players hands are the same value, the hand pushes, and the player keeps the bet. If the players total is higher, the player wins, and the bet isn’t paid 1 to 1.

Most casinos consider blackjack a high volume game, and as such they use a multi deck shuffle of 6 or 8 decks in a shoe.

Sorry not much of this was about code, but a blackjack solver should actually play the game correctly, Oh and one more thing. Deeply bested if statements are considered bad form, and can lead to some pretty serious overhead, but I think a lot of your problem is the memory alloc/dealloc.

Plus, when you take cards from the deck, first check to see if they have been used, if used, get another card, if not used then give it to the player/dealer. That will save some cycles too.

Just my two bits.

\$\endgroup\$
  • \$\begingroup\$ Hmm the point was to improve his code, maybe his intentions were different. Although I do frequent casinos, so my order of code accounted for how blackjacks play out, in the proper sequence of checking, except the fact if the dealer shows blackjack as well, counted it towards a draw. His code mentions no soft plays or splits, so didn't build on that. Again not trying to make a new game, just make his game better. All cards in play are removed from the deck in use, but I do like the flag idea over, regenerate the deck. Also yes I was thinking about multi-deck play the entire time \$\endgroup\$ – vash_the_stampede Sep 2 '18 at 22:12
  • \$\begingroup\$ again though just was trying to spoof up his code verse make a entirely new game \$\endgroup\$ – vash_the_stampede Sep 2 '18 at 22:12
  • \$\begingroup\$ Well, I also had a bit of an underlying message to the way I set out the rules for the most part. I set them out in a way that would make it very easy to start at the top, and write code for each segment in order (mostly), and come out at the end with a program that logically emulates casino blackjack correctly. A kind of implementation detail specification if you will. ;) and as I mentioned, it is mostly me just being pedantic :) \$\endgroup\$ – DJHenjin Sep 2 '18 at 23:20
  • \$\begingroup\$ Of course, I guess I wasn’t being open minded to the fact it’s something your passionate about, if this was a code for how to do certain things I am passionate about I would have took the same approach as you, cheers :) \$\endgroup\$ – vash_the_stampede Sep 3 '18 at 0:18

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.