Python交通模拟中如何正确收集车辆出发与到达时间
问题描述
我正在用Python开发一个小型路口交通模拟程序,需要绘制纵轴为车辆数量、横轴为车辆行驶时长的图表。程序中用nb_voiture初始化车辆总数,但start_time列表最终收集了数千个值,远超出预期的nb_voiture数量;end_time列表工作正常,我找不到原因。
相关代码
import pygame import random import time import matplotlib.pyplot as plt # Initialisation de Pygame pygame.init() # Dimensions de la fenêtre WINDOW_WIDTH = 800 WINDOW_HEIGHT = 600 # Dimensions de la voie ROAD1_WIDTH = 650 ROAD1_HEIGHT = 100 # Dimensions de la seconde voie ROAD2_WIDTH = 400 ROAD2_HEIGHT = 100 # Dimensions de la voie à sens unique ROAD3_WIDTH = 50 ROAD3_HEIGHT = 800 # Création de la fenêtre win = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) # Définition des couleurs BLACK = (0, 0, 0) WHITE = (255, 255, 255) BLUE = (0, 0, 255) GREEN = (0, 255, 0) RED = (255, 0, 0) GARDEN = (55, 210, 122) # Classe pour représenter la voiture class Car: def __init__(self, x, y, speed, direction, color): self.x = x self.y = y self.speed = speed self.direction = direction self.change_direction = False self.reached_460 = False self.color = color def move(self): if self.direction == "horizontal": self.x += self.speed if self.x >= 600 and not self.change_direction: self.direction = random.choices(["horizontal", "vertical"], weights=[0.8, 0.2])[0] self.change_direction = True if self.direction == "vertical": self.speed = -self.speed elif self.y > 410 and self.direction == "horizontal" and self.speed < 0: self.y = 410 elif self.y > 410 and self.direction == "horizontal" and not self.reached_460: if self.y > 460: self.y = 460 self.reached_460 = True else: self.y += self.speed elif self.direction == "vertical": self.y += self.speed if self.y >= 410 and not self.change_direction: self.direction = "horizontal" self.change_direction = True self.speed = random.choices([self.speed, -self.speed], weights=[0.8, 0.2])[0] def draw(self, surface): pygame.draw.rect(surface, self.color, (self.x, self.y, 30, 30)) # Création de la voiture nb_voiture = 10 start_time = [] #stock les temps de départ de chaque voiture end_time = [] #stock les temps d'arrivée de chaque voiture cars = [] for i in range(nb_voiture): car1 = Car(0, 460, 3, "horizontal", BLUE) car2 = Car(560, 0, 3, "vertical", GREEN) cars.append(car1) cars.append(car2) # Variables pour enregistrer les coordonnées des voitures car1_x = [] car1_y = [] car2_x = [] car2_y = [] # Boucle principale running = True clock = pygame.time.Clock() while running: #pygame.time.delay(1000) # 50ms entre chaque tours de boucles # Gestion des événements for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # Effacer l'écran win.fill(GARDEN) # Dessiner la voie pygame.draw.rect(win, BLACK, (0, 400, ROAD1_WIDTH, ROAD1_HEIGHT)) pygame.draw.rect(win, BLACK, (550, 0, ROAD2_HEIGHT, ROAD2_WIDTH)) pygame.draw.rect(win, BLACK, (0, 450, ROAD3_HEIGHT, ROAD3_WIDTH)) pygame.draw.rect(win, RED, (650, 450, 10, 50)) #pygame.draw.rect(win, RED, (100, 450, 10, 50)) #pygame.draw.rect(win, RED, (550, 100, 50, 10)) # Dessiner et déplacer les voitures t = 0 for car in cars: if pygame.time.get_ticks() >= t * 500: car.draw(win) car.move() t += 1 if car.direction == "vertical" and car.x == 560 and car.y == 0: start_time.append(pygame.time.get_ticks()) # ajout du temps de départ de chaque voiture dans start_time timedep=False if car.direction == "horizontal" and car.x == 0 and car.y == 460: start_time.append(pygame.time.get_ticks()) # ajout du temps de départ de chaque voiture dans start_time if car.direction == "horizontal" and car.x == 650 and car.y == 460: end_time.append(pygame.time.get_ticks()) # ajout du temps d'arrivée de chaque voiture dans end_time # Mettre à jour l'affichage pygame.display.update() # Limiter la vitesse de la boucle clock.tick(60) # Quitter Pygame pygame.quit() print(start_time) print(len(start_time)) print(end_time) print(len(end_time))
问题原因
问题出在start_time的记录逻辑上:主循环以60帧/秒的频率运行,每一次循环都会检查车辆是否处于起点位置。而车辆在初始化后会停留在起点(直到满足pygame.time.get_ticks() >= t * 500才开始移动),这段时间内每帧都会触发start_time.append(),导致同一个车辆的出发时间被重复记录数千次。
而end_time的记录条件是车辆到达终点,这个状态只会出现一次(车辆到达后会继续移动,不会停留在终点),所以不会重复添加。
解决方案
给Car类添加一个标记属性,确保每辆车只记录一次出发时间:
- 修改
Car类的__init__方法,添加self.start_recorded = False:
class Car: def __init__(self, x, y, speed, direction, color): self.x = x self.y = y self.speed = speed self.direction = direction self.change_direction = False self.reached_460 = False self.color = color self.start_recorded = False # 新增标记
- 修改主循环中记录
start_time的逻辑,添加标记判断,记录后将标记设为True:
for car in cars: if pygame.time.get_ticks() >= t * 500: car.draw(win) car.move() t += 1 # 记录垂直方向车辆的出发时间,仅一次 if car.direction == "vertical" and car.x == 560 and car.y == 0 and not car.start_recorded: start_time.append(pygame.time.get_ticks()) car.start_recorded = True # 记录水平方向车辆的出发时间,仅一次 if car.direction == "horizontal" and car.x == 0 and car.y == 460 and not car.start_recorded: start_time.append(pygame.time.get_ticks()) car.start_recorded = True if car.direction == "horizontal" and car.x == 650 and car.y == 460: end_time.append(pygame.time.get_ticks())
这样修改后,每辆车的出发时间只会被记录一次,start_time的长度就会和车辆总数一致(这里nb_voiture=10,实际生成了20辆车,所以start_time长度应为20)。
内容的提问来源于stack exchange,提问作者Romain Darde
相关产品推荐
相关产品推荐

