Search code examples
pythonshuffleindex-error

How to solve index error while using pop in python?


This is the error I'm getting(In the image)

From a deck of cards 13 cards are being shuffled and distributed among 4 players, and after shuffling the game rules are checked if it does not abide by rules then reshuffling will take place. When reshuffling takes place it shows pop from empty list error

import random

suites=['Hearts', 'Diamonds', 'Clubs', 'Spades']
values = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
deck=[]

class cards:
    def __init__(self,value,suit,priority):
        self.suit=suit
        self.value=value
        self.priority=priority

    def __str__(self):
        return "{} of {}".format(self.value,self.suit)    

class player:
    def __init__(self,name):
        self.name=name
        self.point=0
        self.hand=[]

    def show_cards(self):
        for a in self.hand:
            print(a)  

def un_deck():
    for i in suites:
        p=1
        for j in values:
            if i =="Spades":
                pri=p*15
                p+=1
            else:
                pri=p
                p+=1
            deck.append(cards(j,i,pri))

def shuffle() :
    random.shuffle(deck)
    return deck

p=[player("Player 1"),player("Player 2"),player("Player 3"),player("Player 4")]

def distribue_cards():
    card=shuffle()
    n=51
    while n>=0:
        print("-----------------------length=",len(card),"---------------------")
        if n%4==0:                                     
            p[0].hand.append(card.pop(n))
        elif n%4==1:
            p[1].hand.append(card.pop(n))
        elif n%4==2:
            p[2].hand.append(card.pop(n))
        elif n%4==3:
            p[3].hand.append(card.pop(n))
        n-=1
    # del card                                            
    # del n 
    check()

def check() :
    for i in p:
        ace,heart,diamond,spade,club=0,0,0,0,0
        for j in i.hand:
            if j.value=="A":
                ace+=1
            if j.suit=="Hearts":
                heart+=1    
            elif j.suit=="Diamonds":
                diamond+=1 
            elif j.suit=="Clubs":
                club+=1 
            else:
                spade+=1
        if (ace>=3 or heart>=7 or diamond>=7 or club>=7 or spade>=7 or heart==0 or diamond==0 or club==0 or spade==0):
            distribue_cards()
            break      

#main
un_deck()
distribue_cards()
for b in p:
    print("player name:",b.name)
    b.show_cards()

Error message(length in output is for testing purpose)


Solution

  • Errors:

    • card gets emptied and when you call check() inside the function, if a specific condition meets you are calling distribue_cards(). This is your mistake, as card are already emptied and calling pop() in the empty list is generating the error.

    • Also you are not clearing cards distributed to players not doing so, will pile lots of cards in their hand causing an infinite loop (Due to your given condition ace>=3 or heart>=7 or diamond>=7 or club>=7 or spade>=7 or heart==0 or diamond==0 or club==0 or spade==0)).

    Code:

    import random
    
    suites=['Hearts', 'Diamonds', 'Clubs', 'Spades']
    values = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
    deck=[]
    
    class cards:
        def __init__(self,value,suit,priority):
            self.suit=suit
            self.value=value
            self.priority=priority
    
        def __str__(self):
            return "{} of {}".format(self.value,self.suit)    
    
    class player:
        def __init__(self,name):
            self.name=name
            self.point=0
            self.hand=[]
    
        def show_cards(self):
            for a in self.hand:
                print(a)  
    
    def un_deck():
        for i in suites:
            p=1
            for j in values:
                if i =="Spades":
                    pri=p*15
                    p+=1
                else:
                    pri=p
                    p+=1
                deck.append(cards(j,i,pri))
    
    def shuffle() :
        random.shuffle(deck)
        return deck
    
    p=[player("Player 1"),player("Player 2"),player("Player 3"),player("Player 4")]
    
    def distribute_cards():
        card=shuffle()
    
        n=51
        _0=0
        _1=0
        _2=0
        _3=0
        while n>=0:
            print("-----------------------length=",len(card),"---------------------")
    
            if n%4==0:
                _0 +=1
                p[0].hand.append(card.pop(n))
            elif n%4==1:
                _1 += 1
                p[1].hand.append(card.pop(n))
            elif n%4==2:
                _2 +=1
                p[2].hand.append(card.pop(n))
            elif n%4==3:
                _3 += 1
                p[3].hand.append(card.pop(n))
            n-=1
        # del card                                            
        # del n 
        check()
    
    def check() :
        for i in p:
            ace,heart,diamond,spade,club=0,0,0,0,0
            for j in i.hand:
                if j.value=="A":
                    ace+=1
                if j.suit=="Hearts":
                    heart+=1    
                elif j.suit=="Diamonds":
                    diamond+=1 
                elif j.suit=="Clubs":
                    club+=1 
                else:
                    spade+=1
            if (ace>=3 or heart>=7 or diamond>=7 or club>=7 or spade>=7 or heart==0 or diamond==0 or club==0 or spade==0):
                #if the condition is True then:
                un_deck()          # create new deck
                for i in range(4): 
                    p[i].hand=[]   # Clear players' cards
                distribute_cards()  # Then only call distribute_cards
                break      
    
    #main
    un_deck()
    distribute_cards()
    for b in p:
        print("player name:",b.name)
        b.show_cards()