1

How to make a deck for a card game that could be refreshed in the start of each game ?

The code I've tried seems to be not working properly. It shows that the lentgth is reduced and in the end an error is raiesd, even though it shows the full length after continuing

      import random
import copy

deck=(2,3,4,5,6,7,8,9,10,'J','Q','K','A')

deck1=list(deck)

class player(object):
    def __init__ (self):
        self.hand=[]
        self.score=0
    def draw(self,num,d=deck1):
        for _ in range(num):
            
            ra=random.randint(
                0,len(d)-1)
            print('The number',ra,'the length=',len(d))
            self.hand.append(d.pop(ra))
            
def test1():
    
    ch1=input('Want to continue ? ')
    
    if ch1=='y':start()
    if ch1=='n':pass

def start():
    
    plr=player()
    dlr=player()
    deck1=copy.deepcopy(list(deck))    
    print('the length is',len(deck1),'\n')
    dlr.draw(2)
    plr.draw(2)
    test1()

start()
print(deck1)
test1()

The output:

> the length is 13 
>     
>     The number 11 the length= 13
>     The number 10 the length= 12
>     The number 3 the length= 11
>     The number 4 the length= 10
>     Want to continue ? y
>     the length is 13 
>     
>     The number 0 the length= 9
>     The number 3 the length= 8
>     The number 4 the length= 7
>     The number 3 the length= 6
>     Want to continue ? y
>     the length is 13 
>     
>     The number 3 the length= 5
>     The number 2 the length= 4
>     The number 1 the length= 3
>     The number 0 the length= 2
>     Want to continue ? y
>     the length is 13 
>     
>     The number 0 the length= 1

The end of the error:

...File "C:\python38\lib\random.py", line 248, in randint
    return self.randrange(a, b+1)   File "C:\python38\lib\random.py", line 226, in randrange
    raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width)) 
ValueError: empty range for randrange() (0, 0, 0)
PQlet
  • 51
  • 4

1 Answers1

1

First issue

The first issue is Python’s default arguments are evaluated once when the function is defined, not each time the function is called (like it is in say, Ruby) Reference

So this code:

def draw(self,num,d=deck1):

Is normally changed to:

def draw(self,num,d=None):
    if d is None:
        d = deck1

Second Issue

The normal remedy doesn't work since deck1 is defined in the caller (i.e. call Tree is):

start ----> defines deck1
   draw --wants to access deck1

But this is not possible Accessing parent function's variable in a child function called in the parent using python unless draw was a nested function of start.

Fix--Since draw is in it's own class, we can't have deck1 as a default parameter.

The options are:

  1. Pass deck1 to the Player class constructor, or
  2. Pass deck1 to draw

Using option 1 (which seems better in this case), the code becomes the following.

Code

import random
import copy

deck=(2,3,4,5,6,7,8,9,10,'J','Q','K','A')

deck1=list(deck)

class player(object):
    def __init__ (self, deck):
        self.hand=[]
        self.score=0
        self.deck = deck

    def draw(self, num):
        d = self.deck
        for _ in range(num):
            ra = random.randint(0, len(d)-1)
            print('The number',ra,'the length=',len(d))
            self.hand.append(d.pop(ra))  
            
def test1():
    ch1=input('Want to continue ? ')
    
    if ch1=='y':start()
    if ch1=='n':pass

def start():
    deck1=copy.deepcopy(list(deck)) 
    plr=player(deck1)
    dlr=player(deck1) 

    print('the length is',len(deck1),'\n')
    dlr.draw(2)
    plr.draw(2)
    test1()

start()
print(deck1)
test1()

Output

the length is 13 

The number 6 the length= 13
The number 9 the length= 12
The number 6 the length= 11
The number 3 the length= 10
Want to continue ? y
the length is 13 

The number 8 the length= 13
The number 9 the length= 12
The number 2 the length= 11
The number 5 the length= 10
Want to continue ? y
the length is 13 

The number 2 the length= 13
The number 2 the length= 12
The number 4 the length= 11
The number 6 the length= 10
Want to continue ? y
the length is 13 

The number 3 the length= 13
The number 9 the length= 12
The number 6 the length= 11
The number 1 the length= 10
Want to continue ?

Final Note

Your function flow is recursive, i.e.:

start test1 start test1 ...

This is not the best practice in Python since you will eventually reach the recursion limit (normally 1000 by default), but the current code will work for hundreds of games. The normal pattern is to use a while loop instead of this recursive pattern.

DarrylG
  • 16,732
  • 2
  • 17
  • 23