|
Программирование >> Рекурсивные объекты и фрактальные узоры
csOvertake - расстояние до ближайшей впереди машины превысило минимальную допустимую дистанцию. Функция обновления ТСаг: : UpDate () выглядит следующим образом: void ТСаг::UpDateО { if {state changed) { switch (state) { case csTrouble : speed -= speed up; if (speed <= 0) { speed = 0; state = csTroubleSolved; color = clYellow; break; case csTroubleSolved: speed += speed up; if (speed >= max speed) { speed = max speed; state = csNormal; color = clGreen; State changed = false; break; case csTroubleNoticed: if (reaction time) { speed -= speed up; if (speed < 0) speed = 0; чтобы назад не поехал else --reaction time; приближаем момент реагирования break; case csOvertake: if (reaction time) { speed += speed up; if (speed > rnax speed) speed - inax speed; не допускаем превышения скорости state = csNormal; else --геасtion time; break; position += speed; Здесь используется механизм наподобие конечного автомата: в зависимости от текущего состояния выполняем некоторые действия и при определённых условиях переходим к другому состоянию. Стоит отметить, что бездействие есть выполнение ничего . Так, в состоянии csNormal машина ничего не изменяет кроме позиции, а позиция обновляется всегда, поэтому нормальное состояние даже не рассматривается. Однако в нашей задаче состояния могут меняться не только изнутри самим автоматом, но и снаружи генератором помех посредством функции МакеТгоиЫе(): void ТСаг::MakeTrouble() { state changed = true; state = csTrouble; color = ClRed; Разобравшись с автомобилями, займёмся главным окном нашей программы (рис. 7.5). На главную форму FMain поместим объект типа TPanel для размещения всех управляющих элементов, придав свойству Align значение alBottom. На эту панель поместим пять объектов типа TLabeledEdit: LE Length: длина моделируемого участка автострады; LE CarInterval: частота генератора автомобилей; LE TroubleInt.erval: частота генератора помех; LE Speed: максимальная допустимая скорость; LE Distance: минимальная допустимая дистанция. На форму следует поместить ещё несколько элементов управления: B Initialize: кнопка инициализации; SE ModelingSpeed: элемент типа TSpinEdit для выставления скорости моделирования; B StartStop: кнопка запуска/прекращения моделирования; ST CarsOnWay: элемент типа TStaticText для отображения количества машин на трассе в текущий момент времени; ST CarsPassed: количество машин, успешно проехавших участок; ST Traffic: пропускная способность автострады; 4 Пользуясь случаем, прорекламирую книгу, в которой тема конечных автоматов обсуждается куда подробнее: М. Мозговой. Классика программирования: алгоритмы, языки, автоматы, компиляторы. Практический подход. СПб, Наука и Техника , 2006. MainTimer: таймер (объект типа TTimer) , работающий с частотой 100 тиков в секунду (значение свойства Interval таймера равно 10). ,4-. ДопастмяаяciopocTb ш. Часгогвгтц<г вгомобилей(свк) Допуп аядйста Частого помех (сек) И Скорость Moaeiw Машин на TpeccRS Прошло машин: 26 Пропершая стособность: Рис 7.5. Главное окно программы Модель автострады На главную форму поместим ещё два объекта типа TImage: I Bkg и I Buffer, сделав их невидимыми (Visible = false) и растянутыми на всю область формы (Align = alClient). Последний элемент формы - объект PB Screen типа TPaintBox. Значение его свойства Align также должно быть равно alClient. Инициализация параметров программы производится по нажатии кнопки B Initialize: void-fastcall TF Main::B lnitializeClick(TObject *Sender) cqueue.clear 0; cars on way = 0; traffic = 0; cars passed = 0; car nuinber = 0; ininutes passed = 0; скорость моделирования; если modeling speed = 1, моделирование происходит в режиме реального времени modeling speed = SE ModelingSpeed->Value;* для удобства переведём все величины в метры highway length = LE Length->Text.ToInt()*1000; counter = car interval - LE CarInterval->Text.ToInt () *100/modeling speed; trouble interval = bE TroubleInterval->Text.ToInt()*100/modeling speed; max speed = LE Speed->Text.ToDouble()/360*modeling speed; car distance = LE Distance->Text.ToDouble(); minute interval = 6000/modeling speed; randomi2e(); Нажатие кнопки BStartStop запускает и останавливает моделирование: void fastcall TF Main::B StartStopClick(TObject *Sender) if (MainTime!r->Enabled) { MainTimer->Enabled = false; B StartStop->Caption = Пуск ; else { MainTimer->Enabled = true; B StartStop->Caption = Стоп*; Теперь следует организовать работу со списком машин и отобразить происходящее на экране. Находящиеся на автостраде автомобили удобно хранить в объекте класса TCarQueue, расширяющего стандартный дек: template <class Т> class TCarQueue : public deque<T> ( public: void Update 0 { for (TCarQueue<T>: : iterator p = beginO; p != end(); p ++) { if(end()-l != p) { TCarQueue<T>::iterator r = p; r++; потенциально опасное сближение: включаем маневр сброса скорости. обратите внимание на очередность вычитания или используйте функцию fabs() if (((p->position - r->position - r->width/2 - p->width/2) < car distance) && (p->speed < r->speed) && (r->state == csNormal II r->state == csOvertake)) r->timer on = true; пошёл обратный отсчёт r->state changed = true; изменяется состояние машина впереди Эс1медлила ход и расстояние между машинами меньше допустимого r->state = csTroubleNoticed; r->color = clAqua; расстояние больше допустимой дистанции: включаем маневр набора скорости if ((p->position - r->position - r->width/2 - p->width/2) > car distance && r->speed < p->speed && (r->state -- csNormal I I r->state == csTroubleNoticed)) { r->timer on = true; r->statfe changed = true; r->state = csOvertake; r->color = clLime; проверка на столкновение if ((p->position - r->position - r->width/2 - p->width/2) < 0) едем догонять F Main->B StartStopClick(F Main); AnsiString err rness = Столкнулись машины * + (AnsiString) r->nuii±)er + * и * + (AnsiString) p->nuiTUDer; Application->MessageBoxA(err mess.c str(), Произошла авария , 0); F Main->B InitializeClick(F Main); return; обновление всей очереди машин: обновление каждой машины p->Update(); если машина дошла до конца дороги, снимаем её с трассы if (p->position > highway length + car distance) { cars on way--; cars passed++; pop front(); TCarQueue<TCar> cqueue; Результаты моделирования отображаются на экране с помощью функции Draw(). Чтобы избежать мерцания при выводе графики, воспользуемся механизмом двойной буферизации (её суть заключается в том, что весь вывод сначала производится на скрытую графическую поверхность, а затем за один присест копируется на основной экран). void fastcall TF Main::Draw() стираем предыдущее содержимое экрана I VBuffer->Canvas->CopyRect(Rect(О,О, PB Screen->Width, 5 Последняя реклама на сегодня: М. Мозговой. Занимательное программирование. СПб, Питер , 2004. PB Screen->Height), I Bkg->Canvas, Rect(0,0, PB Screen->Width, PB Screen->Height)); рисуем на виртуальном экране все машины for (u int i = 0; i < cqueue.size(); i ++) I VBuffer->Canvas->Brush->Color = cqueue[i].color; I VBuffer->Canvas->Ellipse(cqueue[i].position/highway length * PB Screen->Width - 5, 10, cqueue[i].position/highway length*PB Screen->Width + 5, 16); копируем содержимое буфера на основной экран PB Screen->Canvas->CopyRect(Rect(О, О, PB Screen->Width, PB Screen->Height), I VBuffer->Canvas, Rect(0, 0, PB Screen->Width, PB Screen->Height)); He забудьте объявить открытую функцию-член Draw () в описании класса формы. Собственно моделирование поведения списка машин происходит в обработчике события OnTimer объекта MainTimer: void fastcall TF Main: :MainTiinerTimer (TObject *Sender) if (++counter > car interval) { TCar с = TCar (max speed/2, car nuinber++) ; cqueue.push back(с); counter = 0; car s on way++; if (++trouble counter > troubl e lnterval && cqueue. sizeO > 1) { cqueue [random(cqueue. size () -1) ] -МакеТгоиЫе() ; trouble counter = 0; if (++minute counter > minute interval) { ST CarsOnWay->Caption = Машин на трассе: + (AnsiString)cars on way; ST CarsPassed->Caption = Прошло машин: + (AnsiString)cars passed; if (cars passed > 0) { minutes passed++; ST Traffic->Caption = Пропускная способность: + (AnsiString)(float)cars passed/minutes passed + машин в минуту ; minute counter = 0;
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |