im a beginner in python and i have a big trouble for this code. im making a small match making game and this game made me hate python.
simply, user should match the photos together and try to do it as fast as possible for getting less time.
however, the timer is never working or giving me recursion limit error.
i want a simple second counter and a way to count the score.
so far, this is what i have and the timer is happening only once. so the label just becoming 1
import mycanvas as mc
import tkinter as tk
import random as r
import time
clickedimages=[]
score = 0
seconds=0
def main():
root=tk.Tk()
root.geometry("550x800")
root.resizable(0,0)
coverimg=tk.PhotoImage(file="pics\\qs.png")
name=""
images=[]
coppyimages=[]
allcanvas=[]
lbl=tk.Label(root,text="0",font=('robot',20))
lbl2=tk.Label(root,text=str(score),font=('robot',20))
lbl.place(x=100,y=750)
lbl2.place(x=400,y=750)
#making images
for x in range(1,11):
name="pics\\p"+str(x)+".png"
images.append(tk.PhotoImage(file=name))
coppyimages.append(tk.PhotoImage(file=name))
coppyimages.append(tk.PhotoImage(file=name))
#5x4
#positioning
tx=50
ty=150
counter=1
for x in range(0,5):
for y in range (0,4):
choice=r.randint(0,len(coppyimages)-1)
allcanvas.append(mc.myconvas(root,counter,coppyimages.pop(choice),tx,ty,coverimg))
tx+=120
counter+=1
tx=50
ty+=120
root.after(1000,timer(lbl))
root.mainloop()
def timer(lbl):
global seconds
seconds+=1
lbl.configure(text=str(seconds))
def clicked(event):
if(len(clickedimages)==0):
event.widget.showorhide()
clickedimages.append(event.widget)
elif((len(clickedimages)>0) and (event.widget != clickedimages[0])):
event.widget.showorhide()
clickedimages.append(event.widget)
matchchecker()
def matchchecker():
global clickedimages,score
time.sleep(0.5)
if(clickedimages[0].nameofimage==clickedimages[1].nameofimage):
print("Its a match")
clickedimages[0].place_forget()
clickedimages[1].place_forget()
score+=1
else:
print("wrong :(")
clickedimages[0].showorhide()
clickedimages[1].showorhide()
clickedimages.clear()
gamechecker()
def gamechecker():
global score
if(score==10):
print("Game over")
if __name__ == '__main__':
main()
the class is :
import tkinter as tk
import main
class myconvas(tk.Canvas):
number=0
myimage=None
nameofimage=""
coverimg=None
show=True
def __init__(self, root,n,img,px,py,dfault):
super().__init__()
self["width"] = 100
self["height"] = 100
self.number=n
self.myimage=img
self.maketheimage(dfault,px,py)
self.nameofimage = img.cget('file')
# self.setimagename()
self.coverimg=dfault;
self.bind("<Button-1>",main.clicked)
# root.after(500,self.showorhide())
def maketheimage(self,img,px,py):
self.create_image(50,50,image=img,anchor='center')
self.place(x=px,y=py)
def setimagename(self):
self.nameofimage=self.myimage.cget('file')
def showorhide(self):
if(self.show):
self.create_image(50,50,image=self.myimage,anchor='center')
self.show=False
else:
self.create_image(50,50,image=self.coverimg,anchor='center')
self.show=True
thank you in advance
Related
For my project I'm making a game with moving notes up. But the movement becomes inconsistent depending on notes amount. Here is the code and I want to speed up function "Update".
from multiprocessing import Process
import time
from tkinter import *
def wait(timee):
for i in range(int(timee*10000000)):
time.perf_counter()
def updateNotes(songdata):
global hp
speed=songdata['Data']['Speed']
tick=0
notearriving=0.9
toadd=1/100
toaddtick=1/10/speed
timetowait=1/100/speed
steps=notearriving/toadd
delay=steps*toaddtick
root.update()
tick=delay
# for i,v in enumerate(songdata['Notes']):
# changed=int(songdata['Notes'][i]['Time'])*toaddtick
# if type(songdata['Notes'][i]['Time'])==str:
# songdata['Notes'][i]['Time']=str(changed)
# else:
# songdata['Notes'][i]['Time']=changed
Get_Songs(songdata['Data']["Name"])
while True:
if hp <=0:
root.destroy()
SpawnNotes(tick-delay,songdata)
tick+=toaddtick
def Update(half):
global hp
middleIndex = math.ceil(len(notes) / 2)
if half == 1:
newlist=notes[0:middleIndex]
elif half == 2:
newlist=notes[-middleIndex:]
else:
newlist=notes
for i,v in enumerate(newlist):
note = v['note']
currentpos=v['currentypos']#-70
change=currentpos-toadd
note.place(relx=v['xpos'],rely=change)
notes[i]['currentypos']=change
if change<1-notearriving and v['owner']=='Enemy':
notes.remove(v)
note.destroy()
break
if configData['WindowSize'][1]*change+note.winfo_height()<0:
if v['owner']=='Player':
hp-=songdata['Data']['NoteDamage']
note.destroy()
notes.remove(v)
#---code with multiprocessing------
if len(notes)>=2:
a=Process(target=lambda: Update(1))
a.start()
a.join()
f=Process(target=lambda: Update(2))
f.start()
f.join()
else:
f=Process(target=lambda: Update(3))
f.start()
#---------------------------------------
# Update(3) code without multiprocessing
root.update()
wait(timetowait)
I tried Multiprocessing, but it gives me an error "EOFError: Ran out of input". Also I tried to do it with Pool, but it made even worse.
I am tryig to create a turtle game where two players can chase around a "goal" shape. I am struggling to get the program to recognize that two shapes are close to each other and therefore that one player should receive a point and then the goal should move. I have pasted my code below, any help would be greatly appreciated.
import turtle as trtl
import random as rand
#initialization / game setup
wn = trtl.Screen()
player1 = trtl.Turtle()
player1.shape('turtle')
player1.fillcolor('red')
player1.penup()
player1.goto(rand.randint(-100,100),rand.randint(-100,100))
player2 = trtl.Turtle()
player2.shape('triangle')
player2.fillcolor('blue')
player2.penup()
player2.goto(rand.randint(-100,100),rand.randint(-100,100))
goal = trtl.Turtle()
goal.shape('circle')
goal.fillcolor('yellow')
goal.penup()
goal.goto(rand.randint(-200,200),rand.randint(-150,-150))
player1_score = 0
player2_score = 0
def player1_up():
player1.setheading(90)
player1.forward(10)
def player2_up():
player2.setheading(90)
player2.forward(10)
def player1_down():
player1.setheading(270)
player1.forward(10)
def player2_down():
player2.setheading(270)
player2.forward(10)
def player1_right():
player1.setheading(0)
player1.forward(10)
def player2_right():
player2.setheading(0)
player2.forward(10)
def player1_left():
player1.setheading(180)
player1.forward(10)
def player2_left():
player2.setheading(180)
player2.forward(10)
if (abs(player1.xcor() - goal.xcor())<5):
if (abs(player1.ycor() - goal.ycor())<5):
player1_score+=1
goal.goto(rand.randint(-200,200),rand.randint(-150,150))
print(player1_score)
#events
wn.onkeypress(player1_up, "w")
wn.onkeypress(player2_up, "i")
wn.onkeypress(player1_down, "s")
wn.onkeypress(player2_down, "k")
wn.onkeypress(player1_right, "d")
wn.onkeypress(player2_right, "l")
wn.onkeypress(player1_left, "a")
wn.onkeypress(player2_left, "j")
wn.listen()
wn.mainloop()
I tried to simplify the code and I have seen this work in other programs. However, I cannot get it to work here!
I'm making an unoriginal game for a first project that just runs in my python terminal. The user is randomly given a set of 2-3 letters and the user has to come up with a real word (checked by the Webster dictionary) that contains the given set of letters within 5 seconds. For example, if the game generates "le" the user can input "elephant" within 5 seconds as a correct word and gives them a point.
The problem is that I can't seem to implement the 5 second timer function to run in the back for every time a prompt is given without messing up some other part or running into another problem. I've looked into threading and can't seem to make use of it.
Here is the code for the main game:
from letters import letter_sets_list
fhand = open("words_dictionary.json")
data = fhand.read()
global score
score = int(0)
game_over = False
while game_over is False:
import random
random_letters = random.choice(letter_sets_list)
print('Word that contains:', random_letters)
answer = input("Type a word:")
if answer in data and random_letters in answer:
score += 1
print("nice one")
else:
game_over = True
print("Game Over \n Score:", score)
fhand.close()
exit()
Here is the timer function I found off YouTube and tried to implement:
def countdown():
global my_timer
my_timer = int(5)
for x in range(5):
my_timer -= 1
sleep(1)
countdown_thread = threading.Thread(target=countdown)
countdown_thread.start()
Take a look at that. Especially check if that will work for you:
import time
from threading import Thread
answer = None
def check():
time.sleep(2)
if answer != None:
return
print("Too Slow")
Thread(target = check).start()
answer = input("Input something: ")
Edit: I tried to implement code from my previous answer to your code but with a little different approach:
import time, threading
#from letters import letter_sets_list
#import random
#fhand = open("words_dictionary.json")
#data = fhand.read()
data = ["answer"]
answer = [None]
random_letters = [None]
global score
score = int(0)
game_over = False
x = 0
def game(answer, random_letters):
#random_letters = random.choice(letter_sets_list)
print('Word that contains:', random_letters)
while True:
answer[0] = input("Type a word: ")
mythread = threading.Thread(target=game, args=(answer, random_letters))
mythread.daemon = True
mythread.start()
for increment in range(5):
time.sleep(1)
if answer[0] in data: # and random_letters in answer
score += 1
print("Good answer")
x = 1
break
if x != 1:
print("\nTime is up")
else:
x = 0
game_over = True
In this approach I didnt use time.sleep() inside threaded function but outside of it which helps with killing it. Also i assumed that if your answer is incorrect you would like to have another chance to answer untill time is up or answer is correct so I just used while loop in threaded function. The code is quite simple so I think if you spend a little time analysing your parts of the code you will figure it out.
Some parts of the code I didn't use as I dont have access to your json files ect., but if I understand correctly what you're trying to do, it shoud work. Also check how will behave your kernel. In my case sometimes it shows some problems but my PC is not the best and so it might be only problem with RAM or other part of my computer as it happens quite often with my projects.
Clarificaition
This is a repost of my previous question as I am extremely desperate to receive an answer to my problem. I am quite new and if this is against any of the rules, please inform me as I would remove this post if so.
I want to create a quiz-like program where the user would be able to see the countdown timer ticking down every second while they can input their answer at any time. According to my previous post regarding this question, I've tried using threading in my code. Here is a sample of my code.
from threading import Thread
import time
import sys
def func1():
t = 10
for t in range (t,1,-1):
sys.stdout.write('\r' + str(t))
sys.stdout.flush()
time.sleep(1)
if __name__ == '__main__':
Thread(target = func1).start()
answer = input("\tEnter: ")
It does function, but the problem is that the user input is forced to return back (\r) while the timer doesn't properly remove the '0' of the 10 which is not what I desire. Here is the output:
It would be a tremendous help if you could suggest a solution to this problem. Thank you in advance.
After some messing around, I came up with this.
If you would like me to edit this to make it work without the windows, let me know.
import time
import tkinter
from tkinter import messagebox
from tkinter import *
from tkinter import ttk
from threading import Thread
def clear():
print('\033[H\033[J', end='')
run = True
def timer():
tim = int(input("Type how long the countdown should last in seconds: "))
clear()
count = 0
while count < tim and run == True:
clear()
b1 = (tim-count)
c = (str(b1),"second(s) left")
win = Tk()
win = Tk()
win.attributes('-fullscreen', True)
if run == False:
win.destroy()
Label(win, text= c,
font=('Helvetica 20 bold')).pack(pady=20)
win.after(1000,lambda:win.destroy())
win.mainloop()
time.sleep(1)
count += 1
def take_input():
inpu = input()
#Your code
def time_input():
global run
while run == True:
t1 = Thread(target=timer)
t2 = Thread(target=take_input)
t1.start()
t2.start()
t2.join()
thread_running = False
run = False
time_input()
Hope this helps, and you're welcome. 乇卩丨匚卄乂尺
(To stop the window from being fullscreen, change the (window).attributes('-fullscreen', True) to (window).geometry(500x500) or whatever you wish.
I am aware of the .after method, but it requires a function to use.
I tried making a function that does nothing, but it just freezes the screen.
Is there a way to make it so it doens't modify the gui when doing .after? (I tried with a function that did, and it worked)
def doNothing():
return "nothing"
def init_timer(time=25):
global minutes
global onBreak
minutes = 0
onBreak = False
while True:
pomodoro()
def pomodoro():
global pomodoros
if pomodoros < 4:
setTimer(25)
while not(isTimerDone):
print("Timer In Progress")
setTimer(5)
while not(isTimerDone):
pomodoros += 1
else:
setTimer(30)
def timerDone():
global onBreak
global isTimerDone
isTimerDone = True
reminderTitle.config(text="The timer is done!")
onBreak = not(onBreak)
if onBreak:
reminderTitle.config(text="Go on break!")
else:
reminderTitle.config(text="Get to work!")
timer.config(text="Completed")
playsound(f'{os.getcwd()}/Audio/notification.mp3')
def setTimer(mins=25):
global isTimerDone
isTimerDone = False
timer.config(text="In Progress")
window.after(mins * 60 * 1000, timerDone)
This problem occurs when you use while function . So, in order to make your program work properly you have to use .after only , not inside a while function .Here is an example that you could base on to improve your program :
import tkinter as tk
root = tk.Tk()
clock = tk.Label(root)
k = 0
def timing(time):
'''time in minutes'''
global k
k = time
clock.configure(text = 'you still have : ' + str(time) + ' minutes')
def change_value():
global k
if k > 0:
k = k-1
clock.configure(text = 'you still have : ' + str(k)+' minutes')
root.after(60000,change_value)
else :
clock.configure(text = "it's over")
root.after(60000,change_value)
timing(5)
clock.pack()
root.mainloop()