📄 classcross.pas
字号:
unit classCross;
interface
uses
unitConst, classVehicle, Graphics, Math, ExtCtrls, Classes, SysUtils;
type
TTrafficCross= class
public
constructor Create(var image: TImage; time_green,time_red,time_yellow: TLightsTime;
initialnum: TCrosses; timerinterval: TTime;
speed: TCoordinateSD; maxnum: TUInt; createprop: TUInt);
//initialnum记录初始交通状况,车辆列队于道路外边界坐标依次 0, [1].long, [2].head+[2].long, ...
//timerinterval记录外部timer的扫描周期
procedure Refresh;
private
conTimerInterval: TTime;
conMaxVehicle: TUInt; //单向最大车辆数
conCreateProp: TUInt; //每秒车辆生成率
conTimeGreen, conTimeRed, conTimeYellow: TLightsTime; //交通灯时间长度
conFrontier: TCrossesFrontier; //各个车道外边缘左上角的坐标,用于绘制车辆时的参考坐标
datImage: TImage; //绘图区域,设为400*400
datTimeLights: array[0..3]of TTime; // 从绿色开始的 绿黄红黄 一个循环的时间变更点
datVehicles: array[1..4,1..50] of TVehicle; //各个方向的车辆列表 const_MaxVehicle=50
datVehiclesCount: TCrosses; //当前各个方向的车辆数的计数器
datVehiclesColor: TCrosses; //当前新创建车辆的颜色,在1--5之间循环
datVehiclesHead: array[1..4]of TCoordinateSD; //当前新创建车的起始位置
datVehicleType: TVehicleType; // 在初始化时定义的除了颜色外的标准化模型
datLights: TCrossLights; // 对各个路口交通灯状态的记录,每次模拟都以1--3方向为绿灯开始
datLightTime: TTime; //记录交通灯使用时间,以便更颜色
datCrossOccupied: TDirection; // 路口占用信号量,只在0,1中取值,基数号路口为1,偶数号路口为0
procedure VehicleMove; //判断车辆状态并移动车辆
procedure VehicleCreate; //随机车辆生成器
procedure VehicleFree; //车辆释放
procedure Draw; //总的绘图
procedure DrawRoad; //绘制路口和交通灯
procedure ClockMove; //红绿灯变更
procedure CrossOccupy; //路口占用信号亮变更
procedure VehicleIncrease(direction: TCoordinateSD); // 按几率生成车辆
published
property Image: TImage read datImage;
end;
implementation
{ TTrafficCross }
procedure TTrafficCross.ClockMove;
var
direction: TDirection;
begin
datLightTime:= datLightTime+ conTimerInterval;
if (datLightTime=datTimeLights[0])or
(datLightTime=datTimeLights[1])or
(datLightTime=datTimeLights[2])or
(datLightTime=datTimeLights[3])
then begin
if datLightTime=datTimeLights[3]
then datLightTime:=0;
for direction:=1 to 4 do
datLights[direction]:= (datLights[direction]+ 1) mod 4;
end;
end;
constructor TTrafficCross.Create(var image: TImage; time_green, time_red,
time_yellow: TLightsTime; initialnum: TCrosses; timerinterval: TTime;
speed: TCoordinateSD; maxnum: TUInt; createprop: TUInt);
var
i,direction:TInt;
begin
conMaxVehicle:=maxnum;
conCreateProp:=createprop;
datLightTime:= 0;
datLights[1]:=0;
datLights[3]:=0;
datLights[2]:=2;
datLights[4]:=2;
datImage:=image;
conTimeGreen:= time_green;
conTimeYellow:= time_Yellow;
conTimeRed:= time_red;
datTimeLights[0]:=conTimeGreen[1];
datTimeLights[1]:=datTimeLights[0]+conTimeYellow[1];
datTimeLights[2]:=datTimeLights[1]+conTimeRed[1];
datTimeLights[3]:=datTimeLights[2]+conTimeYellow[1];
datCrossOccupied:=1;
conTimerInterval:= timerinterval;
conFrontier[1].x:=0;
conFrontier[1].y:=205;
conFrontier[2].x:=185;
conFrontier[2].y:=0;
conFrontier[3].x:=400;
conFrontier[3].y:=185;
conFrontier[4].x:=205;
conFrontier[4].y:=400;
datVehiclesCount[1]:=0;
datVehiclesCount[2]:=0;
datVehiclesCount[3]:=0;
datVehiclesCount[4]:=0;
datVehiclesColor[1]:=0;
datVehiclesColor[2]:=0;
datVehiclesColor[3]:=0;
datVehiclesColor[4]:=0;
datVehiclesHead[4]:=0;
datVehiclesHead[4]:=0;
datVehiclesHead[4]:=0;
datVehiclesHead[4]:=0;
datVehicleType.speed:=speed;
datVehicleType.long:=const_Vehicle_Long;
datVehicleType.width:=const_Vehicle_Width;
for direction:=1 to 4 do // 4个方向的循环
begin
for i:=1 to initialnum[direction] do
begin
VehicleIncrease(direction);
end;
end;
end;
procedure TTrafficCross.CrossOccupy;
var
t,i,direction: TDirection;
occupied: TBool;
begin
occupied:=false;
for t:=1 to 2 do
begin
direction:=t*2-datCrossOccupied;
for i:=1 to datVehiclesCount[direction] do
begin
if ((datVehicles[direction,i].Head>const_Cross_StreetLong)and
(datVehicles[direction,i].Head<const_Cross_StreetLong+2*const_Cross_HalfCrossLong))or
((datVehicles[direction,i].Head-datVehicles[direction,i].Long>const_Cross_StreetLong)and
(datVehicles[direction,i].Head-datVehicles[direction,i].Long<const_Cross_StreetLong+2*const_Cross_HalfCrossLong))
then begin
occupied:=true;
break;
end;
end;
end;
if (occupied=false)and(datLights[datCrossOccupied+2]=const_Red)
then
datCrossOccupied:=(datCrossOccupied+1)mod 2;
end;
procedure TTrafficCross.Draw;
var
direction,i: TCoordinateSD;
begin
DrawRoad;
for direction:=1 to 4 do
for i:=1 to datVehiclesCount[direction] do
datVehicles[direction,i].Draw(conFrontier[direction]);
end;
procedure TTrafficCross.DrawRoad;
begin
with datImage do begin
Canvas.Brush.Color:=clWhite;
Canvas.FillRect(Rect(0,0,400,400));
Canvas.Pen.Color:=clBlack;
Canvas.Pen.Width:=3;
Canvas.MoveTo(180,0);
Canvas.LineTo(180,180);
Canvas.LineTo(0,180);
Canvas.MoveTo(220,0);
Canvas.LineTo(220,180);
Canvas.LineTo(400,180);
Canvas.MoveTo(0,220);
Canvas.LineTo(180,220);
Canvas.LineTo(180,400);
Canvas.MoveTo(400,220);
Canvas.LineTo(220,220);
Canvas.LineTo(220,400);
Canvas.Pen.Color:=clSilver;
Canvas.Pen.Width:=1;
Canvas.MoveTo(200,0);
Canvas.LineTo(200,180);
Canvas.MoveTo(200,220);
Canvas.LineTo(200,400);
Canvas.MoveTo(0,200);
Canvas.LineTo(180,200);
Canvas.MoveTo(220,200);
Canvas.LineTo(400,200);
//红绿灯
Canvas.Pen.Width:=10;
Canvas.Pen.Color:=const_Light_Color[datLights[2]];
Canvas.MoveTo(180,180);
Canvas.LineTo(200,180);
Canvas.MoveTo(220,220);
Canvas.LineTo(200,220);
Canvas.Pen.Color:=const_Light_Color[datLights[1]];
Canvas.MoveTo(220,180);
Canvas.LineTo(220,200);
Canvas.MoveTo(180,220);
Canvas.LineTo(180,200);
// Canvas.TextOut(20,20,inttostr(datCrossOccupied));
end;
end;
procedure TTrafficCross.Refresh;
begin
ClockMove;
VehicleMove;
CrossOccupy;
VehicleCreate;
VehicleFree;
Draw;
end;
procedure TTrafficCross.VehicleCreate;
var
direction: TDirection;
begin
randomize;
for direction:= 1 to 4 do
begin
if (datVehiclesCount[direction]<=conMaxVehicle)and
((random(100)+1)<=(conCreateProp * conTimerInterval) div const_PerTime)
then begin
VehicleIncrease(direction);
end;
end;
end;
procedure TTrafficCross.VehicleFree;
var
direction: TCoordinateSD;
i,t: TUShort;
begin
for direction:=1 to 4 do
begin
for i:=datVehiclesCount[direction] downto 1 do
begin
if (const_Cross_WholeLong < datVehicles[direction,i].Head-datVehicles[direction,i].Long)
then begin
for t:=1 to i do
datVehicles[direction,t].Free;
for t:=i+1 to datVehiclesCount[direction] do
datVehicles[direction,t-i]:=datVehicles[direction,t];
datVehiclesCount[direction]:=datVehiclesCount[direction]-i;
break;
end;
end;
end;
end;
procedure TTrafficCross.VehicleIncrease(direction: TCoordinateSD);
begin
inc(datVehiclesCount[direction]);
datVehiclesColor[direction]:=(datVehiclesColor[direction] mod 5)+1;
datVehicleType.color:= const_Vehicle_Colors[datVehiclesColor[direction]];
datVehicles[direction,datVehiclesCount[direction]]:= TVehicle.Create(datImage,datVehicleType,direction,datVehiclesHead[direction],conTimerInterval);
datVehiclesHead[direction]:=min(0,
datVehicles[direction,datVehiclesCount[direction]].Head-
datVehicles[direction,datVehiclesCount[direction]].Long-1);
// -1 是为了保证不会追尾
end;
procedure TTrafficCross.VehicleMove;
var
direction: TDirection;
nexthead,pretail: TCoordinateSD;
i: TInt;
begin
for direction:= 1 to 4 do
begin
for i:= 1 to datVehiclesCount[direction] do
begin
if (datVehicles[direction,i].Head-datVehicles[direction,i].Long>=
const_Cross_StreetLong+2*const_Cross_HalfCrossLong) //是否已经通过路口
then begin {通过}
datVehicles[direction,i].Moveable:= true;
end
else begin {未通过}
if (datCrossOccupied<> direction mod 2) //是否已经占有路口
then begin {未占有}
// datVehicles[direction,i].Moveable:= false;
nexthead:=datVehicles[direction,i].Head + datVehicles[direction,i].Speed;
//如果前进的位置坐标
if nexthead>const_Cross_StreetLong //是否会越过停车线
then begin {会越过}
datVehicles[direction,i].Moveable:= false;
end
else begin {不会越过}
if i>1 // 是否有车在前面
then begin {有车在前面}
pretail:= datVehicles[direction,i-1].Head - datVehicles[direction,i].Long;
if nexthead>=pretail //是否会追尾
then begin {追尾}
datVehicles[direction,i].Moveable:=false;
end
else begin {不追尾}
datVehicles[direction,i].Moveable:=true;
end;
end
else begin {无车在前面}
datVehicles[direction,i].Moveable:= true;
end;
end;
end
else begin {已占有}
if (datVehicles[direction,i].Head>const_Cross_StreetLong) //是否已经越过停车线
then begin {已越过停车线}
datVehicles[direction,i].Moveable:= true;
end {未越过停车线}
else begin
if (datLights[direction]=const_Green) //是否为绿灯
then begin {绿灯}
datVehicles[direction,i].Moveable:= true;
end
else begin {非绿灯}
nexthead:=datVehicles[direction,i].Head + datVehicles[direction,i].Speed;
//如果前进的位置坐标
if nexthead>const_Cross_StreetLong //是否会越过停车线
then begin {会越过}
datVehicles[direction,i].Moveable:= false;
end
else begin {不会越过}
if i>1 // 是否有车在前面
then begin {有车在前面}
pretail:= datVehicles[direction,i-1].Head - datVehicles[direction,i].Long;
if nexthead>=pretail //是否会追尾
then begin {追尾}
datVehicles[direction,i].Moveable:=false;
end
else begin {不追尾}
datVehicles[direction,i].Moveable:=true;
end;
end
else begin {无车在前面}
datVehicles[direction,i].Moveable:= true;
end;
end;
end;
end;
end;
end;
end;
end;
for direction:=1 to 4 do
for i:=1 to datVehiclesCount[direction] do
datVehicles[direction,i].Move;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -