I have a list that's been modified in one function, and I want it to go to another function in order to be read and modified further.
def get_cards_player():
deck = Deck()
deck.shuffle()
player1 = []
player2 = []
you_won = False #if u won, var is true, if u lose, var is false
for i in range(5):
player1_cards = deck.get_card()
player1.append(player1_cards.get_name())
player2_cards = deck.get_card()
player2.append(player2_cards.get_name())
print('Your Hand:',', '.join(player1))
print('Opponent Hand:',', '.join(player2))
return player1, player2
def calc_winner():
I want player1 and player2 lists in get_cards_player function to go to the calc_winner function so that I can read the list and do stuff with it.
Thanks.
calc_winner should take these lists as parameters. I purposely changed the names to highlight that parameters don't have to have the same name in different functions.
get_cards_player already creates and returns the lists, so no need to change. Again, to show the different ways you can do this, I'm remembering the tuple containing the two players and using that in the call.
def calc_winner(p1list, p2list):
print(p1list, p2list)
players = get_card_player()
calc_winner(players[0], players[1])
Related
cards1 = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v']
def piles(cards1):
print("You must remember what card is yours!")
pile = [[],[],[]]
first = 0
second = 1
third = 2
for i in range (7):
pile[0].append(cards1[first])
pile[1].append(cards1[second])
pile[2].append(cards1[third])
first += 3
second += 3
third += 3
print(pile)
return(pile)
piles(cards1)
def sorting_piles():
sorted_piles = []
final_pile = []
which_pile = int(input("Which card is your pile in, 1,2 or 3?"))
for i in range (2):
while which_pile not in(1,2,3):
which_pile = int(input("Invalid input. Which card is your pile in, 1,2 or 3?"))
if which_pile == (1):
sorted_piles.append(pile[2,0,1])
elif which_pile == (2):
sorted_piles.append(pile[2,1,0])
else:
sorted_piles.append(pile[1,2,0])
print("This is now the new pile:",sorted_piles)
for i in range(7):
final_pile.append(sorted_piles[0][i-1])
for i in range(7):
final_pile.append(sorted_piles[1][i-1])
for i in range(7):
final_pile.append(sorted_piles[2][i-1])
print("Your card is:",final_pile[10])
return(final_pile)
sorting_piles()
Whenever I run this code, the first function runs perfectly and I am able to input which pile my card is in but after I input, I get this error message:
NameError: name 'pile' is not defined
How do I make the second function recognise the list 'pile'? Thanks
You have no variable that is catching the output being returned from the function definition. You need this :
pile = piles(cards1)
pile = piles(cards1)
You can use the return value .
Also pile[2,0,1] does not work with list.You can use (pile[2], pile[0],pile[1]).Append a tuple or list
You need to assign the return value of piles to a variable, then pass that to sorting_piles as an argument:
def sorting_piles(pile):
...
pile = piles(card1)
sorting_piles(pile)
This is a scoping issue. The pile variable defined in your piles function only exists in here, in this scope.
It looks like you're trying to access it from a different scope, inside your other function, where it doesn't exist.
You can simply create a global reference to the return value from your function like the other answers said:
pile = piles(cards1)
This question already has answers here:
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 6 years ago.
Needless to say the following code does not work and the fault or problem seems to be that the function does not access or recognise the list [cards]. On the other hand if I place the list [cards] within the function, the code works perfectly. I had assumed that variables placed in the main code were global, and variables declared in a function were just local.
#!/usr/bin/python
import random
cards = ['A︎♣︎︎', '2︎♣︎︎', '3︎♣︎︎', '4︎♣︎︎', '5︎♣︎︎', '6︎♣︎︎', '7︎♣︎︎', '8︎♣︎︎', '9︎♣︎︎', '10︎♣︎︎', 'J︎♣︎︎', 'Q︎♣︎︎',
'K︎♣︎︎', 'A♠︎', '2♠︎', '3♠︎', '4♠︎', '5♠︎', '6♠︎', '7♠︎', '8♠︎', '9♠︎', '10♠︎', 'J♠︎',
'Q♠︎', 'K♠︎', 'A︎♥︎', '2︎♥︎', '3︎♥︎', '4︎♥︎', '5︎♥︎', '6︎♥︎', '7︎♥︎', '8︎♥︎', '9︎♥︎', '10︎♥︎',
'J︎♥︎', 'Q︎♥︎', 'K︎♥︎', 'A︎♦︎︎', '2︎♦︎︎', '3︎♦︎︎', '4︎♦︎︎', '5︎♦︎︎', '6︎♦︎︎', '7︎♦︎︎', '8︎♦︎︎', '9︎♦︎︎',
'10︎♦︎︎', 'J︎♦︎︎', 'Q︎♦︎︎', 'K︎♦︎︎']
# define function
def sort_cards(hand):
temp = []
for n in range(0, 7):
temp.append(cards.index(str(hand[n])))
# sort cards
temp.sort()
hand = []
# fetch card according to index and assign to hand
for c in temp:
hand.append(cards[c])
return hand
# copy cards list to working list
rem_cards = cards
# initiate players card list
player1 = []
player2 = []
player3 = []
# define variable
# 7 cards per player
deal = 7
while deal != 0:
# get a card from rem_cards and assign to player1
card = rem_cards[random.randint(0, len(rem_cards) - 1)]
player1.append(card)
# remove card from deck
rem_cards.remove(card)
card = rem_cards[random.randint(0, len(rem_cards) - 1)]
player2.append(card)
rem_cards.remove(card)
card = rem_cards[random.randint(0, len(rem_cards) - 1)]
player3.append(card)
rem_cards.remove(card)
deal -= 1
print(sort_cards(player1))
print(sort_cards(player2))
print(sort_cards(player3))
print("No of cards left in the deck is ", len(rem_cards))
Any suggestions or is my concept just wrong?
Take a look at your comments:
# copy cards list to working list
rem_cards = cards
This code does not make a copy of the list, it creates another name, under which the original list could be accessed. Whenever you modify rem_cards, cards is modified. Thus, rem_cards.remove(card) actually removes the card from cards!
If you want to copy the list, use copy.[deep]copy:
import copy
# copy cards list to working list
rem_cards = copy.deepcopy(cards) # if cards could contain other lists
rem_cards = copy.copy(cards) # create a simple shallow copy
rem_cards = cards[:] # you may create shallow copies without the copy module
This also will solve your problem without using copy.deepcopy
rem_cards = cards[:]
rem_cards = cards
does not copy the list, but just creates an alias. It should be
rem_cards = list(cards)
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)
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.
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.