Issue with calculating score - python

I am trying to generate a blackjack game but I cannot get the values my_score and computers_score to update. They keep giving me value of 0. Can anyone advise?
Code is below. I am expecting the sums of the picked cards for my hand and computer's hand to correspond to the scores, but I am getting return values of 0.
import random
# Create the deck and two empty hands
cards = [11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10]
my_hand = []
my_score = 0
computers_hand = []
computers_score = 0
# Choose two cards from deck randomly and place into each hand
def hand_builder(chosen_hand, chosen_score):
pick_card = random.choice(cards)
chosen_score = 0
chosen_hand.append(pick_card)
chosen_score += pick_card
for n in range(2):
hand_builder(my_hand,my_score)
hand_builder(computers_hand,computers_score)
print(my_hand)
print(my_score)
print(computers_hand)
print(computers_score)

You have to return your values:
import random
# Create the deck and two empty hands
cards = [11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10]
my_hand = []
my_score = 0
computers_hand = []
computers_score = 0
# Choose two cards from deck randomly and place into each hand
def hand_builder(chosen_hand, chosen_score):
pick_card = random.choice(cards)
chosen_score = 0
chosen_hand.append(pick_card)
chosen_score += pick_card
return chosen_score
for n in range(2):
# save the output from the function
my_score += hand_builder(my_hand,my_score)
computers_score += hand_builder(computers_hand,computers_score)
print(my_hand)
print(my_score)
print(computers_hand)
print(computers_score)
The reason that the _hand variable is updated is because it is a list. One can update a list in a function without returning a value.
Please read for exmaple: https://www.mygreatlearning.com/blog/understanding-mutable-and-immutable-in-python/
Or use google to look into mutable and immutable variables.

Related

Why is my RLE encoder working for some inputs but not others?

'''
def encode_rle(flat_data):
rle_complete = []
run_length = 0
num_variables = count_runs(flat_data)
# goes through each value in flat_data
for item in flat_data:
if item not in rle_complete: # if item is not in blank list then it is added
rle_complete.append(item)
x = 0
# current item in rle_complete is the first value
current = rle_complete[x]
rle_final = []
for item in rle_complete: # for each value in rle_complete
for item in flat_data: # for each value in original data
if current == item:
run_length += 1 # add a value to count
else: # when current value in rle_complete stops being
# the same as the current value in flat_data the rle_final is updated
rle_final.extend([run_length, current])
current = rle_complete[x + 1]
run_length = 1
num_variables -= 1
if num_variables == 0:
break
return rle_final
'''
I am using the latest version of python and pycharm. When it comes to my code the function works if I use the input [15, 15, 15, 4, 4, 4, 4, 4, 4] I get the correct output [3, 15, 6, 4]. However when I change the input to anything else like [15, 15, 15, 4, 4, 4, 4, 4, 5] the output is completely wrong and different. Any help would be appreciated. The count_runs function that you see in my code simply counts the amount of unique variables within the input.

calling function multiple times with new results

I wanted to create a poker simulation that creates a certain number of 5-card poker hands, to see how many times hands I need to play till I get the royal flush...
I wrote a function that generates 5 cards but when i run the function multiple times it won't work --> i get 5*x cards instead of multiple hands with each 5 cards
import random
d = []
h = []
def cards():
l1 = ["Herz", "Karo", "Pik", "Kreuz"]
l2 = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
for i in range(10):
d.append([])
for k in range(10):
d[k].append(l1[random.randint(0, (len(l1) - 1))])
d[k].append(l2[random.randint(0, (len(l2) - 1))])
for a in d:
if a not in h:
h.append(a)
if len(h) == 5:
break
else:
continue
return h
for i in range(2):
print(cards())
When I run the code, I get the following:
[['Karo', 8], ['Herz', 5], ['Pik', 13], ['Herz', 12], ['Karo', 3]]
[['Karo', 8, 'Karo', 5], ['Herz', 5, 'Karo', 6], ['Pik', 13, 'Herz',
4], ['Herz', 12, 'Herz', 5], ['Karo', 3, 'Pik', 3], ['Karo', 8,
'Kreuz', 3], ['Karo', 9, 'Kreuz', 3], ['Pik', 13, 'Herz', 10], ['Pik',
6, 'Karo', 11], ['Karo', 2, 'Pik', 13], []]
Your code currently has global lists that it keeps appending to. This is almost certainly not what you want.
I would suggest creating a deck of cards, and sampling them without replacement to get a hand of five. You can get up to 10 such hands from a deck of 52 cards. A better way might be to create the deck and shuffle it, picking off 5 cards at a time until it contains fewer than 5 cards.
In either case, you could then pass each hand through a function that tests if it is a flush or whatever else you want.
All the tools you will need for this (until you use numpy), are in the itertools and random modules.
First create a global deck. There is no need to do this multiple times because it will slow you down to no purpose. The deck of cards won't change, only their order will:
rank = [str(x) for x in range(2, 11)] + list('JQKA')
suit = list('♠♥♦♣')
deck = list(''.join(card) for card in itertools.product(rank, suit))
Now you can use this deck to generate from 1 to 10 hands at a time with no repeating cards between them. The key is that shuffling the deck is done in place. You don't have to regenerate the deck every time:
def make_hands(cards=5, hands=None):
if hands is None:
hands = len(deck) // cards
if cards * hands > len(deck):
raise ValueError('you ask for too much')
if cards < 1 or hands < 1:
raise ValueError('you ask for too little')
random.shuffle(deck)
result = [deck[cards * i:cards * i + cards] for i in range(hands)]
You can change the desired number of cards per hand and hands per deck with this function. Let's say that you also have a function to check if a hand is a flush or not called isflush. You could apply it like this:
def how_many():
shuffles = 0
hands = 0
while True:
shuffles += 1
cards = make_hands()
for hand in cards:
hands += 1
if isflush(hand):
return shuttles, hands
shuffles, hands = how_many()
print(f'It took {hands} hands with {shuffles} reshuffles to find a flush')

