Страница 3 из 6 Программная модель командира В формулировке задачи нет ни слова о том, откуда берется команда. Будем считать, что ее подает командир и что он делает это, переходя во внутреннее состояние "Огонь". Заголовочный файл и реализация методов для класса "Командир" (Officer) представлены в листинге 2. Алгоритм функционирования командира прост (но роль его важна!): это циклические переходы из состояния "Сон" в состояние "Огонь". Из "Сна" командира можно вывести принадлежащим ему методом SetCommand. Перекуем мячи на пули Теперь превратим мячик в пулю, придав ему новый алгоритм поведения. Для этого введем в конструктор мячика параметр - адрес таблицы переходов. Отметьте, кстати, что мы меняем алгоритм работы объекта, не меняя его методов, - прием, почти невозможный в обычном программировании. Кроме того, как объекту некоторого контейнера библиотеки STL, классу необходимо добавить перегруженные операторы ==, !=, > и <. Для связи со стрелком введены ссылка и метод, позволяющий ее установить. Анализ внутреннего состояния стрелка, к которому "прикреплена" пуля, при наступлении состояния "Выстрел" выполняет предикат x1. Предикат x2 определяет условие достижения пулей границы окна. Действие y4 введено для установки пули в исходную позицию в окне отображения. Метод SetCenter помещает бывший мячик (ныне - пулю) в заданную точку, а метод SetMove задает шаг перемещения по координатным осям (см. листинг 3). В начальном состоянии st пуля ожидает события "Выстрел". Когда оно происходит, пуля вылетает и переходит в состояние b1. В этом состоянии она пребывает до тех пор, пока не достигнет границы окна, а затем возвращается в состояние st и ждет следующего выстрела (эдакая пуля-бумеранг). Вместе весело шагать ... Итак, все "общество" в сборе. Есть пуля, стрелок и командир. Их нужно объединить в цепь - единую систему, способную выполнить поставленную задачу. Дадим классу "Цепь" имя CchainShot (листинг 4). Данный класс создает объект "Командир", а также массивы объектов "Стрелок" и "Пуля" - соответственно IArrayRifleman и IArrayBullet. Связи между порожденными объектами организует метод SetLink. Метод OnSize должен вызываться сразу после создания цепи стрелков. Он служит для задания размеров мячиков-пуль, установки их начального положения и определения шагов перемещения по координатным осям за один такт автоматного времени. Методы GetAddrRifleman и GetAddrBullet возвращают адреса стрелков и пуль по их номерам из массивов. При организации связей для каждого стрелка ищется пуля с таким же номером, как у него. Организация связей заключается в присвоении значений указателям, входящим в состав объектов "Стрелок" и "Пуля". При этом для первого стрелка соседом слева является командир, а для последнего указатель на соседа справа имеет значение Null. |