You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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类添加一个标记属性,确保每辆车只记录一次出发时间:

  1. 修改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  # 新增标记
  1. 修改主循环中记录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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 19:25:05