For a school project a friend of mine and I are currently trying to program a simulation of our solar system. The platform we use is Glowscript and we're working with VPython. We have programmed our whole solar system already with all its planets, the sun and the forces between them.
Now we're trying to add some extras and one of them is a menu in which the user can select a planet. In our code the selected object (a planet or the sun which are defined in the code) will be labeled as the 'currentobject'. After that it will be possible for the user to change the currentobject's mass using a slider.
Two problems occurred during the process of programming. The first one is that we were not able to define an object as the currentobject so that its mass can be changed later on. Sadly, we couldn't find the problem in our code.
The second problem is that we weren't able to add more than one extra to our simulation in Glowscript. We have already programmed a slider feature to change the simulations 'rate' (velocity) and after that the menu and the slider for changing the mass simply didn't show up.
def M(m):
global col, currentobject
currentobject.visible = True
obj = m.selected
if obj == 'Sun':
currentobject = sun
elif obj == "Mercury":
currentobject = mercury
elif obj == "Venus":
currentobject = venus
elif obj == "Earth":
currentobject = earth
elif obj == "Mars":
currentobject = mars
elif obj == "Jupiter":
currentobject = jupiter
elif obj == "Saturn":
currentobject = saturn
elif obj == "Uranus":
currentobject = uranus
elif obj == "Neptune":
currentobject = neptune
currentobject=m.selected
print(m.selected,m.index)
menu(choices=['Choose an object', 'Sun', 'Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune'], bind=M)
scene.append_to_caption('\n\n')
def setmass(b):
wt.text = '{:1.2f}'.format(b.value)
sl = slider(min=0.1, max=10, value=0.1, length = 1000, bind=setmass)
wt = wtext(text='{:1.2f}'.format(sl.value))
#mainloop
while (True):
rate(10)
currentobject.mass=currentobject.mass*sl.value
In the end, the user of our simulation should be able to select a planet or the sun in a drop down menu. After that the user should be able to change the selected object's mass (using a slider) and see the effects in the simulation above (the other planets orbits change because they are more attracted to the currentobject).
Error message:
TypeError: Cannot read property 'mass' of undefined
You code fragment isn't sufficiently complete to know exactly what the problem is, but I note that the first call to M has currentobject.visible = True, but currentobject doesn't yet exist, so you get an error. Similarly, in your loop you reference currentobject.mass, but currentobject doesn't yet exist.
Related
import time
shop = {'Processor': {'p3':100, 'p5':120, 'p7':200},
'RAM': {'16gb':75, '32gb':150},
'Storage': {'1tb':50, '2tb':100},
'Screen': {'19"':65, '23"':120},
'Case': {'Mini Tower':40, 'Midi Tower':70},
'USB Ports': {'2':10, '4':20}}
basket = []
def main():
print('''
Welcome to the PC Component Store!
Here, we sell you everything you will need.
(Keep in mind that display prices do NOT include VAT; this is added in checkout)
''')
options()
def productchoice():
a = 0
ptype = ''
pspec = ''
print('''
We assume you have taken a look at our catalog. To add an item to your basket here, you must:
> INPUT the type of product you are looking for, e.g: "RAM"
> Then, INPUT the specification of that type of item you desire, e.g: "16gb"
> We will process your request, and OUTPUT whether it has been accepted.
> If this does not work, we will allow you to try again. If you wish to return to menu, enter "MENU"
at each input prompt.
''')
while a == 0:
ptype = input('Product: ')
pspec = input ('Specification: ')
if ptype.lower() == 'menu' and pspec.lower() == 'menu':
print('''Returning to menu...
''')
options()
elif a == 0:
totalcost = 0
try:
totalcost += shop[ptype][pspec]
except:
print('''Your request was invalid. Please try again, and if you are unsure, return to
menu and revisit our catalog.
''')
continue
else:
addtocart(ptype,pspec)
print(totalcost)
print(basket)
else:
print('''Your request was invalid. Please try again, and if you are unsure, return to
menu and revisit our catalog.
''')
continue
def addtocart(ptype,pspec):
itemstr = ptype + ' ' + pspec
basket.append(itemstr)
return basket
def options():
a = 0
while a == 0:
choice = input('''Do you want to:
"SEE CATALOG"
"CHOOSE PRODUCT TO ADD TO BASKET"
"VIEW BASKET"
"CLEAR BASKET"
"CHECKOUT"
Enter a valid option using a number from (1-5): ''')
if choice == '1':
a = 1
print('WORK IN PROGRESS')
elif choice == '2':
a = 1
productchoice()
elif choice == '3':
a = 1
print('Your basket contains: ')
print(basket)
elif choice == '4':
a = 1
basket = []
print('''Basket cleared.'''
)
options()
elif choice == '5':
a = 1
checkout()
else:
print('''You must select a valid option from (1-5), taking you back to the menu...
''')
continue
main()
It comes up with an error saying 'UnboundLocalError: local variable 'basket' referenced before assignment' when 'basket' is used in options 3 or 4. What does this mean? Why when 'basket' is used in option 2, it works perfectly? I'm a GCSE student going into A-level who isn't that great at coding, so I thought stackoverflow could help.. this is really frustrating and I need to do it for homework..
You are facing a very common issue for most of new python developers and it is variable-scope problem. So, every variable has a its own scope, which means it can be referenced at some point in code in a very specific way. You can read here more about it.
As far as your problem holds, you can use a global key word at the start of function. Add this line:
global basket
at line # 91 and your program will run perfectly. This lines tells python to use the global basket list that you have created on line # 10.
Remember:
It should be noted that, use of global all around the code is not so much appreciated in python community, as it can lead to very complex code, if your code is very large and your modifying the global variable all across the code. If this is the case then its time to re-structure your code.
I am just starting to code. Got a job as a junior developer thanks to other skills. And right now I am self studying to learn Python 3, Django and React. I am 3 weeks in, and i like it thus far.
While learning to code i found some exercises to do and gave my own swing at it. So I am trying to make kind of a lite rpg, where the player and comp chooses an attack and it gets executed in random order.
But i am having trouble making the attacks and everything else to be in callable functions. I could write out the whole code to the length of times, but i want to make it easier to code and expand on. This is what i have at the moment. I think the mistake is in the parameters in the functions? Which make some local instead of global values.
anyways, thank you in advance.
So i tried a lot of different parameters in different places. cant figure it out. also tried to call the move functions inside the player_move function.
import random
def tackle():
dmg = random.randint(150, 280)
return dmg
def bite():
dmg = random.randint(110, 350)
return dmg
def heal():
dmg = random.randint(130, 260)
return dmg
player_health = 1000
comp_health = 1000
alive = True
def player_move():
move = input("Use one of the following moves: \n"
"1. Tackle\n"
"2. Bite\n"
"3. Heal\n"
"Choose the Move: ")
if move == 1 or move == "Tackle" or move == "tackle":
comp_health -= tackle()
elif move == 2 or move == "Bite" or move == "bite":
comp_health -= bite()
elif move == 3 or move == "Heal" or move == "heal":
comp_health -= heal()
return comp_health
player_move()
print(comp_health)
So i figured a few things out. Most of it was in the scope of the functions. Had to call the functions before using them. I ended up rewriting most of it, but got it to work. (edit) The question still stands though. How can I call a function out of scope??
I'm having difficulty with one small part of my code. I'm modifying a player's HP while they're in combat, but when exiting combat the HP resets to 100. This is odd because the enemy's HP is preserved. By using print(id(player.hp)) I can see that a new instance of player.hp is being created, I just don't know why. I've tried googling the issue but I can't find an example that fits my problem. I'll try to only include the pertinent parts of the code below (there's a lot of superfluous writing that isn't necessary here), but if I need to include everything I will.
class Alleyway(Scene):
room_items = []
room_characters = []
room_enemies = ["hobo"]
def __init__(self):
self.fresh_arrival = True
self.north = False
self.east = True
self.south = True
self.west = False
self.enemy = Hobo()
def fight(self, player, weapon): #Lots of what makes this fun is edited out
while True:
if self.enemy.hp > 0:
print("Do you attack or flee?")
words = input("> ").lower()
if words == "flee":
map_ = Map("alleyway")
game = Engine(map_)
game.play()
if words == "attack":
miss = randint(1,4)
if miss == 1:
print("Too bad, you miss!")
else:
print("You got him!")
self.enemy.hp -= weapon.damage
print("Hobo's HP: {}".format(max(self.enemy.hp, 0)))
if self.enemy.hp > 0:
print("The hobo takes a swing at you.")
hobomiss = randint(1,5)
if hobomiss == 1:
print("He missed!")
else:
print("Ouch, he got you!")
player.hp -= self.enemy.damage
print("Your HP: {}".format(max(player.hp, 0)))
else:
print("No idea what you mean. Attack the man or flee.")
else:
print("You defeat the hobo!")
print()
print("Dirty shoes and shank added to inventory.")
print()
shoes = DirtyShoes()
shank = Shank()
player.inventory.append(shoes)
player.inventory.append(shank)
self.room_enemies.remove("hobo")
map_ = Map("alleyway")
game = Engine(map_)
game.play()
When fight() is called, an instance of Player() is sent in as an argument, which has an instance variable of self.hp = 100.
This is still a work in progress so please gloss over the fact that it doesn't exit when the player dies and other silly things like that (:
Now, when the player flees in the middle of the fight, my goal is for the enemy's HP to be preserved, the player's HP to be preserved, and the items to be added to the player's inventory. So far, the enemy's HP is accurately preserved and everything else in my code regarding the enemy's HP and his alive/dead status work great when combat is exited. My issue is with player.hp -= enemy.damage, player.inventory.append(shoes), and player.inventory.append(shank). None of them work. The player.hp displays correctly during the fight and decreases as expected, however once the player exits combat the HP is reset to 100 and there is nothing added to the inventory. I've tried player.hp = player.hp - enemy.damage for the HP issue and it still creates a new variable. I'm just not sure what's going on since the enemy portions are working fine.
If more information is needed please let me know. And if there are any obvious ways my code can be improved I'm totally open to suggestions.
Got it! I was defining player = Player() inside of a method, so it only created the instance for that method (I think). So I defined it outside of the method and now the modified values stick!
I'm trying to write a MasterMind game using classes and objects and I'm currently stuck around some of my loops.
while True:
# create a combination
# test the combination
while game_won == False:
print(scoreboard)
# player input combination
# combination is tested then added to scoreboard
tries_left = tries_left+1
if game_won == True:
print(You Won!)
input = Play Again? Y/N
if tries_left == 10:
print(You Lost!)
input = Play Again? Y/N
How do I do to go back to my while True -> create combination from my last if statement? (if tries_left == 10:)
What's wrong
Your first while True doesn't have anything in it, You need to indent code under it if you want it to be inside the loop.
There is a few typos, missing comment characters, and quotation marks.
What needs to happen
When the nested while loop while game_won == True exits, the code will return looping the parent loop while True, which will replay the game, if the user wishes.
Your code fixed (with a few improvements)
Following is how you can loop the game forever (given the user wishes it).
# Assume user wants to play when the program runs
user_wants_to_play = True
ans = ""
# loop the entire game while the user wishes to play
while user_wants_to_play:
# Create the combination
# Test the combination
# Game isn't done when started
game_done = False
tries_left = 10 # Arbitrary number I chose
while not game_done:
# Play the game
print("Scoreboard")
# Subtract one to tries left
tries_left -= 1
if game_done:
print("You won!")
elif tries_left == 0:
print("You lost!")
game_done = True
# if users answer was 'n'
ans = input("Play again? Y/N \n")
if ans.strip().upper() == 'N':
user_wants_to_play = False
Improvements
Boolean logic is more pythonic using not instead of myBool == False
while True: changed to while user_wants_to_play:
User input is scrubbed to ignore white-space and lower case
Changed game_won to game_done
Made tries_left count down instead
I am trying to make a simon says game and am having trouble collecting the users choice to compare against the computer's pattern. I am using four buttons to select the colors that flash on the screen. The problem I am having is my program continues to chug along even if my user hasn't selected a color yet, despite my best efforts to stop it, what can I do to stop the program? Here is my code...
Sequence[]
PosColors = ["Yellow","Red","Blue","Green"]
PlayerChoice[]
Score = 0
def Game(Sequence, PlayerChoice,Score):
Score += 1
PlayerChoice = []
Number = randint(0,3)
Sequence.append(PosColors[Number])
for i in Sequence:
RunTime = Score * 1000
Gui.after(1000, blink, rect, SquareCanvas , i)
RunTime = (Score + 1) * 1000
Gui.after(2000, blink, rect, SquareCanvas , White)
X = len(Sequence)
Index = 0
Color = " "
while Color != " ":
BlueButton.config(command = partial(setSelection,NeonBlue))
RedButton.config(command = partial(setSelection,NeonRed))
YellowButton.config(command = partial(setSelection,NeonYellow))
GreenButton.config(command = partial(setSelection,NeonGreen))
Color = getSelection()
print(Color)
while Color != " ":
PlayerTurn(Sequence,PlayerChoice,Score,Index)
X -= 1
Index +=1
def setSelection(Color):
if Color == NeonBlue:
return "NeonBlue"
elif Color == NeonRed:
return "NeonRed"
elif Color == NeonGreen:
return "NeonGreen"
elif Color == NeonYellow:
return "NeonYellow"
def getSelection():
return TheColor
def PlayerTurn(Sequence, PlayerChoice,Score,Index):
PlayerChoice.append(Color)
print(PlayerChoice)
Label1.config(text = 'Well done! \nYou advance to the next round!')
I am planning on passing this through a checker and to loop it until there is an error but I need to get past this front loop first... I know my logic works as I created it using just lists and the command line before moving on the the graphical portion I just need to know how to get the program to stop to collect the user guess, especially as the length of the pattern gets larger. Originally I had the command function included later where I build my Buttons but this placement seems to get as close as possible to what I am looking for. Any help is appreciated thank you
You're going to need to rethink your main program logic. Tkinter is designed such that you should never have your own infinite loop. Tkinter already has an infinite loop -- the mainloop() method of the root window. You can't write logic that waits for input from the user. You have to think of the GUI as in a perpetual state of waiting, and you need set up handlers (button callbacks or event bindings) to react to events.
You also need to understand that a button command can't "return" anything. "Can't" is a bit strong since it obviously can, but there's nothing waiting for the result -- no place to return it to. You need to design your button function such that it sets a global or instance variable.