Python list doesn't seem to be updating - python

I'm fairly new to python and I'm trying to create blackjack. However, when I'm trying to print out what the player's hand is, I run into a few difficulties.
This is my code for hitting (drawing a card):
def hit(card, deck):
global money, choice
choice = input("How much would you like to bet?\n")
money -= int(choice)
print("You have decided to bet $" + str(choice))
card = card.drawCard(deck.deck)
card.getPt()
deck.addScore(card)
deck.addCard(card)
c = str(card)
p = str(deck)
print("You have drawn: " + str(c) + "\n")
print("The player has:\n" + str(p) + "\n")
print("Total score:", deck.score)
And this is my code for printing my cards out:
def __str__(self):
for i in range(0, len(self.deck)):
self.print = self.print + "\n" + str(self.deck[i])
return self.print
The first thing my code does is draw two cards for the dealer and the player, which runs fine. However, after the player draws a card is where it gets a bit wonky. The output is something like this:
The player has drawn Card A
The player has drawn Card B
Total score: number
How much would you like to bet?
number
You have bet number
You have drawn Card B
Player has:
Card A
Card B
Card A
Card B
Card B
When I draw a new card, the card doesn't change, it stays the last card I drew. Then, when I print my deck, it prints my old deck and my new deck. However, the score is correct, which indicates that my list is only three cards long. What is going on, and why is it printing five cards?
Full code
Example output

Well, to get to the answer in short: you never reset Deck.print. So it keeps accumulating at each call to __str__
But in general this code could be improved significantly
E.g. your __str__ function is far from being pythonic. Something along the lines of
return '\n'.join(self.deck)
would look much better.
In general there is no need to prepend each variable with "self." if they are used within the function only. In most cases in a class method you either update an object variable (self.something) or return some value from the function, but not both.
There may, of course, be exceptions to this, but it seems in your case this is the rule and not the exception.
Using globals is also something you should avoid whenever possible.

Related

My function is too long. In order to pass class I need < 18 lines

