I have a game that generates multiple objects and which object comes to other side of canvas wins. When you press button every object moves a different random distance forward. The problem is that firts object moves the least and last object moves the most. So last object always wins. How do i made it that random object will win and not always the last one.
import tkinter
import random
canvas=tkinter.Canvas(width=400, height=400)
canvas.pack()
label=tkinter.Label(text='set amout of cars')
label.pack()
entry=tkinter.Entry()
entry.pack()
def car():
global move
move=0
canvas.delete('all')
p=int(entry.get())
for i in range(p):
canvas.create_rectangle(20,20 i*20,40,30 i*20, fill='coral')
move=0
def race():
global move
canvas.delete('all')
p=int(entry.get())
for i in range(p):
rand=random.randint(5,20)
move=move rand
canvas.create_rectangle(20 move,20 i*20,40 move,30 i*20, fill='coral')
button=tkinter.Button(text='start', command=car)
button.pack()
button2=tkinter.Button(text='forward', command=race)
button2.pack()
CodePudding user response:
As described in the comments, every object shares the same move
variable, so each object starts where the last one stopped.
The better solution is to call the move
method on the canvas for each of the objects. You can either save a list of objects or just ask the canvas to give you the objects. You can then use randint
to decide how much to move each item.
The race
function would look something like this:
def race():
for car in canvas.find("all"):
delta_x = random.randint(5,20)
delta_y = 0
canvas.move(car, delta_x, delta_y)
CodePudding user response:
All your objects use the same variable move
- so in every execution of race
they use the same position. But in every loop you add new values to move
- so first object use distance move rand1
, second move rand1 rand2
, third move rand1 rand2 rand3
, etc - and this makes problem.
Every object should have own variable with position.
So it would need to use list with positions.
Or better create object only once and get ID
car_id = canvas.create_rectangle(...)
and later use ID
to move this object
canvas.move(car_id, ...)
and this way every car will use own position.
And of course it also need to use list to keep all IDs
def restart():
canvas.delete('all')
all_cars.clear()
number = int(entry.get())
for i in range(number):
car_id = canvas.create_rectangle(20, 20 i*20, 40, 30 i*20, fill='coral')
all_cars.append( car_id )
def race():
for car_id in all_cars:
distance_x = random.randint(5,20)
distance_y = 0
canvas.move(car_id, distance_x, distance_y)
# --- main ---
all_cars = []
EDIT:
Full working code:
I also used
after(100, race)
- so it automatically repeate function after 100ms and you don't have to click buttonrace
again and again.canvas.corrds()
to get current position and check if it end of race.create_line
to show finish line
import tkinter as tk
import random
# --- functions ---
def restart():
canvas.delete('all')
all_cars.clear()
number = int(entry.get())
for i in range(number):
car_id = canvas.create_rectangle(20, 20 i*20, 40, 30 i*20, fill='coral')
all_cars.append( car_id )
# finish line
canvas.create_line(360, 10, 360, 30 (number-1)*20 10, fill='red')
def race():
winner = False
for car_id in all_cars:
distance_x = random.randint(5, 20)
distance_y = 0
canvas.move(car_id, distance_x, distance_y)
x1, y1, x2, y2 = canvas.coords(car_id)
if x1 >= 360:
winner = True
canvas.moveto(car_id, 360, y1-1)
canvas.itemconfig(car_id, fill='green')
if not winner:
root.after(100, race)
# --- main ---
all_cars = [] # list for all IDs
root = tk.Tk()
canvas = tk.Canvas(root, width=400, height=400)
canvas.pack()
label = tk.Label(root, text='set amout of cars')
label.pack()
entry = tk.Entry(root)
entry.pack()
button = tk.Button(root, text='start', command=restart)
button.pack()
button2 = tk.Button(root, text='forward', command=race)
button2.pack()
root.mainloop()