3
\$\begingroup\$

I developed a simple command-line roulette game. Your only options are betting on color, but you can bet multiple times in one round

import copy
import distutils.core
from time import sleep
from random import randint

red_slots=(1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36)
black_slots=(2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33, 35)
master_color_dict={'red':0,'black':0,'green':0}
quit = False
bal = 500

def roll(num,bet_choice,color_choice):
    color_dict = master_color_dict.copy()
    hits = 0
    for _ in range(num):
        sleep(.1)
        r = randint(0,36); print(r,end=" ")
        if r in red_slots:
            color_dict['red']+=1
            if color_choice == 'red':
                hits+=1
                print(' --  HIT x'+str(hits))
            else:
                print()
        elif r in black_slots:
            color_dict['black']+=1
            if color_choice == 'black':
                hits+=1
                print(' --  HIT x'+str(hits))
            else:
                print()
        elif r == 0:
            color_dict['green']+=1
            if color_choice == 'green':
                hits+=1
                print(' --  HIT x'+str(hits))
            else:
                print()

    if color_choice == 'red':
        return color_dict[color_choice]*bet_choice - color_dict['black']*bet_choice - color_dict['green']*bet_choice
    elif color_choice == 'black':
        return color_dict[color_choice]*bet_choice - color_dict['red']*bet_choice - color_dict['green']*bet_choice
    elif color_choice == 'green':
        return color_dict[color_choice]*bet_choice*34 - color_dict['black']*bet_choice - color_dict['red']*bet_choice

def colorchoose(msg):
    while True:
        try:
            color = input(msg)
            if color == 'r' or color == 'red':
                return 'red'
            elif color == 'b' or color == 'black':
                return 'black'
            elif color == 'g' or color == "green":
                return 'green'
            else:
                print("Invalid Input")
        except ValueError:
            print("Invalid Input")

def betchoose(msg):
    while True:
        try:
            bet = int(input(msg))
            if bet >= 0 and bet <= bal:
                return bet
            elif bet > bal:
                print("You don't have enough money!")
            elif bet < 0:
                print("You can't bet negative money!")
        except ValueError:
            print("Please enter a positive integer less than or equal to your balance")

def rollchoose(msg):
    while True:
        try:
            rc = int(input(msg))
            if rc*bet_choice <= bal and rc > 0:
                return rc
            elif rc*bet_choice > bal:
                print(f"You cannot afford to roll {rc} times")
            elif rc <= 0:
                print("Please enter a positive integer")
        except ValueError:
            print("Please enter a positive integer")

def money_change_format(num,paren=False):
    if num >= 0 and paren == True:
        return '(+$%d)' % (num)
    elif num < 0 and paren == True:
        return '(-$%d)' % (-num)
    elif num >= 0 and paren == False:
        return '+$%d' % (num)
    else:
        return '-$%d' % (-num)

def replenish(msg):
    while True:
        try:
            rep = distutils.util.strtobool(input(msg))
            if rep == 0 or rep == 1:
                return rep
            else:
                print('Please indicate whether you\'d like to replenish your balance')
        except ValueError:
            print('Please indicate whether you\'d like to replenish your balance')

print("Welcome to Roulette! Payouts are x2 for black and red and x35 for green. Your starting balance is $500\n")

while not quit:
    while bal > 0:
        color_choice = colorchoose('What color would you like to bet on? ')
        bet_choice = betchoose('How much money would you like to wager? ')
        roll_choice = rollchoose('How many times would you like to roll? ')

        old_bal = copy.copy(bal)
        bal = bal + roll(roll_choice,bet_choice,color_choice)
        print('New Balance: ','$'+str(bal),money_change_format(bal-old_bal,True))

    rep = replenish("You're Broke! Would you like to replenish your $500 balance? ")
    if rep: bal+=500; print('New Balance: $500 (+$500)')
    elif not rep: quit = True

print('Play again anytime!')

```
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Since master_color_dict is only used in roll to initialize another dict, you could just write that initialization inside roll:

def roll(...):
    color_dict = {'red': 0, 'black': 0, 'green': 0}

And since you don't use this dictionary as a whole but only its individual parts, you could as well say:

def roll(...):
    red = 0
    black = 0
    green = 0

You should not abbreviate balance to bal. The additional 4 letters won't hurt anywhere in the code.

You should read about PEP 8 and apply the usual coding conventions to your code, which are:

  • after a comma, write a space
  • around binary operators, write spaces
  • and several more

Since the roll function is more than a screen long (at least for some screens), it takes a while to read all the code. Therefore you should provide a doc string that summarizes all that code in a single sentence.

At the end of roll, there are 3 large expressions that are hard to read. One of them contains the magic number 34. That number is magic because it neither appears in the roulette rules nor anywhere else in the code. To get rid of these complicated formulas, it would be easier to maintain a separate balance variable in that function:

def roll(num, bet_color, bet_amount):
    balance = 0

    for _ in range(num):
        balance -= bet_amount

        rolled_color = ...

        if bet_color == rolled_color:
            balance += payout[rolled_color] * bet_amount

This way, the code exactly tells the story how it happens in reality. First you bet some money, and it is gone. And should you have picked the correct color, you get the payout.

In rollchoose you should reorder the conditions:

  • first check whether the given number is positive. If not, reject it.
  • then check whether you can afford it. If not, reject it.
  • return it.

Since you already ruled out negative numbers in the first condition, you don't need that check rc > 0 in the second condition anymore. That's exactly what the elif is for.

In money_change_format, you don't seem to need the cases for paren = False since you only call that function with paren = True. This dead code should be removed.

In the main program, the number 500 appears 4 times. It should appear only once. When printing the new balance, you should use money_change_format so that all your program's output is formatted in the same way.

A final remark on the post's title: your roulette program has nothing to do with a command line since it doesn't access sys.args. It runs in text mode, which often goes together with command lines, but not necessarily so. Keeping different concepts separated is important. If you mix up these concepts, you will write programs that work almost correctly, which is the worst that can happen. Especially if the program only shows unexpected behavior in situations that are hard to explain.

\$\endgroup\$

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.