Home > Mobile >  Why is my python card game returning None for every card when restarting?
Why is my python card game returning None for every card when restarting?

Time:04-19

I have a Streets and Alleys card game and I'm currently having trouble making a new game when the user inputs "r" or if they win a game. Every time, it returns None for every card. I'm not quite sure if it has something to do with my function initialize() or if it's something I have to rewrite in my main(). Here's my code:

import cards, random, re
random.seed(100) #random number generator will always generate 
                 #the same 'random' number (needed to replicate tests)

MENU = '''     
Input options:
    MTT s d: Move card from Tableau pile s to Tableau pile d.
    MTF s d: Move card from Tableau pile s to Foundation d.
    MFT s d: Move card from Foundation s to Tableau pile d.
    U: Undo the last valid move.
    R: Restart the game (after shuffling)
    H: Display this menu of choices
    Q: Quit the game       
'''

the_deck = cards.Deck()  

            
def initialize():
    
    '''Establishes two lists and deals the cards
    to the tableau with even lists having 7 cards
    and odd lists having 6 cards'''
    
    foundation = [[], [], [], []]
    
    tableau = [[], [], [], [], [], [], [], []]
    checker = False
    
    while checker == False:
        the_deck.shuffle()
    
        for i in range( 7 ):
            tableau[0].append(the_deck.deal())
            
        for i in range (8, 14):
            tableau[1].append(the_deck.deal())
            
        for i in range( 15, 22 ):
            tableau[2].append(the_deck.deal())
            
        for i in range (23, 29):
            tableau[3].append(the_deck.deal())
            
        for i in range( 30, 37):
            tableau[4].append(the_deck.deal())
            
        for i in range (38, 44):
            tableau[5].append(the_deck.deal())
            
        for i in range( 45, 52 ):
            tableau[6].append(the_deck.deal())
            
        for i in range (53, 59):
            tableau[7].append(the_deck.deal())
            
            checker = True
            
            continue
    
    return tableau, foundation


def display(tableau, foundation):
    '''Each row of the display will have
       tableau - foundation - tableau
       Initially, even indexed tableaus have 7 cards; odds 6.
       The challenge is the get the left vertical bars
       to line up no matter the lengths of the even indexed piles.'''
    
    # To get the left bars to line up we need to
    # find the length of the longest even-indexed tableau list,
    #     i.e. those in the first, leftmost column
    # The "4*" accounts for a card plus 1 space having a width of 4
    max_tab = 4*max([len(lst) for i,lst in enumerate(tableau) if i%2==0])
    # display header
    print("{1:>{0}s} | {2} | {3}".format(max_tab 2,"Tableau","Foundation","Tableau"))
    # display tableau | foundation | tableau
    for i in range(4):
        left_lst = tableau[2*i] # even index
        right_lst = tableau[2*i   1] # odd index
        # first build a string so we can format the even-index pile
        s = ''
        s  = "{}: ".format(2*i)  # index
        for c in left_lst:  # cards in even-indexed pile
            s  = "{} ".format(c)
        # display the even-indexed cards; the " 3" is for the index, colon and space
        # the "{1:<{0}s}" format allows us to incorporate the max_tab as the width
        # so the first vertical-bar lines up
        print("{1:<{0}s}".format(max_tab 3,s),end='')
        # next print the foundation
        # get foundation value or space if empty
        found = str(foundation[i][-1]) if foundation[i] else ' '
        print("|{:^12s}|".format(found),end="")
        # print the odd-indexed pile
        print("{:d}: ".format(2*i 1),end="") 
        for c in right_lst:
            print("{} ".format(c),end="") 
        print()  # end of line
    print()
    print("-"*80)
     
     
def valid_tableau_to_tableau(tableau,s,d):
    '''Checks to see if you can move a card
    from one tableau to another'''
    
    if len(tableau[s]) == 0:
        return False
    
    card_source = tableau[s][len(tableau[s])-1]
    
    if d > 7: #makes sure destination isn't greater than 7
        return False
    
    if card_source.rank() >= 1 and len(tableau[d]) == 0:
        return True
    
    try:
        card_destination = tableau[d][len(tableau[d])-1]
    except:
        return False
    
    if card_source.rank() == card_destination.rank()-1:
        return True
    else:
        return False
    
