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)
Related
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])
I'm trying to understand how some code works so I've made my own simple code that should act like how the more complex code works. However, it seems that I'm missing something. I made a simple program to pass a "trigger" to compare to my list.
def function(findme, thislist):
print("FindMe: {}".format(findme))
print("In This List: {}".format(thislist))
if findme in thislist:
print("In!")
return thislist
while(True):
find = []
list = []
find.append(input("Input number to find: "))
print("Find: {}".format(find))
list.append(input("Input 1st number: "))
list.append(input("Input 2nd number: "))
print("List: {}".format(list))
result = function(find, list)
print(result)
if result is not None:
print("returned list")
print(list)
else:
print("nothing returned")
The code finishes returning None and printing "nothing returned". I input 1 as find and 1, 2 as list. What am I missing here?
p.s. I'm new to python and stack overflow, forgive my messy post :x
You cannot search if a list contains a sublist that way.
If you want to check if multiple elements are in the list, then you can do this instead
if (all(x in thislist for x in findme)):
print ("Sublist in the mainlist")
return thislist
This is one way to do it, if you do not have to compare lists, then you could simply use the code which you have just replace findme with findme[0]
The problem is, that the search value is a list itself. So you check if a list with one value is in the list with the values you want to find. It is not. The one value in the search list might be in the list with the values.
So you should use a single value as your search term.
I optimized the names of some variables, used f-strings for formatting and used fixed values for filling the list so you can test it faster.
def is_in_list(findme, data):
print(f"FindMe: {findme}")
print(f"In This List: {data}")
if findme in data:
print("In!")
return True
return False
find = input("Input number to find: ")
print(f"Find: {find}")
data = []
data.append("42")
data.append("23")
print(f"List: {data}")
if is_in_list(find, data):
print(data)
else:
print("nothing returned")
One more change. It doesn't make much sense to return the same list from the function that you put in there as a parameter. So I used return values of True and False instead.
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.
I have created a list class with a few simple methods.
class ListQ(object):
"""List object creation"""
def __init__(self, earlier_list=[]):
self.list=earlier_list
def isEmpty(self):
"""checks if list is empty"""
if len(self.list)==0:
return(True)
else:
return(False)
def put(self, new_item):
"""puts new_item last in list"""
self.list.append(new_item)
def get(self):
"""returns the next item in line"""
self.first_item = self.list.pop(0)
return self.first_item
I also have a function to help create these lists. (Helping to solve a magic card trick btw)
def create_card_list(card_list=None):
"""creates listQ of cards from user input"""
if card_list!=None: #if user already has list of cards
for item in card_list:
item=replace_card_strings(item) #replaces any strings in list
if item == False:
print('One of your cards does not exist, list creation failed')
return(False)
cards=ListQ(card_list)
The replace_card_strings() function has been properly tested and I do not believe it's at fault but here it is anyway.
def replace_card_strings(word):
"""replaces strings of words with their numbers and returns edited list"""
if type(word)!=int:
if word.lower()=='one':
word=1
elif word.lower()=='two':
word=2
elif word.lower()=='three':
word=3
elif word.lower()=='four':
word=4
elif word.lower()=='five':
word=5
elif word.lower()=='six':
word=6
elif word.lower()=='seven':
word=7
elif word.lower()=='eight':
word=8
elif word.lower()=='nine':
word=9
elif word.lower()=='ten':
word=10
elif word.lower()=='jack':
word=11
elif word.lower()=='queen':
word=12
elif word.lower()=='king':
word=13
elif word.lower()=='ace':
word=1
else:
word=False #if card doesnt exist
return(word)
When I run the following test is when the problem start.
cards=create_card_list(['one', 2, 3])
one=cards.get()
two=cards.get()
three=cards.get()
print(one, two, three)
if one==1 and two==2 and three==3:
print("create_card_list gives the correct answer")
else:
print("create_card_list gives the wrong answer")
It prints that the function has given the wrong answer and
the print(one, two, three) prints one 2 3 which is the original list.
Anybody have an idea where I've messed up?
You're not replacing items in the list, only in the loop's context:
Replace the entire loop:
for item in card_list:
item=replace_card_strings(item) #replaces any strings in list
....
Which does not do anything to the list (it does not "replace" the item).
With python's map which is used in order to apply a function to an iterable and create a list of results:
card_list = map(replace_card_strings, card_list)
If you don't want to use map you can use list comprehension:
card_list = [replace_card_strings(card_str) for card_str in card_list]
Now you'll have:
def create_card_list(card_list=None):
"""creates listQ of cards from user input"""
if card_list != None:
card_list = map(replace_card_strings, card_list)
cards=ListQ(card_list)
Tip:
You can replace the lengthy function replace_card_strings:
def replace_card_strings(word):
"""replaces strings of words with their numbers and returns edited list"""
word = word.lower()
string_to_int = {"one":1, "two":2 ...}
return word in string_to_int and string_to_int[word]
This works since and returns the last Truth-y result or the first False-y result.
You can also use dict.get:
# return word in string_to_int and string_to_int[word]
# try and read value from dict, return False otherwise
return string_to_int.get(word, False)
Which is cleaner (thanks #padraic).
Tip 2: You don't want two places referencing, and possibly mutating, the same list. It seems like you're keeping a reference to the same list that's used to construct a card list outside the generated object. This is prone to errors. What you should do is instead copy the list when it's passed:
def __init__(self, earlier_list=[]):
self.list=earlier_list[:]
Tip 3: python has a known "gotcha" with mutable default argument, which is exactly what you use here (earlier_list=[]). This is prone to errors as well since python binds default arguments once. You should instead have:
def __init__(self, earlier_list=None):
# copy passed list or create a new one if none passed.
self.list=earlier_list[:] if earlier_list else []
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.