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 buttonraceagain and again.canvas.corrds()to get current position and check if it end of race.create_lineto 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()