So I am a total beginner yet this is 100% my code and I am proud of it. Now mind you I need a little cleaning up, however it does what I want it too. My issue is this: In order to turn this in for credit, one of the things is that procedures(functions) should not contain more than 18 lines. My function gameCont() has many more. Would anyone have suggestions on how I could shorten it up? Additionally I am obviously challenged when it comes to function parameters so any help is appreciated. Please be gentle as I am BRAND NEW! :)
game1 = "When dealing with SCUBA diving there are many dangers to consider. The very first one is _1_. \
I mean if you take water into your lungs, you are NOT SCUBA diving. Another is rising to the surface too quickly which could \
result in the _2_. Now this is a funny name, as I am sure when it happens, you dont feel 'bendy'. Let's also consider Nitrogen Narcosis.\
If you dont know what that is, well when you are very deep and your body is absorbing more nitrogen than it is used to, you can get \
feeling kinda _3_ feeling as though you just drank not one, but _4_ martinis"
game1_answers = ["drowning", "bends", "drunk", "2"]
game2 = "When you first learn to dive you are taught to do dives within a no DECOmpression limit(NDL). \n This means you do not want to \
stay that deep too long or you will rack up _1_. \n If you DO stay longer than what the NDL allows, you will have an obligation to \
take your time getting to the surface allowing that _2_ gas to leave your body. If you were taking IN gas you may call it \
in-gassing, but when you are decompressing, it may be called _3_-gassing. You are taught also, how to read _4_"
game2_answers = ["deco", "nitrogen", "off", "tables"]
game3 = "Equipment used by cold water divers such as myself are as such. On my head I would wear a _1_. To help regulate the breathing\
pressure from my SCUBA tank I would use a _2_. To help me propel through the water I would place_3_ on my feet. Considering \
we cannot see underwater I need to be wearing a _4_ on my face. Diving in the tropic, many people would use wetsuits, however it's\
very cold where I dive so we wear _5_ suits."
game3_answers = ["hood", "regulator", "fins", "mask", "dry"]
def howManyTries():
gameTries = raw_input("Thanks for giving my quiz a try, how many attempts do you want? ")
return int(gameTries)
def game_choice(): #this function is used to determin which difficulty the user wants and returns the proper game and answer list
user_input = raw_input("Greetings. This is my Udacity project for fill in the blanks. Which one of my options would you like?\
easy, hard, or hardest? Please take note of capitalization ")# this will define the user_input variable to raw input placed in by user
print ("\n" * 20)# just something to clean up the screen
print "Decided to choose " + user_input + '?' " Well " + user_input + " it is"# this confirms to the user which difficulty they chose.
print ""
print ""
if user_input == "easy": #easy returns game1 and game1 answers
return game1, game1_answers
elif user_input == "hard": # hard returns game2 and game2 answers
return game2, game2_answers
elif user_input == "hardest": #hardest returns game3 and game 3 answers
return game3, game3_answers
else:
print "It seems that " + user_input + " is not a valid response" #in case the user doesnt choose or spell choice correctly
def gameCont():
blanks = 1 #this assings blank to 1 which will tell the user which blank they are guessing in below prompt
attempts = howManyTries() #this calls the howManyTries function for a user choice integer
quiz, answers = game_choice() #this returns 2 values (game# and game# answers)
while attempts > 0: #while attempts (called from function) is greater than 0 we will loop this
print quiz #prints the chosen quiz for user updated each time the loop runs with correct answer
print("\n" * 10) #clears some more screen to loook better for the user
guess = raw_input("Reading the above paragraph, What would your guess be for _" + str(blanks) + "_") #asks for guess for current blank which always starts at 1
print("\n" * 10) #clears some more screen to loook better for the user
if guess == answers[blanks - 1]: #because indexing count starts at zero, and blanks start at 1 this will check if answer is equal to blanks - 1
print "As you can see your correct choice has replaced the variable, great job!!"#this will print if the guess is correct
quiz = quiz.replace("_" + str(blanks) +"_", answers[blanks - 1]) # here is the line of code that replaces the blank with the correct guess
blanks += 1 # this adds 1 to the blank which will prompt the user to move to the NEXT blank when loop begins again
if blanks > len(answers):
print ("\n" * 10)
print "YOU DID IT!! Here is the final paragraph with all the correct answers"
print ("\n" * 2)
print quiz
break
elif guess != answers[blanks -1]: #if the answer does not match the list index
attempts = attempts - 1 #then we will subtract 1 from the attempts
print ("\n" * 10)
print "Oops that is not correct, there should be hints in the paragraph" # lets user know they were wrong
print "You have " + str(attempts) + " attempts left." # lets the user know how many attempts they have left
print ""
if attempts < 1:
print "Well it looks like you are out of choices, Try again?"
break
print "Thanks for playing"
gameCont()
All of the printing that you're doing could be done in a separate function
def game_print(newlines_before, text, newlines_after)
print ("\n" * newlines_before + text + "\n" * newlines_after)
Two suggestions:
Delegate tasks that are accomplished by your function to smaller functions. So, for example, if you had a function that needed perform task A and performing that task could be divided into tasks B, C, and D, then create helper functions and call them inside of the function that does task A.
You have long strings, maybe store them somewhere else? Create a class just for constant strings of related functions and access that when you need a particular string. It'll make it less likely that you'll make a mistake when you need to use that string in multiple locations.
class Constants:
str1 = "..."
str2 = "..."
print(Constants.str1)
you can call a function from inside another function. inside an if statement you could call a small new function that just prints some stuff. this should make it easy to get the function size down.
something like this should work:
def correct(quiz, blanks):
print "As you can see your correct choice has replaced the variable, great job!!"
quiz = quiz.replace("_" + str(blanks) +"_", answers[blanks - 1]) # here is the line of code that replaces the blank with the correct guess
blanks += 1 # this adds 1 to the blank which will prompt the user to move to the NEXT blank when loop begins again
if blanks > len(answers):
print ("\n" * 10)
print "YOU DID IT!! Here is the final paragraph with all the correct answers"
print ("\n" * 2)
print quiz`
remember that you still want to break after calling that function in order to exit your loop.

Modifying a dictionary inside of an if statement

I've been trying to make a basic text game in Python, and I'm using dictionaries to contain the player's information. I want to make it so that when a player's health reaches 0, the code will stop running. I've had trouble making that happen. My dictionary, which is at the beginning of my code, looks like this:
playerAtt = {}
playerAtt["Weapon"] = "Baseball bat"
playerAtt["Party"] = "Empty"
playerAtt["Health"] = 15
playerAtt["Cash"] = "$100"
print(playerAtt)
if playerAtt['Health'] <= 0:
exit()
The bottom section is what I wrote to try and make the code stop running when the player's health reached zero, but it doesn't seem to work. In one path of my game, your health gets set to zero and the game is supposed to end, but the program continues to run:
townChoice = raw_input("You met a traveler in the town. 'Yo. I'm Bob. Let's be friends.' Will you invite him to your party? Y/N\n")
if townChoice == 'y' or townChoice == 'Y':
print("That kind traveler was not such a kind traveler. He stabbed you with a machete. RIP " + Name + '.')
playerAtt['Health'] == 0
When you reach this part of the game, all it does is print the message, and moves on to the next decision. In this situation, I could just manually end the program by doing exit() under the print command, but there are circumstances where the player only loses a fraction of their health, and they would eventually reach zero. Sorry if this is a stupid question, I've only been working on Python for a few days.
You have two "=" when you set the player's health to 0
I had put 2 == instead of 1 = when defining
playerAtt["Health"].
Also, I needed to make sure it was constantly checking if the player's health was zero, so I used a while loop. I used
while playerAtt["Health"] = 0:
deathmsg()
exit()
to fix it. deathMsg was a function I made to display a random death message, for more information.

Return function does not seem to be working

I am trying to make a Blackjack game in Python and I made a separate function for each option to hit stay etc... When I call each function, I pass it the players hand total so far: ​​​
def hit(PlayerHand):
PlayerCard3 = random.randint(2,10)
print("You got %s" %PlayerCard3)
PlayerHand = PlayerHand+PlayerCard3
return(PlayerHand)
And then I print the players total hand outside of the function but it returns the previous value of PlayerHand and not the new value. I'm not sure what to do.
Make sure you are saving the new value:
print("New value is: {}".format(hit(PlayerHand)))
or
PlayerHand=hit(PlayerHand)
print(PlayerHand)

I/O python: Handling output and variable

Good day :)
So during the day, I decided to make a gambling simulation. I'm testing a fail gambling strategy (So mine you if you try to tried my method)
Let me show my code, then the whole thing what happened.
from random import randint
winningNumber=0
bankroll=5000
testCase=1
betLevel=0
bettingLevel=[1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987]
town=[]
bet=0
#----------------------------
my_file= open("output.txt","w")
my_file.write(" # Bet Number Outcome bankroll "+"\n")
def startTheSimulation():
print "OK"
for i in range(100):
if bankroll==0:
break
global betLevel
if bankroll < bettingLevel[betLevel]:
betLevel=0
bet= bettingLevel[betLevel]
print "betlevel",betLevel
print "bet",bet
winningNumber= randint(0,36)
print "winningnumber",winningNumber
if winningNumber== 4:
win(bet)
else:
lose(bet)
def win(inbox):
global bankroll
cow= inbox*35
bankroll+=cow
print "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"
print "bankroll",bankroll
town=[testCase,bet,winningNumber,"WIN",bankroll]
print town
betLevel=0
writing()
def lose(inbox):
global bankroll
global betLevel
wow= inbox
bankroll-=wow
town=[testCase,bet,winningNumber,"LOSE",bankroll]
betLevel+=1
if betLevel==16:
betLevel=15
writing()
def writing():
global testCase
testCase+=1
print "Hey!"
my_file.write(" ".join(town)+"\n")
startTheSimulation()
my_file.write("On all betting, player bet single bet on one number, which is number 4. How money money bet on number for is indicated.")
my_file.close()
My betting system is a weird one. It works like martingale betting system, but instead of doubling my bet, my next bet is based on Fibonacci sequence.
The parameter betLevel is used to decide how many should I bet. The bettingLevel shows the list of the Fibonnaci sequence.
Here comes trouble
Trouble #1:
My output contains blank line
The desired output file is this
& Bet Number Outcome bankroll
# 100 lines of information
On all betting, player bet single bet on one number, which is number 4. How money money bet on number for is indicated.
However, I in turn got this
& Bet Number Outcome bankroll
# 100 BLANK LINES
On all betting, player bet single bet on one number, which is number 4. How money money bet on number for is indicated.
My debugging process:
I actually print the list town. The list if filled (not empty). No other improvement.
Trouble #2: (Solved by using function with arguments.)
My bank roll doesn't update.
My debugging process:
I figured out the problem.
Notice the win function. When I print (int(35)*int(bet)). It turns out to return 0, causing the bankroll not moving.
HOWEVER
When I print "bet",bet in the startTheSimulation() function, it prints the right number. I'm stucked here.
That's my 2 biggest problem. Any help is appreciated.
PS: I use global to avoid UnBoundLocalError
PPS: I use Python 2.7.6
Your logic seems quite convoluted for a fairly simple process. Also, you write things like int(35), that tell me you just came to Python from another language (IDL, perhaps?).
If you are using this as an exercise to learn, I can give you a few hints on how to solve it:
First of all, global variables are almost always a bad idea. If you need to use one, you are probably doing something wrong. The proper way of sharing this information is creating a class. Something like this (very incomplete)
class Simulation(object):
def __init__(self, bankroll):
self.betlevel = 0
self.betting = [1, 1, 2, 3, 5] # You should actually generate this on the fly
self.bankroll = bankroll
self.outputfile = open('filename.txt', 'w')
def do_bet(self):
self.bet = self.betting[self.betlevel]
luckynumber = random.randint()
mynumber = random.randint()
if mynumber == luckynumber:
self.win()
def win(self):
self.bankroll -= self.bet
self.outputfile.write('I won:' + str(self.bet))
The idea is that the class methods have access to the class attributes, so you totally avoid global variables, and reduce the possibility of mistake.
Try to complete the implementation. Once you have it, you can post it again and we can see if there are improvements.
Trouble #1:
you didn't set town as global, so this will print correctly:
town=[testCase,bet,winningNumber,"WIN",bankroll]
print town
, but in writing() method town is empty, and that's why you get 100 empty lines
here is example:
#global town #uncomment if you want to change "town" in "one()"
town = ["not", "changed", "town"]
def one():
#global town #uncomment if you want to change "town" here
town = [1,"local", "town", True]
print "local -> ", town
def two():
# you don't need "global town" here because you do not change it, you only use it
print town
one()
two()
this is output:
local -> [1, 'local', 'town', True]
['not', 'changed', 'town']
Trouble #2:
similar as trouble #1, in startTheSimulation(): you need to write global bet , otherwise bet is local variable and never gets changed, that's why it's 0 in your win() method.
Those are solutions for your problems , but consider creating a class, like #davidmh said...global variables are almost always a bad idea

random.randint function isnt working the way i would like it to

Whenever I run this program (not a serious program just messing around getting an idea of things) the damage from the monster (monster[1]) just repeats the same number over and over again. It randomizes once then just repeats it. I understand WHATS happening but I don't understand WHY it is. Here is the code (I'm sorry I don't know if I'm making my question clear or not...makes sense in my head lol)
EDIT - I would like the monster[1] function to randomize each time but I don't know how to do it without writing more code (i.e damage=random.randint(5, 15) health-=damage). If I write it like that it works fine. But I dont want to write that specially if I have a series of 10 different monsters. I would like to just call upon each monster and have it run by itself if that makes sense.
EDIT#2: Is it possible to create a tuple within a list since tuples are immutable (i.e monster=[100, (random.randint(5, 15)), random.randint(15, 30)] this code doesn't work I've tried it already but just wondering if it would be possible.
import random
monster = [100, random.randint(5, 15), random.randint(15, 30)]
health = 200
a = 1
print "you run into a monster"
while a == 1:
if monster[0] <= 0:
print "monster is dead"
print "you get, " + str(monster[1]) + " exp"
a += 1
elif monster[0] >= 0:
att = random.randint(5, 15)
monster[0] -= att
health -= monster[1]
print ("you attack the monster and do, " + str(att) + " damage"
" the monster does," + str(monster[1]) + " damage to you")
print "you have, " + str(health) + " health left"
print "monster has, " + str(monster[0]) + " health left"
monster[1] get assigned a random integer on the second line of your code. It then is stored in the list monster as an integer. That integer is going to remain the same. You would have to rerun the random.randint(5, 15) call to get a new "damage" number or new exp amount.
Though I think it may be beyond the scope of what you are working on here, you may want to look into creating a class monster instead of using an array, and then having a method that generates these random integers each time it attacks.
Here is an example monster class that may give you the idea of how it works.
class monster():
def __init__(self,health):
self.health = health
def attack(self):
return random.randint(5,15)
You can then create a new monster as follows.
monster = monster(100)
See how much damage it does as follows.
monsterDamage = monster.attack()
health -= monsterDamage
print "The monster does " + str(monsterDamage) + " damage to you."
And lower the monster's health as follows.
att = random.randint(5,15)
monster.health -= att
This line:
monster=[100,random.randint(5, 15), random.randint(15, 30)]
saves 100 and two random numbers once. For example, this may be the representation of monster at runtime:
monster=[100, 11, 26]
And these numbers don't change, because the assignment happens only once. (eg. outside the loop)
monster=[100,random.randint(5, 15), random.randint(15, 30)]
When you define this list, it will be the same throughout. The values will not change every time you do monster[1].
To fix this, you could do something like:
monster=[100, random.randint, random.randint]
And when you go to call it:
monster[1](15, 15)
Just an option. Although a dictionary could be better here.
Well, you gave monster[1] a value only once, in the 2nd line:
monster=[100,random.randint(5, 15), random.randint(15, 30)]
That line is executed only once, so "of course" monster[1] is always the same. If you want monster[1] (and/or monster[2] too) to change, you need to give it a new value inside your loop. You did that for att! You need to do something similar for all the other things you want to see change :-)
When you call your line:
monster = [100, random.randint(5, 15), ...]
the function random.randint(5, 15) is executed and a specific value is stored in the list.
I'm going to present one more alternative to do what you want, through the storage of the function as a string; you can write:
monster = [100, "random.randint(5, 15)", ...]
then when you want to get a new random integer you call:
r=eval(monster[1])
and that gives you a different integer each time you call it, because the function is re-evaluated.
(notice that if you want to re-use a random value, for instance to print it, you must store it in a temporary variable, "r", and then use str(r), instead of str(eval(monster[1])), as the former way prints the result of the call stored in "r", and the later way re-evaluates again the function).
eg.
tmp = eval(monster[1])
health -= tmp
print ("you attack the monster and do, " + str(att) + " damage. the monster does," + str(tmp) + " damage to you")

Categories

Resources