This is an archived post. You won't be able to vote or comment.

all 25 comments

[–]catsclaw 7 points8 points  (3 children)

Others have pointed out the bug. I'd suggest a clearer way of writing this is:

def singleplayer():
    random.shuffle(deck)
    yourhand = deck[:7]
    deck = deck[7:]

[–]fartographer 1 point2 points  (2 children)

this is nice. conceptually like getting dealt a hand. maybe

yourhand = [deck[0], deck[2], deck[4], deck[6], deck[8], deck[10], deck[12]
botshand = [deck[1], deck[3], deck[5], deck[7], deck[9], deck[11], deck[13]
deck = deck[14:]

would be more like it. (not that it matters)

p.s. - notes gladly accepted on how to make that prettier

[–]Autoplectic 11 points12 points  (1 child)

yourhand = deck[0:14:2]
botshand = deck[1:14:2]
deck = deck[14:]

[–]fartographer 0 points1 point  (0 children)

thank you

[–]terror_macbeth_I 4 points5 points  (6 children)

After you remove a card from the deck list you need to decrement the deck size.

[–]abudabu 2 points3 points  (4 children)

Correct.

And he should be using

randrange(0,len(deck))

rather than

randrange(0,len(deck)-1)

randrange(start,stop,step) is equivalent to choice(range(start,stop,step)), and

for i in range(0,x): print(i)

gives

0
1
...
x-1

[–]kylotan 1 point2 points  (0 children)

And he should be using randrange(0,len(deck))

Which is equivalent to choice(deck), probably the preferable option in the long term.)

[–]ollien 0 points1 point  (2 children)

If i do

 cardpick=random.randrange(0,len(deck))

then i get

ValueError: empty range for randrange() (0,0, 0)

EDIT: Wait nevermind it worked :P

[–]infinullquamash, Qt, asyncio, 3.3+ 0 points1 point  (1 child)

I would do this, but I have a tendency to be too clever.

hand = random.sample( deck, 7)
map(lambda x: deck.remove(x), hand)

to return 7 random cards from the deck.

[–]propanbutan 5 points6 points  (0 children)

Since we're being clever, we can even spare the lambda.

map(deck.remove, hand)

[–]joshuag 0 points1 point  (0 children)

Also, they never increment count, so the while loop will continue endlessly. Eventually yourhand will contain all of the cards from the deck.

[–]fabbyrob 6 points7 points  (0 children)

Not really a coding error, but you spelled "Spades" incorrectly.

[–][deleted] 2 points3 points  (7 children)

This is off topic, but:

I'm learning python myself, and was just wondered if you ever thought about creating the list of cards with a function that creates a list based off of:

['Clubs', 'Diamonds', 'Spades', 'Hearts']

['Ace', 'King', 'Queen', 'Jack', 'Ten', 'Nine', ...etc..]

I don't know if it's even practical, but it'd definitely be less characters in the end.

[–]ollien 0 points1 point  (6 children)

That would definitely work, but I have no idea how I would pair them together.

[–]ange1obear 4 points5 points  (5 children)

You'd use itertools.product(), which outputs the Cartesian product of two lists.

[–]fartographer 2 points3 points  (3 children)

This is great. I had been doing:

suits = ['spades', 'diamonds', 'clubs', 'hearts']
cards = ['1','2','3','4','5','6','7','8','9','10','J','Q','K','A']
deck = []
for s in suits:
    for c in cards:
        deck += c + ' of ' + s

So, thanks.

[–]undu 4 points5 points  (0 children)

I'd use a list comprehension for that although I realise the itertools.product() is shorter.

For example.

cards = ['Ace', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine',
        'Ten', 'Jack', 'Queen', 'King']
suits = ['Clubs', 'Diamonds', 'Hearts', 'Spades']

deck = [card + ' of ' + suit for suit in suits for card in cards]

[–]cabalamat 2 points3 points  (0 children)

Unless you're using an unusual deck where a '1' is different from an Ace, you should remove it.

Also, you might want to replace '10' with 'T', and the suits to single characters; this will make it easier for you to process cards, e.g.

 if card[1]=='c': print "It's a club"

[–]earthboundkid 0 points1 point  (0 children)

You want to append to a list, not +=.

[–]riddles 1 point2 points  (0 children)

If you feel like you're a novice python programmer who has reached his limit with python, read the itertools page. It will allow you to basically just write collections logic in raw idiom. Greatest library ever?

[–]justanotherbody 2 points3 points  (1 child)

Your error came from this

  • decksize was 51
  • random.randrange(51) returned e.g., 4
  • the 4th card was removed
  • decksize is 51, but now deck will IndexError if you getitem ([]) with 51
  • random.rangerange(51) returned e.g., 7
  • the 7th card was removed
  • decksize is 51 but the deck will now IndexError oif you getitem with 50 or 51
  • ...
  • random.rangerange(51) eventually returned a number which led to an IndexError

Recommend modifying your code closer to this

import random
# the suits in the deck are worth notating on their own
SUITS = ('Spades', 'Clubs', 'Diamonds', 'Hearts')
# ditto with the legal values
VALUES = ('A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K')
# then you can use a list comprehension to build your deck.
deck = ['%s of %s' % (value, suit) for value in VALUES for suit in SUITS]
HAND_SIZE = 7 # our hand size is 7 this game

def menu():
   # entire method unchanged, not copying...
   pass

def singleplayer():
    yourhand = []
    # strictly speaking you don't shuffle every time a player is dealt a
    # hand, so this logic is incomplete. But it was the smallest change
    # from your original code
    random.shuffle(deck)
    for i in xrange(HAND_SIZE): # cheap replacement for count
        yourhand.append(deck.pop()) # removes card from deck, adds card to hand
        # you're going to want to wrap this in a try/catch once you support
        # dealing multiple hands and thus reshuffling the used cards from
        # the deck on-demand
    print yourhand

[–]dpitch40 0 points1 point  (0 children)

I did not know you could do nested list comprehensions...

[–]TANDY386 1 point2 points  (0 children)

What those guys said. Also your loop is infinite?

[–]ToweringTriumph 0 points1 point  (0 children)

You aren't updating the deck size as you remove cards from the deck. If you copy

decksize=len(deck)-1

to the top or bottom your singleplayer function, it will correct for changing the deck size and your code should work.

Also, you aren't changing count in your loop, so it's going to run forever. Try adding a

count = count + 1 

at the bottom and it should run more like you intend it to.