Skip to main content
2 of 4
deleted 12 characters in body; edited tags; edited title
200_success
  • 145.6k
  • 22
  • 191
  • 481

Simulated card trick with splitting and reordering

I need a bit of help with a practice Computer Science coursework. I have written a code for a magic trick (more information below) using Python 3.x, and for one particular section, I need to suggest potential improvements/enhancements. I know this sounds a tiny bit egotistical, but I can't seem to think of any :( .

The program is called ‘The Card Trick’. It simulates a magic trick that can be performed in real-life. The program should generate 21 random playing cards, with suits and values, and will split them into three groups of seven. The user will be asked to choose a card, and input which group the chosen card is contained within. The cards will then be put back into a larger list in a certain order, and dealt in the same way as before. The steps will be repeated twice, and then the program will ‘magically’ print the card that the user is thinking of.

Anyway, here is my code:

import random # Imports the random module

def get_cards():
    '''
    Funtion which randomly generates the cards and adds them to
    deck if the card is not in the deck already.
    Parameters: None
    Returns: cards_dealt
    '''
    cards_dealt=[]
    while len(cards_dealt) < 21: # Repeats until there are 21 cards in the deck
        #Generates the card
        card = random.choice(['A','2','3','4','5','6','7','8','9','10','J','Q','K'])+ random.choice([u'\u2665',u'\u2663',u'\u2666',u'\u2660'])
        if card not in cards_dealt: # If card not already in the deck
            cards_dealt.append(card) # Adds card to deck
        else:
            continue # continue generating cards
    return cards_dealt


def get_piles(deck):
    '''
    Funtion which deals the cards in the way that a magician would.
    It then adds the cards to three lists called P1, P2 and P3, depending
    on their position in the deck.
    Parameters: deck
    Returns: P1, P2, P3
    '''                                   # range() makes lists of:
    P1 = [deck[i] for i in range(0,21,3)] # [0,3,6,9,12,15,18]
    P2 = [deck[i] for i in range(1,21,3)] # [1,4,7,10,13,16,19]
    P3 = [deck[i] for i in range(2,21,3)] # [2,5,8,11,15,17,20] which correspond to the positons of cards in the deck.
    return P1, P2, P3


def get_newdeck(choice, P1, P2, P3):
    '''
    Function which reorders the deck in a way that the chosen list is
    in the middle of the two other lists.
    Parameters: choice, P1, P2, P3
    Returns: the new, reordered deck
    '''
    deck = P1+P3+P2 # Orders the deck with Pile 3 in middle
    if choice == 1: # if user's choice is 1
        deck = P2+P1+P3 # Put pile 1 between other piles
    elif choice == 2: # If user's choice is 2
        deck = P1+P2+P3 # Put pile 2 between other piles
    return deck


def PrintPiles(P1, P2, P3):
    '''
    Procedure which prints the lists(P1, P2, and P3) vertically
    with headers to tell the user which piles they are.
    Parameters: P1, P2, P3
    Returns: None
    '''
    # Prints the piles vertically
    print("Pile 1\tPile 2\tPile 3")        
    for i in range(7):                
        print(P1[i]+'\t'+P2[i]+'\t'+P3[i])


def Get_Choice():
    '''
    Funtion which gets the users input of which pile their chosen
    cards is inside. It also tells the user if they entered an invalid
    input (not 3, 2, or 1).
    Parameters: None
    Returns: choice
    '''
    choice = 0 # sets variable choice to 0
    # while loops and try:except fix invalid inputs
    while choice > 3 or choice < 1: # Choice not 1-3
        while True: # Allows the user to keep entering inputs when input invalid
            try: 
                choice = int(input("Which pile is your card in? (1-3)? > "))
                break
            except ValueError: # If input non-integer and returns exception
                               # ValueError
                print("Must be an integer")
    return choice


def main():
    '''
    The main body of the code, using previous procedures and functions
    to make the code work as intended.
    Parameters: None
    Returns: None
    '''
    deck = get_cards() # generates deck (list) from get_cards function
    print("Choose a card and remember it")
    # Repeats 3 times
    for x in range(3):
        # 'deals' three piles and stores them in P1, P2 and P3
        P1, P2, P3 = get_piles(deck)
        # calls PrintPiles procedure
        PrintPiles(P1, P2, P3)
        # gets the user's choice between 1 and 3 depending on
        # the position of their card
        choice = Get_Choice()
        print()
        # reorders the deck according to the user's choice
        deck = get_newdeck(choice, P1, P2, P3)
    print()
    # Prints the card in the middle of the deck
    print('>>> Your card is {} <<<'.format(deck[10]))


main()

Any ideas? FYI no improvements regarding commenting please! Believe me - I tried incredibly hard to find anything, my best guess was to try to improve the speed, but it already runs pretty well. I suppose I could use some different data structures to make my code more concise.

AJ123
  • 143
  • 1
  • 1
  • 8