def move_tableau_to_tableau(tableau,s,d):
    '''Moves the selected card from a tableau to another'''
    
    if valid_tableau_to_tableau(tableau, s, d):
        tableau[d].append(tableau[s].pop()) #move the card
        return True
    else: #figure out when to return True or False
        print("Error in move: {} , {} , {}".format("MTT", s, d))
        return False


def valid_foundation_to_tableau(tableau,foundation,s,d):
    '''Checks to see if you can move a card
    from the foundation to a tableau'''
    
    if len(foundation[s]) == 0:
        return False
    
    card_source = foundation[s][len(foundation[s])-1]
    
    if len(tableau[d]) == 0: #checks that foundation can move to empty tableau
        return True
    
    try: #checks that tableau destination has a card
        card_destination = tableau[d][len(tableau[d])-1]
    except:
        return False
    
    if card_source.rank() == card_destination.rank()-1: #source code is one lower than the destination card
        return True
    else:
        return False
    
    

def move_foundation_to_tableau(tableau,foundation,s,d):
    '''Moves the selected card from the foundation to a tableau'''
    
    if valid_foundation_to_tableau(tableau, foundation, s, d):
        tableau[d].append(foundation[s].pop())
        return True
    else:
        print("Error in move: {} , {} , {}".format("MFT", s, d))
        return False

def valid_tableau_to_foundation(tableau,foundation,s,d):
    '''Checks to see if you can move a card
    from one tableau to the foundation'''
    
    if len(foundation[d]) == 0:
        card_source = tableau[s][len(tableau[s])-1]
        
        if card_source.rank() == 1: 
            return True  #True if source card is an Ace
        else: 
            return False
        
    else:
        try: #checks if destination and source has card
            card_source = tableau[s][len(tableau[s])-1]
            card_destination = foundation[d][len(foundation[d])-1]
        except:
            return False
        
        if (card_source.rank()-1 == card_destination.rank() and card_source.suit() == card_destination.suit()):
            return True #checks if suits match as well as ranked accordingly 
        else:
            return False

def move_tableau_to_foundation(tableau, foundation, s,d):
    '''Moves the selected card from a tableau to the foundation'''
    
    if valid_tableau_to_foundation(tableau, foundation, s, d):
        foundation[d].append(tableau[s].pop())
        return True
    else:
        print("Error in move: {} , {} , {}".format("MTF", s, d))
        return False
    
    
def invalid_tableau_to_foundation(tableau, foundation, s, d):
    ''''Undo a move from tableau to foundation'''
    foundation[d].append(tableau[s].pop())
    return True

def invalid_tableau_to_tableau(tableau, s, d):
    ''''Undo a move from tableau to another tableau'''
    tableau[d].append(tableau[s].pop())
    return True

def invalid_foundation_to_tableau(tableau, foundation, s, d):
    ''''Undo a move from the foundation to a tableau'''
    tableau[d].append(foundation[s].pop())
    return True

def check_for_win(foundation):
    '''Checks to see if all lists of the foundation
    are filled with 13 cards each (Full suit).'''
    
    #checks if all foundation lists have all 13 cards in them
    if (len(foundation[0]) == 13) and (len(foundation[1]) == 13) and (len(foundation[2]) == 13) and (len(foundation[3]) == 13):
        return True
    else:
        return False