Create a list of random integers and then put all numbers that are the same right beside eachother

def run():
lst=[]
for i in range(0,20):
ran = random.randint(1,10)
lst.append(ran)
return lst
So far I have created a list of random integers from 1 to 9 with 20 values, however how can I incorporate a swapping method so that values that are the same but not next to eachother will be next to eachother?
Thanks
You can build your own sorting criteria using indexes for the key argument.
import random
def run():
lst=[]
for i in range(0,20):
ran = random.randint(1,10)
lst.append(ran)
return lst
lst = run()
print(lst)
#[5, 10, 5, 1, 8, 10, 10, 6, 4, 9, 3, 9, 6, 9, 2, 9, 9, 1, 7, 8]
result = sorted(lst, key = lambda x: lst.index(x))
print(result)
#[5, 5, 10, 10, 10, 1, 1, 8, 8, 6, 6, 4, 9, 9, 9, 9, 9, 3, 2, 7]
Perhaps just sort the list:
lst = sorted(lst)
import random
#this is the function you gave with little edits, to see the changes it make
# after the process
def run():
lst=[]
for i in range(0,20):
ran = random.randint(1,10)
lst.append(ran)
print(lst)
swap(lst)
print(lst)
return lst
#this uses indexes of every element, and checks every other element of the list.
#this swap function works for lists with element made up of strings as well.
def swap(lst):
for i in range(len(lst)):
nu_m=lst[i]
x=i+1
while x<len(lst):
dump=i+1
acc=lst[i+1]
if(lst[i]==lst[x]):
lst[dump]=lst[x]
lst[x]=acc
x=x+1
x=run()
First let's create another list to keep the order of the unique numbers (like a set, but not sorted).
unsorted_set = []
for nb in lst:
if nb not in unsorted_set:
unsorted_set.append(nb)
Now that we got this list, let's create a final list that will continue that list but each number will be repeated n times, n is the occurences of the number in the first list. We will do this with lst.count()
final_list = []
for nb in unsorted_set:
for _ in range(lst.count(nb)):
final_list.append(nb)
Note that this code can be simplified a lot with List Comprehension.

Shuffling an array without built in functions?

Trying to shuffle an array without using built in functions.
def shuffle2():
lis = [5,6,7,10,11,12]
print (lis)
x = random.randint (0,len (lis)-1)
y = random.randint (0,len (lis)-1)
z = lis[x], lis[y] = lis[y], lis[x]#flips the elements around
shuffle2()
So far it switches two elements around once, however I need it to shuffle the whole array rather than just two positions.
output:
[5, 6, 7, 10, 11, 12]
[11, 6, 7, 10, 5, 12]
Any ideas?
Here's one way:
import bisect
import random
def shuffle(lis):
newlis = []
temp = []
for i in lis:
x = random.random()
#put x into temp and put i into the same place in newlis
n = bisect.bisect(temp,x)
temp.insert(n,x)
newlis.insert(n,i)
return newlis
lis=[5,6,7,10,11,12]
>>> shuffle(lis)
[6, 12, 10, 11, 7, 5]
The method essentially generate random numbers and puts them into a sorted list (temp). The items is lis are put into a newlis in the same way, which has the effect of sorting it.
You, of course, can write your own bisect, or use a more trivial search function quite easily...
import random
def shuffle2():
i = 1
lis = [5,6,7,10,11,12]
print (lis)
while i < len(lis):
x = random.randint (0,len (lis)-1)
y = random.randint (0,len (lis)-1)
z = lis[x], lis[y] = lis[y], lis[x]
i = i + 1
#flips the elements around
print (lis)

using += to populate a list through while loop gives me an error

I have a very basic understanding that += and .append are quite similar in terms of appending new element to a list. However, I find them perform differently when I try to populate a list with random integer values through while loop. append works well, however, running my program with += will give me an error :
TypeError: 'int' object is not iterable
Here is my code:
1.use +=
import random
random_list = []
list_length = 20
# Write code here and use a while loop to populate this list of random integers.
i = 0
while i < 20:
random_list += random.randint(0,10)
i = i + 1
print random_list
**TypeError: 'int' object is not iterable**
2.use .append
import random
random_list = []
list_length = 20
# Write code here and use a while loop to populate this list of random integers.
i = 0
while i < 20:
random_list.append(random.randint(0,10))
i = i + 1
print random_list
**[4, 7, 0, 6, 3, 0, 1, 8, 5, 10, 9, 3, 4, 6, 1, 1, 4, 0, 10, 8]**
Does anyone know why would this happen?
This happens because += is for appending a list to the end of another list, not for appending an item.
It is the short version of doing:
items = items + new_value
If new_value isn't a list this will fail because you can't use + to add a item to a list.
items = items + 5 # Error: can only add two list together
The solution is to make the value into a one-item long list:
items += [value]
Or to use .append - the preferred way to add single items to a list.
Yes, it's tricky. just add a , at end of random.randint(0, 10)
import random
random_list = []
list_length = 20
# Write code here and use a while loop to populate this list of random integers.
i = 0
while i < 20:
random_list += random.randint(0, 10),
i += 1
print random_list
It will print:
[4, 7, 7, 10, 0, 5, 10, 2, 6, 2, 6, 0, 2, 7, 5, 8, 9, 8, 0, 2]
You can find more explanation about trailing ,

Categories