I'm using Zelle Graphics library and I'm having trouble replacing graphics objects (which, in this case, happens to be text objects).
Here's the code:
from Graphics import *
winName = "Window"
win = Window(winName,600,500)
win.setBackground(Color('silver'))
title = Text((300,20),"Zack's Flash Card Maker")
title.draw(win)
p1 = Rectangle((50, 100),(550,400))
p1.setFill(Color("black"))
p1.draw(win)
class FlashCard:
def __init__(self):
self.commands = {'addQuestion':self.addQuestion,'startGame':self.startGame}
self.stack = []
self.questions = {}
self.questionAnswered = False
self.questionsCorrect = 0
self.questionsIncorrect = 0
def addQuestion(self):
question = ' '.join(self.stack)
self.stack = []
answer = input(question)
self.questions[question] = answer
def startGame(self):
for question in self.questions:
if(self.questionAnswered == False):
answer=input(question)
questionText = Text((300,150),question)
questionText.setFill(Color("white"))
questionText.draw(win)
if(answer == self.questions[question]):
questionAnswer = Text((300,200),answer + " is correct!")
questionAnswer.setFill(Color("green"))
questionAnswer.draw(win)
self.questionsCorrect = self.questionsCorrect + 1
continue
else:
questionAnswer = Text((300,200),answer + " is incorrect. Study this one.")
questionAnswer.setFill(Color("red"))
questionAnswer.draw(win)
self.questionsIncorrect = self.questionsIncorrect + 1
continue
def interpret(self,expression):
for token in expression.split():
if token in self.commands:
operator = self.commands[token]
operator()
else:
self.stack.append(token)
i = FlashCard()
i.interpret('What is your dog\'s name? addQuestion')
i.interpret('What is your favorite thing to do? addQuestion')
i.interpret('startGame')
This is essentially a mini flash card program I'm making. It takes the interpret commands at the bottom and executes them based on the dictionary in the FlashCard class. It basically works: it does the correct text objects. However, text begins to overlap other text objects because it re-draws. I've tried moving the .draw function all over, but it either doesn't appear at all or it overlaps.
Anyone have any suggestions? I want the text to replace for each new flashcard question.
Thanks!
there's an undraw() command that you need to use if you want to make something invisible. I'd recommend placing it right before your continue statements. It's used like
questionText.undraw()
questionAnswer.undraw()
Alternatively, you can use the del command to get rid of each questionText/questionAnswer instance when you're done with it. That's probably a better option since you're actually freeing up the memory that way instead of storing data and not doing anything with it.
You can use setText method to change the text.
example:
string = Text(Point(1, 1), 'original string')
sting.setText('new string')
Related
I have a program that I want to be able to print all of the instances of each variable using my method that I created. Problem is I can't figure out a way to print them since each are listed under a different variable that aren't configured from hardcoding them in and I need a way to automatically recall them in my code.
class fit:
def __init__(self,day,did,workout='Not Recorded',time='An unknown amount of',calories='An unknown amount of'):
self.day = day
self.did = did
if did.lower()=='no':
self.workout = 'Not Recorded'
self.time = "An unknown amount of Minutes"
self.calories = "An unknown amount of Calories"
else:
self.workout = workout
self.time = "{} Minutes".format(time)
self.calories = "{} Calories".format(calories)
def formate(self):
self.formate = "{}:\n\nDid you work out: {}\nWorkout focus: {}\nYou worked out for: {}\nYou burned: {}\n\n----------------------------------------------------------".format(self.day,self.did,self.workout,self.time,self.calories)
return self.formate
def reader(day,index):
file = open('readme.txt')
file = file.read()
stripped = file.rsplit("\n")
for i in range(len(stripped)):
stripped[i] = stripped[i].rsplit(" ")
del stripped[-1]
if int(index) >= len(stripped[day-1]):
return "none"
else:
return stripped[day-1][index]
x = 0
def create_new_instance(class_name,instance_name):
globals()[instance_name] = class_name(reader(x,0),reader(x,1),reader(x,2),reader(x,3),reader(x,4))
print('Class instance {} created'.format(instance_name))
while True:
try:
x+=1
ins = 'day_' + str(x)
create_new_instance(fit,ins)
except:
break
break
def printer(instance):
print(.formate())
while True:
x+=1
inst = 'day_' + str(x)
printer(inst)
An example of this might be that I have 8 lines of data from a text document and I have a system that creates instances of day_1, day_2, day_3 ect until day_8 and then I want to print each of those instances out, but again I don't have those instances directly hardcoded into my code so I don't know how I'd do it. I've tried looking into maybe a while loop and increasing a variable by 1 and concatenating it with day and trying to make a variable out of that but the my limited experience with python isn't helping.
A very unpythonic and ugly way would be to use exec, for example:
day_3=5
x = 'day_'+'3'
exec("print("+x+")")
I would recommend another way to store your variables though.
I am getting this error each time I try to run this app in its present state.
TypeError: cannot concatenate 'str' and 'GameData' objects
I am trying to get a data object from my Game(GameData) class onto the browser with my html. It's a subclass of GameData() which is a template class.
class GameData(object): #This class is the template for the data for each game.
def __init__(self):
self.title = ''
self.genre = ''
self.description = ''
self.developer = ''
self.rating = ''
self.image = ''
class Game(GameData): #Thas class holds all the data for each game.
def __init__(self):
#object for Castlevania
self.castlevania = GameData()
self.castlevania.title = 'Castlevania'
self.castlevania.genre = 'Action Platformer'
self.castlevania.description = 'Released in 1986 in Japan, Castlevania for the NES and Famicom Disc System spawned a series rich in action as well as exploration. This first game was merely a simple platformer but it inspired many changes to the formula over the years and invented the "Metroidvania" genre.'
self.castlevania.developer = 'Konami'
self.castlevania.rating = '7.5/10'
self.castlevania.image = 'images/t_castlevania.png'
There are other objects but if I can get one of them to work I can figure out the rest. I need it to get into this elif statement highlighted with a comment.
class MainHandler(webapp2.RequestHandler):
def get(self):
i = Intro()
d = GameData()
g = Game()
if self.request.GET:
page = self.request.GET['page']
if page == 'main_page':
self.response.write(i.head + i.main_page + i.main_title + i.main_links)
elif page == 'castlevania': #The data needs to go in this concatenation.
self.response.write(i.head + i.main_page + i.castlevania + (the data object should go here) + i.main_links)
From there I know what to do. I just need to know how to convert the data into a string so I can concatenate it. If anyone can help I would appreciate it. Also I tried using an array for the objects but that didn't work for me either.
You just need to include the __str__ function in your Game(GameData) class.
eg.
def __str__(self):
# Here you would put whatever logic in terms of returning a string
# representation of your game object. Eg:
return self.castlevania.title
Then, you would simply call str(g) where g is your Game(GameData) object
Here is my code (sorry for the messy code):
def main():
pass
if __name__ == '__main__':
main()
from easygui import *
import time
import os
import random
import sys
##multenterbox(msg='Fill in values for the fields.', title=' ', fields=(), values=())
msg = "Enter your personal information"
title = "Credit Card Application"
fieldNames = ["First name",'Last name','email',"Street Address","City","State","ZipCode",'phone','phone 2)']
fieldValues = [] # we start with blanks for the values
fieldValues = multenterbox(msg,title, fieldNames)
# make sure that none of the fields was left blank
def make(x):
xys = x,".acc"
xyzasd = str(xys)
tf = open(xyzasd,'a+')
tf.writelines(lifes)
tf.writelines("\n")
tf.writelines("credits = 0")
tf.close
def add(x):
nl = "\n"
acc = ".acc"
xy = x + acc
exyz = xy
xyz = exyz
xxx = str(xyz)
tf = open('accounts.dat',"a+")
tf.writelines(nl)
tf.writelines(xxx)
tf.close
while 1:
if fieldValues == None: break
errmsg = ""
for i in range(len(fieldNames)-1):
if fieldValues[i].strip() == "":
errmsg += ('"%s" is a required field.\n\n' % fieldNames[i])
if errmsg == "":
break # no problems found
fieldValues = multenterbox(errmsg, title, fieldNames, fieldValues)
names = enterbox(msg= ('confirm FIRST name and the FIRST LETTER of the persons LAST name'))
##txt = "acc"
##na = str(name)
##name = (names)
life = ( str(fieldValues))
lifes = life,'\n'
herro = ("Reply was: %s" % str(fieldValues))
correct = buttonbox(msg=(herro,'\n is that correct'),choices = ('yes','no','cancel'))
if correct == "yes":
make(names)
add(names)
elif correct == "no":
os.system('openacc.py')
time.sleep(0.5)
sys.exit()
else:
os.system('cellocakes-main.py')
sys.exit()
os.system('cellocakes-main.py')
I don't know what the problem is also I am sorry about how sloppy it was programmed I have a white board to help me out still new to programming (I'm only 13) sorry. Personally I think the issue is in the def add area's syntax but because I am still new I don't see the issue personally I am hoping to have a more experienced programmer help me out.
This is an answer not directly answering your question.
Alas, comment fields are STILL not capable to hold formatted code, so I choose this way.
def main():
pass
if __name__ == '__main__':
main()
This is a nice coding pattern, but used by you in a useless way.
It is supposed to prevent executing of the stuff if it is imported as a module and not executed as a script.
Nevertheless, it is not bad to use it always, but then put your code inside the main() function instead of adding it below.
fieldNames = ["First name",'Last name','email',"Street Address","City","State","ZipCode",'phone','phone 2)']
There is a ) too much.
fieldValues = [] # we start with blanks for the values
fieldValues = multenterbox(msg,title, fieldNames)
The second line makes the first one useless, as you don't use fieldValues in-between.
It would be different if you expected multenterbox() to fail and would want [] as a default value.
def make(x):
xys = x,".acc"
xyzasd = str(xys)
tf = open(xyzasd,'a+')
tf.writelines(lifes)
tf.writelines("\n")
tf.writelines("credits = 0")
tf.close
You was already told about this: x, ".acc" creates a tuple, not a string. To create a string, use x + ".acc".
Besides, your close call is no call, because it is missing the (). This one just references the function and ignores the value.
A better way to write this would be (please name your variables appropriately)
with open(xyzs, 'a+') as tf:
tf.writelines(lifes)
tf.writelines("\n")
tf.writelines("credits = 0")
The with statement automatically closes the file, even if an error occurs.
Besides, you use writelines() wrong: it is supposed to take a sequence of strings and write each element to the file. As it doesn't add newlines in-between, the result looks the same,. but in your case, it writes each byte separately, making it a little bit more inefficient.
Additionally, you access the global variable lifes from within the function. You should only do such things if it is absolutely necessary.
def add(x):
Here the same remarks hold as above, plus
xy = x + acc
exyz = xy
xyz = exyz
xxx = str(xyz)
why that? Just use xy; the two assignments do nothing useful and the str() call is useless as well, as you already have a string.
for i in range(len(fieldNames)-1):
if fieldValues[i].strip() == "":
errmsg += ('"%s" is a required field.\n\n' % fieldNames[i])
Better:
for name, value in zip(fieldNames, fieldValues):
if not value.strip(): # means: empty
errmsg += '"%s" is a required field.\n\n' % name
Then:
life = ( str(fieldValues))
makes a string from a list.
lifes = life,'\n'
makes a tuple from these 2 strings.
os.system('openacc.py')
os.system('cellocakes-main.py')
Please don't use os.system(); it is deprecated. Better use the subprocess module.
The problem of the question is here:
# assign the tuple (x, ".acc") to xys
xys = x,".acc"
# now xyzasd is the tuple converted to a string, thus
# making the name of your file into '("content of x", ".acc")'
xyzasd = str(xys)
# and open file named thus
tf = open(xyzasd,'a+')
What you wanted to do is:
# use proper variable and function names!
def make_account(account):
filename = account + '.acc'
the_file = open(filename, 'a+')
....
On the other hand there are other problems with your code, for example the
def main():
pass
if __name__ == '__main__':
main()
is utterly useless.
I'm trying to keep this as simple as possible. Basically I want the data to be saved to a file, and the retrieve it so that questor.py works and can "remember" everything it was ever taught on your machine. The original code is available on the web at http://www.strout.net/info/coding/python/questor.py
If I'm reading the code right, you end up with an object that looks something like {key:{key:{key:class instance},class instance},class instance} . (rough estimate)
Please ignore the unfished method Save, I'm working on that as soon as I figure out how to pickle the dictionary without losing any of the imbedded instances.
The following is my attempt at trying to save the dict via pickler. Some of the code is unfinished, but you should be able to get an idea of what I was trying to do. So far all I am able to do is retrieve the last question/answer set. Either my pickle isn't saving the imbedded instances, or they're not actually there when I save the pickle. I've followed the spaghetti lines as much as possible, but can't seem to figure out how to set up a way to save to file without losing anything.
Also my file doesn't have to be .txt originally I was going to use .data for the pickle.
# questor.py
# define some constants for future use
kQuestion = 'question'
kGuess = 'guess'
questfile = 'questfile.txt'
## Added
import cPickle as p
# create a file for questor
def questor_file():
try:
questor = open(questfile,'rb')
try:
q = p.Unpickler(questor)
quest = q.load()
questor.close()
return quest
except:
print 'P.load failed'
except:
print 'File did not open'
questor = open('questfile.data', 'wb')
questor.close()
return Qnode('python')
# define a function for asking yes/no questions
def yesno(prompt):
ans = raw_input(prompt)
return (ans[0]=='y' or ans[0]=='Y')
# define a node in the question tree (either question or guess)
class Qnode:
# initialization method
def __init__(self,guess):
self.nodetype = kGuess
self.desc = guess
##Added
## Not sure where I found this, but was going to attempt to use this as a retreival method
## haven't gotten this to work yet
def Load(self):
f = open(self.questfile,'rb')
tmp_dict = cPickle.load(f)
f.close()
self.__dict__.update(tmp_dict)
##Added
# was going to use this as a save method, and call it each time I added a new question/answer
def Save(self,node):
f = open(self.questfile,'wb')
quest = p.pickler(f)
# get the question to ask
def query(self):
if (self.nodetype == kQuestion):
return self.desc + " "
elif (self.nodetype == kGuess):
return "Is it a " + self.desc + "? "
else:
return "Error: invalid node type!"
# return new node, given a boolean response
def nextnode(self,answer):
return self.nodes[answer]
# turn a guess node into a question node and add new item
# give a question, the new item, and the answer for that item
def makeQuest( self, question, newitem, newanswer ):
# create new nodes for the new answer and old answer
newAnsNode = (Qnode(newitem))
oldAnsNode = (Qnode(self.desc))
# turn this node into a question node
self.nodetype = kQuestion
self.desc = question
# assign the yes and no nodes appropriately
self.nodes = {newanswer:newAnsNode, not newanswer:oldAnsNode}
self.save(self.nodes)
def traverse(fromNode):
# ask the question
yes = yesno( fromNode.query() )
# if this is a guess node, then did we get it right?
if (fromNode.nodetype == kGuess):
if (yes):
print "I'm a genius!!!"
return
# if we didn't get it right, return the node
return fromNode
# if it's a question node, then ask another question
return traverse( fromNode.nextnode(yes) )
def run():
# start with a single guess node
# This was supposed to assign the data from the file
topNode = questor_file()
done = 0
while not done:
# ask questions till we get to the end
result = traverse( topNode )
# if result is a node, we need to add a question
if (result):
item = raw_input("OK, what were you thinking of? ")
print "Enter a question that distinguishes a",
print item, "from a", result.desc + ":"
q = raw_input()
ans = yesno("What is the answer for " + item + "? ")
result.makeQuest( q, item, ans )
print "Got it."
# repeat until done
print
done = not yesno("Do another? ")
# Added
# give me the dictionary
return result
# immediate-mode commands, for drag-and-drop or execfile() execution
if __name__ == '__main__':
print "Let's play a game."
print 'Think of something, just one thing.'
print 'It can be anything, and I will try to guess what it is.'
raw_input('Press Enter when ready.')
print
questdata = run()
print
# Added
# Save the dictionary
questor = open(questfile,'wb')
q = p.Pickler(questor)
q.dump(questdata)
questor.close()
raw_input("press Return>")
else:
print "Module questor imported."
print "To run, type: questor.run()"
print "To reload after changes to the source, type: reload(questor)"
# end of questor.py
one way that comes to mind is creating a list of all the nodes and saving that ... they should keep their internal pointers on their own.
declare a list of nodes at the top of your file (and use pickle... just cause Im more familiar with that)
import pickle
kQuestion = 'question'
kGuess = 'guess'
questfile = 'questfile.txt'
nodes = []
....
change your load method to something like
def questor_file():
global nodes
try:
questor = open(questfile,'rb')
try:
nodes= pickle.load(questor)
quest = nodes[0]
questor.close()
return quest
except:
print 'P.load failed'
nodes = []
except:
print 'File did not open'
nodes = []
return Qnode('python')
change your class constructor so that it adds each node to nodes
class Qnode:
# initialization method
def __init__(self,guess):
self.nodetype = kGuess
self.desc = guess
nodes.append(self)
at the end where it says #added save dictionary , save your list of nodes
questor = open(questfile,'wb')
q = pickle.dump(nodes,questor)
make sure you exit the program by typing no when prompted ...
you could also save it to a database or whatever but you would still have to store each node and it might be more complicated... this method should really be fine I think , (although there may be a more natural way to save a tree structure) ...
Ok. I'm designing a small text-based RPG, however, I need to have the player be able to save the game. I've succeeded in doing this through using the pickle module, but I'm trying to get the player to be able to get back to their previous point in the storyline through using this variable I call 'storypointe'. Basically it would work like this:
if storypointe == 0:
#Story, story, stuff happens here...
storypointe += 1
if storypointe == 1:
#More story, more story, more stuff happens here....
I would then pickle the variable storypointe, and when the game is loaded (meaning using pickle.load to get player stats and storypointe from whatever file I pickled it into), and IDEALLY it would just start from whichever code block storypointe corresponds to. The actual code is way too much work for the writer and (perhaps) the readers, so I've written the following code that simulates the same environment and replicates the same problem.
storypointe = 0
jump = 0
spin = 0
dive = 0
roar = 0
savefile = "C:\Users\Sammu\The Folder\databin.txt"
import pickle, sys
def save ():
with open(savefile, 'w') as savebin:
actions = [jump, spin, dive, roar, storypointe]
pickle.dump (actions, savebin)
def load ():
with open(savefile, 'r') as loadbin:
actions2 = pickle.load (loadbin)
print actions2
jump = actions2[0]
spin = actions2[1]
dive = actions2[2]
roar = actions2[3]
storypointe = actions2[4]
#Begin the code#
gameIO = raw_input ('Would you like to load previous game?\n>>> ')
if gameIO in ['yes', 'load', 'load game', 'Yes', 'Load', 'Load game']:
load ()
if storypointe == 0:
action = raw_input ('Would you like to jump, spin, dive or roar?\n>>> ')
if action in ['jump', 'Jump']:
jump += 1
print jump
if action in ['spin', 'Spin']:
spin += 1
print spin
if action in ['dive', 'Dive']:
dive += 1
print dive
if action in ['roar', 'Roar']:
roar += 1
print roar
storypointe += 1
if storypointe == 1:
print "\n\nYou have progressed to the next stage"
save ()
So if storypointe is equal to actions2[4], then that must mean it should be equal to 1. But the problem here is that it's always following the first code block, starting from
action = raw_input ('#yadayadayada')
instead of:
print "You have progressed to the next stage"
I think you're confused about Python scoping.
Here you make a new variable at module level:
storypointe = 0
[...]
But here:
def load ():
with open(savefile, 'r') as loadbin:
actions2 = pickle.load (loadbin)
[...]
storypointe = actions2[4]
you simply make a new local name "storypointe" in the function load. It doesn't affect what storypointe is at the module level. I would store your variables in a class or a dict instead, which would also prevent having to do the actions2[i] stuff.
Rather than express your narrative as a bunch of if statements consider it as a state machine, if you express your story-line as a tree then you can easily store routes through the game as references to the next node in the tree, you can also store references (unique) to each node, allowing for easy saving and loading of positions.
See for example
class Node(object):
def __init__(self, parent, children=None):
self.parent = parent
self.children = children or {}
story = {}
story['a'] = Node(None)
story['b'] = Node(a)
story['a'].children['b'] = story['b']