2
\$\begingroup\$

Blackjack (twenty-one) is a casino game played with cards. The goal of the game to draw cards that total as close to 21 points as possible without going over. All face cards count as 10 points, aces count as 1 or 11, and all other cards count their numeric value.

The game is played against a dealer. The player tries to get closer to 21 (without going over) than the dealer. If the dealer busts (goes over 21) the player automatically wins (provided the player had not already busted). The dealer must always take cards according to a fixed set of rules. The dealer takes cards until he or she achieves a total of at least 17. If the dealer's hand contains an ace, it will be counted as 11 when that results in a total between 17 and 21 inclusive; otherwise, the ace is counted as 1.

Write a program that simulates multiple games of blackjack and estimates the probability that the dealer will bust. Hints: treat the deck of cards as infinite. You do not need to keep track of the cards in the hand, just the total so far (treating an ace as 1) and a bool variable hasace that tells whether or not the hand contains an ace. A hand containing an ace should have 10 points added to the total exactly when doing so would produce a stopping total(something between 17 and 21 inclusive).

It runs, but I'm just looking to improve it if possible.

def printIntro():
    print("This program simulates a bunch of blackjack games.")

def getInputs():
    while True:
        n = eval(input("How many games should be simulated? "))
        if n <= 0:
            print("You must enter a number greater than zero!")
        else:
            break

    return n

def simOneGame():
    score = 0
    blacklist = [2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 11]
    while not gameOver(score):
        blackscore = blacklist[randrange(len(blacklist))]
        score = score + blackscore

        if score >= 17: 
             break
        if blackscore == 11 and (score >= 6 and score <= 10): 
            score = score + 11
        else:
            score = score + 1

    return score

def simNGames(n):
    holds = 0
    busts = 0
    for i in range(n):
        score = simOneGame()
        if score >= 22:
            busts = busts + 1
        else:
            holds = holds + 1

    return holds, busts

def gameOver(score):
    return score >= 22 or score >= 17

def printSummary(holds, busts):
    n = holds + busts
    print("Number of holds and busts: Holds: {0:0} Busts: {1:0}".format(holds, busts))
    print("Percentage of holds and busts: Holds: {0:0.1%}".format(holds / n), end = " ")
    print("Busts: {0:0.1%}".format(busts / n))

def main():
    printIntro()
    n = getInputs()
    score = simOneGame()
    holds, busts = simNGames(n)
    printSummary(holds, busts)

if __name__ == "__main__":
    main()
\$\endgroup\$

2 Answers 2

5
\$\begingroup\$
def printIntro():
    print("This program simulates a bunch of blackjack games.")

Python style guide recommend lowercase_with_underscores for function names

def getInputs():
    while True:
        n = eval(input("How many games should be simulated? "))

not a really good idea to use eval, because that allows the user to input any python expression which may not make sense. Instead use int, which will only allow numbers

        if n <= 0:
            print("You must enter a number greater than zero!")
        else:
            break

    return n

def simOneGame():
    score = 0
    blacklist = [2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 11]
    while not gameOver(score):
        blackscore = blacklist[randrange(len(blacklist))]

Python has a function, random.choice() which returns a random element from a list.

        score = score + blackscore

        if score >= 17: 
             break

Why? The loop will terminate anyways. There doesn't seem to be a reason to break here

        if blackscore == 11 and (score >= 6 and score <= 10): 
            score = score + 11
        else:
            score = score + 1

I assume that this has to do with handling aces, but I don't understand the logic. You've already added blackscore to score, so I wouldn't think this would do the right thing. Also, couldn't you need to change the value of an ace to a 1, from an eleven due to later cards?

    return score

You only really care about busts/holds so maybe you should return True or False?

def simNGames(n):
    holds = 0
    busts = 0
    for i in range(n):
        score = simOneGame()
        if score >= 22:
            busts = busts + 1
        else:
            holds = holds + 1

    return holds, busts

def gameOver(score):
    return score >= 22 or score >= 17

That's the same as score >= 17, no reason to include the first part of the condition

def printSummary(holds, busts):
    n = holds + busts
    print("Number of holds and busts: Holds: {0:0} Busts: {1:0}".format(holds, busts))
    print("Percentage of holds and busts: Holds: {0:0.1%}".format(holds / n), end = " ")
    print("Busts: {0:0.1%}".format(busts / n))

def main():
    printIntro()
    n = getInputs()
    score = simOneGame()
    holds, busts = simNGames(n)
    printSummary(holds, busts)

if __name__ == "__main__":
    main()
\$\endgroup\$
-1
\$\begingroup\$

You didn't import the randrange function from the random module. Without this, it won't work.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ It's quite likely they just didn't copy imports into the question, assuming that it wasn't necessary. \$\endgroup\$ Sep 4, 2016 at 9:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.