Python function card deal - python

Write a function, deal(numhands, n=5, deck), that
deals numhands hands with n cards each.
import random # this will be a useful library for shuffling
from random import shuffle
# This builds a deck of 52 cards. If you are unfamiliar with this
# notation, check out Andy's supplemental video
# on list comprehensions (you can find the link in the
# Instructor Comments box below).
mydeck = [r+s for r in '23456789TJQKA' for s in 'SHDC']
def deal(numhands, n=5, deck=mydeck):
mynew = shuffle(deck)
if numhands*n > len(deck):
raise Exception('Not enough cards.')
hands = []
for i in range(0,numhands):
ncards = []
for j in range(0,n):
ncards.append(mynew.pop())
hands.append(ncards)
return hands
print deal(2)
I am not sure what is wrong with the function but it keeps telling me this error
in deal
ncards.append(mynew.pop())
AttributeError: 'NoneType' object has no attribute 'pop'

random.shuffle shuffles in place
it changes the original deck ... it does not return anything
so just use deck

Related

Checking if index in list exists

I would like to note that I'm using Discord.py and some of it's included libs.
So I'm trying to check if an index in a list exists but I keep getting the ValueError saying that the index does not exist in my list.
Here's my code:
def deal_card(self):
U = self.usedCards
randCard = randchoice(list(self.cards))
if not U: #check if it is empty
#if it is empty, just add the card to used cards
U.append(randCard)
elif U.index(randCard): #check if card is already in the list
#if it is, pick another one
randCard = randchoice(list(self.cards))
U.append(randCard)
else: #check if card is not in list
#if it is not, just add it to the used cards
U.append(randCard)
return randCard
self.cards is full of card names and self.usedCards is a list of cards alredy picked by randCard.
hand is my command and P4 is one of the cards in self.cards
I found some solutions saying that adding a try block will solve the problem but I don't know how to add it in the middle of my if statement.
Thanks in advance!
list.index() should be used for finding the index of a list's member. To check whether an item is in a list, simply use in:
if not U:
# do stuff
elif randCard in U:
# do other stuff
This is probably a terrible way to deal your cards, because then you have the cards both in your discard pile and in your deck.
Why not just move the cards around?
import random
cards = ['H{}'.format(val) for val in range(1, 11)]
print(cards)
discard_pile = []
while cards:
random.shuffle(cards)
card = cards.pop()
print('You drew a {}'.format(card))
discard_pile.append(card)
while discard_pile:
cards.append(discard_pile.pop())
# or
cards.extend(discard_pile)
discard_pile.clear()
You don't need to use the index function:
elif randCard in U:
If you would still like to use the .index function for some reason and not follow the above suggestions you could use the try statement as follows:
try:
c = U.index(randCard)
randCard = randchoice(list(self.cards))
U.append(randCard)
except ValueError:
U.append(randCard)

Random choice function

