Задание:
Дана окружность, представляющая собой кольцевую железную дорогу, имеющую определенный радиус. По дороге происходит движение поездов. Каждый поезд характеризуется максимальной скоростью движения. На кольцевой дороге расположены светофоры. Светофор показывает:
красный свет, если на участке от него до следующего светофора имеется хотя бы один поезд;
желтый свет, если поезд имеется на втором от него участке;
зеленый, если на двух ближайших участках поездов нет.
Скорость движения поездов определяется по следующему правилу:
едет с половинной скоростью, если пересек светофор на желтый свет;
едет с полной скоростью, если пересек светофор на зеленый свет;
стоит перед светофором, если на светофоре красный свет;
Обеспечить возможность добавления и удаления светофоров, поездов. Новый поезд добавляется перед каким-либо светофором, если перед ним не стоит другой поезд. В момент добавления поезда движение остальных поездов приостанавливается. Предусмотреть возможность изменения максимальной скорости поездов.
Постановка задачи:
В соответствии с условиями задачи требуется применить средства графического отображения, а так же компонента класса TTimer для организации непрерывного движения поездов с непрерывным ,по определению, переключением светофора. Для добавление и удалении поездов и светофоров, соответственно, а так же изменения скорости поездов целесообразно применять диалоговые окна. Для управления всеми поездами и светофорами целесообразно применить двунаправленный список.
Выделение классов:
Класс светофора
Экземпляр данного класса (TSvetofor) должен уметь пересчитывать свет, прорисовывать, а также знать ссылки на следующий и предыдущий экземпляр класса (TSvetofor) , в связи использования двунаправленного списка. Так же класс содержит в себе уникальный номер, ссылку на поезд (TTrain) который находится перед данным светофором, текущий свет, координаты своей прорисовки и, угол начала и конца своего расположения.
TSvetofor = class
private
NextSvetofor: TSvetofor ;
BackSvetofor: TSvetofor
Index: integer
IndexPoint: TPoint ;
Train: TTrain ;
StatusColor: Byte ;
aPosit: Real ;
aPositPerem: Real ;
xy: array [1..4] of TPoint ;
Canvas: TCanvas ;
ListBox: TListBox ;
Panel: TStatusPanel ;
constructor Create(fNextSvetofor, fBackSvetofor: TSvetofor; faPosit: Real; fIndex: integer ; fCanvas: TCanvas; fListBox: TListBox; fPanel: TStatusPanel) ;
destructor Destroy; override ;
procedure SelfPereschet ;
public
function Delete: boolean ;
end;
где:
NextSvetofor – ссылка на следующий светофор;
BackSvetofor – ссылка предыдущей светофор;
Index – уникальный номер светофора;
IndexPoint – координаты текста(Index) светофора;
Train – ссылка на поезд, находящийся перед данным светофором;
StatusColor – цвет на светофоре(0: красный, 1: желтый, 2: зеленый);
aPosit – фактический угол начала светофора;
aPositPerem – фактический угол конца светофора;
xy – четыре координаты светофора для его прорисовки;
Canvas – холст;
ListBox – список для хранения светофоров;
Panel – визуальное отображение кол-ва светофоров;
Метод constructorCreate служат для создания нового светофора с заданием начальных значений полей класса и определение постоянных значений.
constructor TSvetofor.Create(fNextSvetofor, fBackSvetofor: TSvetofor; faPosit: Real; fIndex: integer ; fCanvas: TCanvas; fListBox: TListBox; fPanel: TStatusPanel) ;
var
fa1,fa2: real ;
w,h: integer ;
begin
inherited Create ;
NextSvetofor:= fNextSvetofor ;
BackSvetofor:= fBackSvetofor ;
{Выбрать индекс автоматически или записать из fIndex}
if fIndex = -1 then
begin
inc(MaxIndexSvetofor) ;
Index:= MaxIndexSvetofor ;
end
else
Index:= fIndex ;
Train:= nil ;
StatusColor:= 2 ;
{Определение углов начала и конца}
aPosit:= faPosit - aVTrain ;
if aPosit < 0 then
aPosit:= pi2 + aPosit ;
aPositPerem:= faPosit + aVTrain ;
if aPositPerem >= pi2 then
aPositPerem:= aPositPerem - pi2 ;
fa1:= faPosit ;
fa2:= fa1 + aVSvetofor ;
{Координаты для прорисовки светофора}
xy[1].x:= x0 + Round(cos(fa1)*(Radius - CLSvetofor)) ;
xy[1].y:= y0 + Round(sin(fa1)*(Radius - CLSvetofor)) ;
xy[2].x:= x0 + Round(cos(fa1)*(Radius + CLSvetofor)) ;
xy[2].y:= y0 + Round(sin(fa1)*(Radius + CLSvetofor)) ;
xy[3].x:= x0 + Round(cos(fa2)*(Radius + CLSvetofor)) ;
xy[3].y:= y0 + Round(sin(fa2)*(Radius + CLSvetofor)) ;
xy[4].x:= xy[1].x + xy[3].x - xy[2].x ;
xy[4].y:= xy[1].y + xy[3].y - xy[2].y ;
if ((fa1 > pi/2) and (fa1 < pi)) or ((fa1 >= pi*3/2) and (fa1 < pi2)) then
fa1:= fa2 ;
Canvas:= fCanvas ;
ListBox:= fListBox ;
Panel:= fPanel ;
{Координаты текста}
IndexPoint.x:= x0 + Round(cos(fa1)*(Radius+10)) ;
IndexPoint.y:= y0 + Round(sin(fa1)*(Radius+10)) ;
w:= Canvas.TextWidth(IntToStr(Index));
h:= Canvas.TextHeight(IntToStr(Index)) ;
if (fa1 >= pi/2) and (fa1 < pi) then
IndexPoint.x:= IndexPoint.x - w
else
if (fa1 >= pi) and (fa1 < pi*3/2) then
begin
IndexPoint.y:= IndexPoint.y - h ;
IndexPoint.x:= IndexPoint.x - w ;
end
else
if (fa1 >= pi*3/2) and (fa1 < pi2) then
IndexPoint.y:= IndexPoint.y - h ;
end ;
Метод destructorDestroy позволяет разрушить светофор при его удалении.
destructor TSvetofor.Destroy ;
begin
inherited Destroy ;
end ;
Метод procedure SelfPereschet позволяет переопределить цвет на светофоре.
procedure TSvetofor.SelfPereschet ;
begin
if NextSvetofor.Train = nil then
begin
{Если впереди на двух участках поездов нет, то свет на светофоре становится зеленым}
if NextSvetofor.NextSvetofor.Train = nil then
StatusColor:= 2
Else
{Если впереди на втором участке есть поезда, то свет на светофоре становится желтым}
StatusColor:= 1
end
else
{Если на следующем участке есть поезд, то свет на светофоре становится желтым}
StatusColor:= 0 ;
end ;
Метод functionDelete проверяет возможность удаления и удаляет светофор.
function TSvetofor.Delete: boolean ;
var
fSvetofor: TSvetofor ; {ссылка на временный светофор}
bool: boolean ; {подтверждение на удаление}
tbool: boolean ;
begin
bool:= false ;
{Пересек ли поезд на заднем светофоре “Угол начала светофора”}
if (BackSvetofor.Train <> nil) and BackSvetofor.Train.PeremBool then
tbool:= true
else
tbool:= false ;
{Поезда нет на следующем и данном участке}
if (NextSvetofor.Train = nil) and (Train = nil) and not tbool then
bool:= true
else
{Поезд есть на следующем участке, но его нет на данном}
if (((NextSvetofor.Train <> nil) and not tbool) or (CountSvetofor = 1)) and (Train = nil) then bool:= true
else
{Поезда нет на следующем участке, но он есть на следующем}
if (NextSvetofor.Train = nil) and (((Train <> nil) and not tbool) or (CountSvetofor = 1)) then
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.