⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 classcross.pas

📁 这是从不同语言来实现操作系统交通灯的调度问题
💻 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 + -