I am making a game using pygame based on the game war. I am getting an error when running the code for splitting my deck in the main loop (it is in its own file). The error says:
"/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/random.py", line 275, in choice
return seq[int(self.random() * len(seq))] # raises IndexError if seq is empty
IndexError: list index out of range
The deck splitting file looks like this:
import Deck
from random import *
deck = Deck.deck
playerDeck = []
AIDeck = []
def splitDeck():
player_deck_count = 26
while player_deck_count > 0:
transfer_card = (choice(deck))
playerDeck.append(transfer_card)
deck.remove(transfer_card)
player_deck_count -= 1
AIDeck = deck
shuffle(playerDeck)
shuffle(AIDeck)
print "Player deck length:" + str(len(playerDeck))
print "AI deck length:" + str(len(AIDeck))
print "Deck length:" + str(len(deck))
The Deck file looks like this:
deck = [
'2_c',
'2_d',
'2_h',
'2_s',
I get that is has to do with the sequence (list is empty) but there is obviously still 26 cards in the original deck. I have tried changing when the while player_deck_count loop stops but with no luck. Thanks for the help in advance
P.S. just comment if you want the main loop.
I believe your problem is that you are relying on the function to set the value of AIDeck. When you attempt to set
AIDeck = deck
you are moving the reference of AIDeck to the reference of deck. When the function returns, AIDeck is restored to its original definition, which was the empty list. If you are doing choice(AIDeck) anywhere in your file, it is probably the cause of your error.

recursive function in class in python

I don't know, why isn't working that code in python. The problem is, that I can get numbers, but sometimes some numbers are uniform. And I want to do 5 different numbers between 1 and 90.
class lottery:
def __init__(self):
self.price = 50
def list(self):
numbers = []
for i in range(0,5):
numbers.append(random.randint(0,90))
for i in range(1,5):
for j in range(0,i-1):
if (numbers[i]==numbers[j]):
game.list()
return numbers
game = lottery()
game.list()
Or is there any better way to solve my problem?
Thanks!
Use random.sample:
def list(self):
return random.sample(xrange(90), 5)
This is (especially for large values of 5) much more efficient than starting over every time your randomization creates a repeat, and also avoids the possibility of overflowing the stack.
First of all you should import the random module:
import random
The problem is that you are not returning the result that you get from the recursive call, therefore you are still returning the list with repeated numbers. It should be:
def list(self):
numbers = []
for i in range(0, 5):
numbers.append(random.randint(0, 90))
for i in range(1, 5):
for j in range(0, i - 1):
if (numbers[i] == numbers[j]):
return self.list() # return
return numbers
note that self is used to access to the instance of the class that calls the method. Also, don't forget to print the results:
game = lottery()
print game.list()
Note:
Don't use list as the name of a variable or method because it will hide the built-in definition of list.

Dealing Cards in Python? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
I'm making a program that deals cards and assigns 5 random cards to each player, and it works up until I try to print the hands of each player (showHand function). I am trying to print the cards the given player has but it's telling me "cards" isn't a global attribute. I know it isn't, but I don't know how to print the cards for the player otherwise. Help?
import random
NUMCARDS = 52
DECK = 0
PLAYER = 1
COMP = 2
cardLoc = [0] * NUMCARDS
suitName = ("hearts", "diamonds", "spades", "clubs")
rankName = ("Ace", "Two", "Three", "Four", "Five", "Six", "Seven",
"Eight", "Nine", "Ten", "Jack", "Queen", "King")
playerName = ("deck", "player", "computer")
#assigns random card to given player
def assignCard(str):
#generates random card number to assign to player
randomNum = random.randrange(0, NUMCARDS-1)
#makes sure card being picked for player is not already assigned to another player
while cardLoc[randomNum] != 0:
randomNum = random.randrange(0, NUMCARDS-1)
cardLoc[randomNum] = str
#shows all the cards in the deck
def showDeck():
print "# Card Location"
print "---------------------------"
cardNum = 0
for x in rankName:
#assigns all ranks
rank = x
for y in suitName:
#assigns all suits
suit = y
cards = "%s of %s" % (rank, suit)
cardNum += 1
location = cardLoc[cardNum-1]
location = detLocation(location)
print "%s %s %s" % (cardNum, cards, location)
global cards
#has program print out appropriate location instead of number
def detLocation(location):
if location == PLAYER:
return "Player"
elif location == COMP:
return "Computer"
else:
return "Deck"
#shows given player's hand... but not their foot (;
def showHand(str):
global cards
location = detLocation(str)
print "Displaying %s Hand:" %location
for i in range(5):
cardLoc[cards] = str
print "%s" % cardNum
#calls all functions necessary
def main():
clearDeck()
for i in range(5):
assignCard(PLAYER)
assignCard(COMP)
#showDeck()
showHand(PLAYER)
showHand(COMP)
First of all your assignCard function doesn't modify the global variable (I assume that is what you actually wont to do)
so you have to add a line there like global cardLoc
having modified this global variable you can print your cards with the following code
for i in range(NUMCARDS-1):
if cardLoc[i] == str:
print whatever card is assigned to the position of i in your deck.
I think you need a global cards object that gets initialized and contains the label. Similar to what you do in showDeck. It could be just an array of NUMCARDS. Then in showHand you iterate through cardLoc and print only the ones given to the user:
for i in NUMCARDS:
if cardLoc[i] == str:
print cards[i]
I'm just not sure your object hierarchy is the most proper one for this case, but I'm just trying to solve your issue without heavily modifying your code.
This might not help with your specific problem, but perhaps it will give you some ideas as you go forward with Python.
import random
def main():
suits = 'S H D C'.split()
ranks = '2 3 4 5 6 7 8 9 X J Q K A'.split()
deck = [r + s for s in suits for r in ranks]
n_players = 4
hand_size = 5
random.shuffle(deck)
hands = deal(deck, n_players, hand_size)
for h in hands:
print h
def deal(deck, n_players, hand_size):
# A general-purpose dealing function.
# It takes a deck and returns a list of hands.
# Each hand is a list of cards dealt from the top of the deck.
hands = [[] for _ in range(n_players)]
i = -1
for _ in range(hand_size):
for h in hands:
i += 1
h.append(deck[i])
return hands
main()
A few general points about the example:
Rather than selecting random items from a list (and then worrying about whether subsequent selections are duplicates of prior selections) this example simply shuffles the deck and then deals from the top.
The dealing function does not rely on any global variables. Instead it receives the deck and other parameters as arguments and then returns the desired hands. To the extent that you can organize your programs to minimize (and localize) reliance on global variables you are usually better off (for many reasons).
The example uses list comprehension, which is a handy technique for creating lists in Python (where deck and hands are initialized).
A number of problems, so I suggest the real fix would be to throw this away and start over.
First thing to do: strings are for people, not computers, so don't represent cards as strings until you have to print something. Everywhere else, they should be numbers. Either a single number for each card, or a "card" object with numbers for rank and suit. Both player hands and decks are then just simple arrays (or in Python, lists).
Create a single global "deck" list from which to deal all the cards, initialize it with one of each, then deal to the player hands. There are two ways to deal random cards from a deck--your method is neither of them. Either (1) "shuffle" the deck using an algorithm called Fisher-Yates (Python's random.shuffle() does this) and pop cards off the end of the deck array as you append them to hand arrays, or (2) To deal each card, select a card randomly from the remaining cards deck, append it to the hand, and remove it from the deck. This is also easy in Python with random.choose() and remove().
A minor pythonism: don't use "str" as a variable name, it's already a built-in type.

List comprehension without using an iterable

I am trying to build a list by picking random elements from another list with no duplicates. Think shuffling a pack of cards. I could obviously write some unpythonic code for this, which I dont want to.
So here is what I am trying to do:
new = [deck[i] where 0<(i = some_rand_int)<51 if new.count(deck[i]) == 0]
Is there a way to do this?
I am trying to build a list by picking random elements from another list with no duplicates.
Use random.sample:
random.sample(population, k)
Return a k length list of unique elements chosen from the population sequence. Used for random sampling without replacement.
Try this:
result = random.sample(deck, n)
To shuffle the entire list use random.shuffle:
random.shuffle(deck)
Still curious if this can be done using list comprehension though!
Not really. A list comphrension preserves the order of the elements, but allows you to project them or filter them. Shuffling is not a projection or a filter.
You can use generators for this:
import random
def pick(deck):
while True:
try:
newCard = random.choice(deck)
deck.remove(newCard)
except:
print 'deck is empty...'
yield newCard
def resetDeck():
deck = []
newCard = None
for i in range(1,53):
deck.append(i)
return deck
pick(deck) picks a card from deck and if you wanted to recreate the deck use resetDeck().
after implementing, use pick(deck).next() to choose card from deck.

Categories

Resources