def get_option():
    '''Prints option menu and takes
    user input to determine which 
    option will follow'''
    
    user_input = input("\nInput an option (MTT,MTF,MFT,U,R,H,Q): ").upper()
    
    if not (re.search('M[A-Z][A-Z] [0-9] [0-9]', user_input) \
            or user_input == "U" or user_input == "R" or user_input == "H" or user_input == "Q"):
        print("Error in option:", user_input)
        return None
    
    else:
        if (user_input == "U" or user_input == "R" or user_input == "H" or user_input == "Q"):
            return [user_input]
        else:
            option_list = user_input.split()
            mode = option_list[0]
            source = int(option_list[1])
            destination = int(option_list[2])
            
            if mode[1] == "T":
                if source not in range(0, 8):
                    print("Error in Source.")
                    return None
                
            if mode[1] == "F":
                if source not in range(0, 4):
                    print("Error in Source.")
                    return None
                
            if mode[2] == "T":
                if destination not in range(0, 8):
                    print("Error in Destination")
                    return None
                
            if mode[2] == "F":
                if destination not in range(0, 4):
                    print("Error in Destination")
                    return None
                
            return [mode, source, destination]

        
def main():  
    c = ""
    option_list = None
    win = False
    continuing = False
    turn = True
    redo = []
    
    
    
    print("\nWelcome to Streets and Alleys Solitaire.\n")
    
    tableau, foundation = initialize()
    
    while c != "Q":
        
        if turn:
            display(tableau, foundation)
            print(MENU) 
            turn = False
        option_list = get_option()
        while option_list == None:
            option_list = get_option()
        moving_string = option_list[0]
        if len(option_list) == 1:
            c = option_list[0]
            
        else:
            c = moving_string
            if moving_string == "MTT":
                continuing = move_tableau_to_tableau(tableau, option_list[1], option_list[2])
                if continuing:
                    list_of_moves = ["MTT", option_list[1], option_list[2]]
                    redo.append(list_of_moves)
                    
            elif moving_string == "MTF":
                continuing = move_tableau_to_foundation(tableau, foundation, option_list[1], option_list[2])
                
                if continuing:
                    list_of_moves = ["MTF", option_list[1], option_list[2]]
                    redo.append(list_of_moves)
                    
            else:
                continuing = move_foundation_to_tableau(tableau, foundation, option_list[1], option_list[2])
                
                if continuing:
                    list_of_moves = ["MFT", option_list[1], option_list[2]]
                    redo.append(list_of_moves)
                    
            if continuing:
                win = check_for_win(foundation)
                if not win:
                    display(tableau, foundation)
                
            if win:
                print("You won!\n")
                display(tableau, foundation)
                print("\n- - - - New Game. - - - -\n")
                tableau, foundation = initialize()
                display(tableau, foundation)
                turn = True
                
        if c == "R":
            tableau, foundation = initialize()
            display(tableau, foundation)
            
        if c == "H":
            print(MENU)
                
        if c == "U":
            if len(redo) == 0:
                print("No moves to undo.")
            else:
                newer_move = redo.pop()
                if newer_move[0] == "MTT":
                    invalid_tableau_to_tableau(tableau, newer_move[2], newer_move[1])
                    
                if newer_move[0] == "MTF":
                    invalid_tableau_to_foundation(tableau, foundation, newer_move[2], newer_move[1])
                    
                if newer_move[0] == "MFT":
                    invalid_foundation_to_tableau(tableau, foundation, newer_move[2], newer_move[1])
                    
                x = newer_move[0]
                y = str(newer_move[1])
                z = str(newer_move[2])
                    
                print("Undo:", x, y, z)
                display(tableau, foundation)
                
    print("Thank you for playing.")

if __name__ == '__main__':
     main()

CodePudding user response:

You didn't show us cards, but I'm betting that returns a generator, and after you've gone through it once, there's nothing left. You should generate a new deck every time. I don't know what you were trying to do with checker, but clearly that was silly. I'm also not sure why you were dealing 8 columns; the 8th column is never going to have any cards.

def initialize():
    
    '''Establishes two lists and deals the cards
    to the tableau with even lists having 7 cards
    and odd lists having 6 cards'''
    
    foundation = [[], [], [], []]    
    tableau = [[], [], [], [], [], [], [], []]

    the_deck = cards.Deck()  
    the_deck.shuffle()
    
    for i in range(7):
        for j in range(7 - i%2):
            tableau[i].append(the_deck.deal())
    
    return tableau, foundation
  • Related