I've currently been creating a math equation generator program that will ask you random multiplication questions. I have been having trouble with the if statements where ans == answer will be equal dependent on the user's input (correct answer). However, my program does not see it as equal despite being the same value with example from printing ans and answer which shows they are the same value. I don't know if I am doing something wrong and I would like to know a method of fixing my issue.
Also when I tried to create for and while loops for the generating the equations, it would print them all out at once, is there a way to also make it so that the loop will not print a new random equation until the user gets the answer right?
from tkinter import *
from random import *
import random
import time
import tkinter as tk
import math
import operator
from tkinter import messagebox
#This is for creating the tkinter window and fixing the specified dimensions into place
root = tk.Tk()
root.geometry("900x600")
#This section creates the canvas and its specifications
canvas_width = 900
canvas_height = 500
c = Canvas(root, width=canvas_width, height=canvas_height, bg="pink")
c.pack()
def quitgame():
root.destroy()
class Game_Images:
#Background Image
bg = PhotoImage(file="../Data/sidescroll background flip.gif")
bg = bg.zoom(2)
c.create_image(0,0, anchor=NW, image=bg)
#Insert Image of Enemy
enemy = PhotoImage(file="../Data/monke2.png")
enemy1 = c.create_image(0,260, anchor=NW, image=enemy)
#Insert image of playable character
player = PhotoImage(file="../Data/monke2.png")
player1 = c.create_image(0,325, anchor=NW, image=player)
g = Game_Images()
score = 0
x = 1
def game_start():
global answer, question
int_1 = random.randint(1, 12)
int_2 = random.randint(1, 12)
displayQuestion = "What is "+str(int_1)+ "*" + str(int_2)+"?"
operator = ["*"]
ops = random.choice(operator)
c.create_rectangle(353,0,550,75, fill = "white")
c.create_text(450, 50, font = ("Helvetica", 15), fill="pink", text = displayQuestion)
question = str(int_1) + str(ops) + str(int_2)
answer = int_1 * int_2
def generateQ():
ans = e1.get()
e1.delete(0, END)
if ans == answer:
score += 1
x += 1
print("correct")
print(ans)
print(answer)
else:
print("wrong")
print(ans)
print(answer)
#Buttons show up below the canvas to run commands when pressed
Button(root, text = "Commence Forth",width = 15, command = game_start).place(x=10, y=570)
Button(root, text = "Quit",width = 11, command = quitgame).place(x=800, y=570)
e1 = Entry(root)
e1.pack(padx=30, pady=30)
b=Button(root,text="Enter", width=5, font=("Helvetica", 12), command = generateQ)
b.place(x=550, y=534)
root.mainloop()
Change function generateQ() like this -
def generateQ():
global score,x
ans = e1.get()
e1.delete(0, END)
if int(ans) == int(answer):
score += 1
x += 1
print("correct")
print(ans)
print(answer)
else:
print("wrong")
print(ans)
print(answer)
Use int() so that they are of same data type. And use global score,x because it shows error. You could also write score and x as arguments.
Related
I am currently working on a hangman game using tkinter in python.
When I click a button of the letter and it is in the word that we are guessing it should show the letter. But when I click the button this problem is popping up:
This example is only with one button. People say that this problem is because of the mainloop(), but i have no idea how to fix it.
from tkinter import *
from tkinter import messagebox
from generate_word import word
#DEFAULT VALUES
score = 0
count = 0
win_count = 2
WINDOW_BG = '#e5404e'
WINDOW_SIZE = '1200x870+300+80'
FONT = ('Arial', 40)
from tkinter import *
from tkinter import messagebox
from generate_word import word
#DEFAULT VALUES
score = 0
count = 0
win_count = 2
WINDOW_BG = '#e5404e'
WINDOW_SIZE = '1200x870+300+80'
FONT = ('Arial', 40)
#this is an example with only one button
buttons = [['b1','a',80,740]]
#Creating window and configurating it
window = Tk()
window.geometry(WINDOW_SIZE)
window.title('Hangman')
window.config(bg = WINDOW_BG)
#generates all of the labels for the word
def gen_labels_word():
label = Label(window, text = " ", bg = WINDOW_BG, font = FONT)
label.pack( padx = 40,pady = (500,100),side = LEFT)
label1 = Label(window, text = word[0], bg = WINDOW_BG, font = FONT)
label1.pack( padx = 41,pady = (500,100),side = LEFT)
x = 21
for var in range(1,len(word)):
exec('label{}=Label(window,text="_",bg=WINDOW_BG,font=FONT)'.format(var))
exec('label{}.pack(padx = {}, pady = (500,100), side=LEFT)'.format(var,x))
x += 1
exec('label{} = Label(window, text = "{}", bg = WINDOW_BG, font = FONT)'.format(len(word),word[-1]))
exec('label{}.pack( padx = {},pady = (500,100),side = LEFT)'.format(len(word), x+1))
# ---------------------------------------------------------------------------------------------------------------------------------------------------
gen_labels_word()
#----------------------------------------------------------------------------------------------------------------------------------------------------
#letters icons(images)
#hangman (images)
hangman = ['h0','h1','h2','h3','h4','h5','h6']
for var in hangman:
exec(f'{var}=PhotoImage(file="{var}.png")')
han = [['label0','h0'],['label1','h1'],['label2','h2'],['label3','h3'],['label4','h4'],['label5','h5'],['label6','h6']]
for p1 in han:
exec('{}=Label(window, bg = WINDOW_BG ,image={})'.format(p1[0],p1[1]))
exec('label0.place(x = 620,y = 0)')
for var in letters:
exec(f'{var}=PhotoImage(file="{var}.png")')
for var in buttons:
exec(f'{var[0]}=Button(window,bd=0,command=lambda: game_brain("{var[0]}","{var[1]}"),bg = WINDOW_BG,font=FONT,image={var[1]})')
exec('{}.place(x={},y={})'.format(var[0],var[2],var[3]))
def game_brain(button, letter):
global count,win_count,score
exec('{}.destroy()'.format(button))
if letter in word:
for i in range(1,len(word)):
if word[i] == letter:
win_count += 1
exec(f'label{i}.config(text="{letter}")')
if win_count == len(word):
score += 1
messagebox.showinfo('GOOD JOB, YOU WON!\n GOODBYE!')
window.destroy()
else:
count += 1
exec('label{}.destroy()'.format(count-1))
exec('label{}.place(x={},y={})'.format(count,620,0))
if count == 6:
messagebox.showinfo('GAME OVER','YOU LOST!\nGOODBYE!')
window.destroy()
def EXIT():
answer = messagebox.askyesno('ALERT','Do you want to exit the game?')
if answer == True:
window.destroy()
e1 = PhotoImage(file = 'exit.png')
ex = Button(window,bd = 0,command = EXIT,bg = WINDOW_BG,font = FONT,image = e1)
ex.place(x=1050,y=20)
#-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
window.mainloop()
Why exec function in python adds '.!' at the beginning of the text?
The exec function isn't doing that. Tkinter by default names all of its widgets with a leading exclamation point. When you print out a widget, it has to be converted to a string. For tkinter widgets, the result of str(some_widget) is the widget's name.
You can see this quite easily without exec:
import tkinter as tk
root = tk.Tk()
label = tk.Label(root)
print(label)
The above will print something like .!label. If you create a second label it will be .!label2, a third will be .!label3 and so on.
On an unrelated note, you shouldn't be using exec to create widgets. It makes the code very hard to understand and debug. If you want to create widgets in a loop, add them to a dictionary or list instead of dynamically creating variables with exec.
For example:
labels = {}
for var in range(1,len(word)):
label = Label(window,text="_",bg=WINDOW_BG,font=FONT)
label.pack(padx=500, pady=100)
labels[var] = label
With that, you can later reference the widgets as labels[1], labels[2], etc.
You should do the same thing with the images, or anything else that you create in a loop and want to keep track of.
im a newbie trying to make a random math question generator and the numbers i give the system will output to the question area but when i give the right answer (e.x. 3 times 3 is 9) the system wont see the answer as right.
iv tried about 15 different iterations of the code you see here and this is what closest to working
import random
from tkinter import *
na = random.randint(1, 3)
nb = random.randint(1, 3)
txtstring = ("what is", na,"*", nb,"?")
root = Tk()
root.geometry("300x320")
root.title(" Q&A ")
def Take_input():
INPUT = inputtxt.get("1.0", "end-1c")
print(INPUT)
if(INPUT == na * nb):
Output.insert(END, 'Correct')
else:
Output.insert(END, "Wrong answer")
l = Label(text = txtstring)
inputtxt = Text(root, height = 10,
width = 25,
bg = "light yellow")
Output = Text(root, height = 5,
width = 25,
bg = "light cyan")
Display = Button(root, height = 2,
width = 20,
text ="Show",
command = lambda:Take_input())
l.pack()
inputtxt.pack()
Display.pack()
Output.pack()
mainloop()
inputtxt.get returns a string, but na * nb is an int. So in your example, you're comparing the string "6" against the integer 6. You need to convert INPUT to an integer, otherwise the comparison against na * nb will always fail. E.g.,
if(int(INPUT) == na * nb):
You can improve this code further by handling non-numeric inputs appropriately, but this is the root of the problem.
I am trying to make a loan amortization table inside tkinter GUI using text box. However, all the loan amortization table is fully displayed in the terminal console as an output.
The tkinter text BOX output display's only the last line: Here is the full code:
import math
import tkinter as tk
from tkinter import *
def calcLoanPayment(p, r, n, t):
if p > 0 and r > 0 and n > 0 and t > 0:
clp = (p *(r/n)*(pow(1 + r/n, n * t)))/(pow(1 + r/n, n * t)-1)
clp = round(clp, 2)
return clp
else:
return -1
def runApp(): #This will bound the function runapp to the calcbtn.
print("running")
p = principalentry.get() #this will get value as a string
try:
p = float(p) #this will make cast it to float variable.
except:
p = -1
principalentry.delete(0, END) #this will clear the entry after calculation
r = interestrateentry.get()
try: #Try will help from crushing the program when wrong value entered
r = float(r)
except:
r = -1
interestrateentry.delete(0, END) #this will clear the entry after calculation
n = compoundintervalentry.get() #this will get value as a string
try:
n = int(n) #this will make cast it to float variable.
except:
n = -1
compoundintervalentry.delete(0, END) #this will clear the entry after calculation
t = durationentry.get()
try: #Try will help from crushing the program when wrong value entered
t = int(t)
except:
t = -1
durationentry.delete(0, END) #this will clear the entry after calculation
clp = calcLoanPayment(p,r,n,t)
print(clp)
paymentinterval = n*t
paymentinterval = int(paymentinterval)
startingBalance=p
endingBalance=p
for i in range(1, paymentinterval+1):
interestcharge =r/n*startingBalance
endingBalance=startingBalance+interestcharge-clp
result ="\t\t"+str(i)+"\t\t" +str(round (startingBalance, 1)
)+"\t\t"+str(round (interestcharge, 1))+"\t\t"+str(round (clp, 1)
)+"\t\t"+str(round (endingBalance, 1))
startingBalance = endingBalance
print(result)
finaloutput = result
output.config(state="normal")
output.delete(0.0, 'end')
output.insert(END, finaloutput)
output.config(state="disabled")
#Frontend maincode Startshere:
#sketch the design of the user interface first.
root = tk.Tk()
root.config(bg="#F8B135")
root.state("zoomed")
#There are 3 steps to build event programming
#Step 1: construct the widgets
#step 2: configure the widget to make it nicer
#srep 3: place or pack the widget in the root window
title = Label(root, text = "Loan Payment Calculator", font = 'bold')
title.config(fg='white', bg="#28348A")
title.pack(fill = BOTH)
principallabel = Label(root, text="Principal: ")
principallabel.config(anchor = W, font = 'bold', bg="#F8B135")
principallabel.place(x=50, y=30)
principalentry = Entry(root)
principalentry.config(bg="#ffffff")
principalentry.place(x=400, y=30)
interestratelabel = Label(root, text="Interest Rate: enter as Decimal (eg.2% as 0.02) ")
interestratelabel.config(anchor = W, font = 'bold', bg="#F8B135")
interestratelabel.place(x=50, y=70)
interestrateentry = Entry(root)
interestrateentry.config(bg="#ffffff")
interestrateentry.place(x=400, y=70)
compoundintervallabel = Label(root, text="Compound Interval: ")
compoundintervallabel.config(anchor = W, font = 'bold', bg="#F8B135")
compoundintervallabel.place(x=50, y=110)
compoundintervalentry = Entry(root)
compoundintervalentry.config(bg="#ffffff")
compoundintervalentry.place(x=400, y=110)
durationlabel = Label(root, text="Duration: ")
durationlabel.config(anchor = W, font = 'bold', bg="#F8B135")
durationlabel.place(x=50, y=150)
durationentry = Entry(root)
durationentry.config(bg="#ffffff")
durationentry.place(x=400, y= 150)
output = Text(root)
output.config(width= 150, height = 100, bg="white", state="disabled", borderwidth=2, relief= "groove", wrap='word')
output.place(x=50, y=230)
calcbtn = Button(root, text= "Calculate", font = 'bold', highlightbackground="#3E4149")
calcbtn.config(fg='#28348A',command=runApp)
calcbtn.place(x=50, y=190)
root. mainloop()
file.close()`
I couldn't figure out How to display the whole output like the terminal did on the tkinter textbox output function. your help is much appreciated.
There are 2 small changes to the code in the function runApp()
output.config(state="normal")
# output.delete(0.0, 'end') # This line deletes the last entry in the text box. Remove this
output.insert(END, finaloutput + '\n') # Add a newline here. Generates the desired 'tabular' output
output.config(state="disabled")
I'm trying to make my scoring system work. it keeps forgetting after I have changed the score once I go back into the class as it is set as 0. How would I change this so the score changes as appropriate?
code:
import random
from tkinter import *
class TimesTableGUI:
def __init__(self, parent, score = 0):
self.score = score
#chooses a random number
num1 = random.randint(1,10)
num2 = random.randint(1,10)
self.answer = num1 * num2
#making labels
entry_label = Label(parent, text = str(num1) + " * " + str(num2))
entry_label.grid(row = 0, column = 0)
self.e1 = Entry(parent, width = 5)
self.e1.grid(row = 0, column = 1)
b1 = Button(parent, text = "Check Answer", command = self.check_answer)
b1.grid(row = 1, column = 0)
b2 = Button(parent, text = "Next", command = self.new_question)
b2.grid(row = 1, column = 1)
self.b1_output = Label(parent, text = self.score)
self.b1_output.grid(row = 2, column = 0)
def check_answer(self): #callback for Check Answer button
#check if users gets correct answer
f = int(self.e1.get())
if f == self.answer:
self.score +=1
self.b1_output.configure(text = self.score)
else:
self.b1_output.configure(text = self.score)
def new_question(self): #callback for Next button to next question
self.b1_output.configure(text = " ")
radiobuttons = TimesTableGUI(root) #restarts the class for new question
if __name__ == "__main__":
root = Tk()
root.title("Task 3")
radiobuttons = TimesTableGUI(root)
root.mainloop()
Try this:
import random
from tkinter import *
class TimesTableGUI:
def __init__(self, parent, score=0):
self.score = score
self.master = parent
self.ask_new_question()
self.b1_output = Label(parent, text="Score = %i" % self.score)
self.b1_output.grid(row=2, column=1)
def ask_new_question(self):
self.question_frame = Frame(self.master)
self.question_frame.grid(row=1, column=1)
#chooses a random number
num1 = random.randint(1, 10)
num2 = random.randint(1, 10)
self.answer = num1 * num2
#making labels
entry_label = Label(self.question_frame, text="%i*%i" % (num1, num2))
entry_label.grid(row=0, column=0)
self.e1 = Entry(self.question_frame, width=5)
self.e1.grid(row=0, column=1)
self.check_answer_btn = Button(self.question_frame, text="Check Answer",
command=self.check_answer)
self.check_answer_btn.grid(row=1, column=0)
b2 = Button(self.question_frame, text="Next",
command=self.new_question)
b2.grid(row=1, column=1)
def check_answer(self):
user_answer = int(self.e1.get())
if user_answer == self.answer:
self.score += 1
self.b1_output.configure(text="Score = %i" % self.score)
# So the user can't submit more than 1 correct answer
self.check_answer_btn.config(state="disabled")
def new_question(self):
# Remove the frame (and all of its children)
self.question_frame.destroy()
# Display the new question
self.ask_new_question()
if __name__ == "__main__":
root = Tk()
root.title("Task 3")
radiobuttons = TimesTableGUI(root)
root.mainloop()
I moved all of the widgets that are for the question inside a frame. The frame gets destroyed and recreated each time a new question needs to be displayed. I also made sure the user can't just keep clicking on Check Answer after they got the correct answer already (for that question).
The problem is that when you you call radiobuttons = TimesTableGUI(root) score is getting reset too.
Quick solution: pass score when you call radiobuttons = TimesTableGUI(root, score=self.score) in new_question
Better solution: create a method that reset GUI without reinitialize the entire class.
import sys
from tkinter import *
def main():
mtext = ment.get()
mlabel2 = Label(top, text=mtext).pack()
def isbn():
digits = [(11 - i) * num for i, num in enumerate(map(int, list()))]
digit_11 = 11 - (sum(digits) % 11)
if digit_11 == 10:
digit_11 = 'X'
digits.append(digit_11)
isbn_number = "".join(map(str, digits))
label2 = Label(top, text = "Your ISBN number is",).pack()
top = Tk()
top.geometry("450x450+500+300")
top.title("Test")
button = Button(top,text="OK", command = isbn, fg = "red", bg="blue").pack()
label = Label(top, text = "Please enter the 10 digit number").pack()
ment= IntVar()
mEntry = Entry(top,textvariable=ment).pack()
Hello, I the code at the moment is a working stage, I just need a way of the results printing because at the moment it is not. I would also like the converter to work proper ally with 10 digits and the 11th digit being the number that the converter finds outs. Thanls
Note how the button's command calls the function to perform your operation:
from tkinter import *
def find_isbn(isbn, lbl):
if len(isbn) == 10:
mult = 11
total = 0
for i in range(len(isbn)):
total += int(isbn[i]) * mult
mult -= 1
digit_11 = 11 - (total % 11)
if digit_11 == 10:
digit_11 = 'X'
isbn += str(digit_11)
lbl.config(text=isbn)
top = Tk()
top.geometry("450x450+500+300")
top.title("Test")
button = Button(top, text="OK", command=lambda: find_isbn(mEntry.get(), mlabel2), fg="red", bg="blue")
button.pack()
label = Label(top, text="Please enter the 10 digit number")
label.pack()
mEntry = Entry(top)
mEntry.pack()
mlabel2 = Label(top, text='')
mlabel2.pack()
top.mainloop()
You also need to call .mainloop(), on your master widget to get the whole things started. It's also better to call .pack() on an object on a separate line. pack() and grid() return nothing so you won't be able to use other methods on the object once you do that.