Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Практический курс математического и компьютерного моделирования. Учебно-практическое пособие

.pdf
Скачиваний:
0
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
II. Программная реализация математической модели
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ­procedure init_rook; begin if ( ID.number = 3 ) then exit; if ( ID.number = 2 ) then queen.delete; ID.number := 3; rook := Trook.Init( ID, chess_board ); rook.move(ID.pos ); end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // инициализация шахматной доски bord // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ­procedure TForm1.FormActivate( Sender: TObject ); begin form1.Width := 600; form1.Height := 540; h := ( form1.Width – 210 ) div 8; chess_board := Tboard.init( whiteCell,blackCell, h, Form1 ); chess_board.refresh; StatusBar1.SimpleText := 'click board'; ID.pos.x := _e; ID.pos.y := 2; ID.color := white; ID.number := 0; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // по "мышиным" координатам выводит в статусную строку // координаты клетки под курсором мыши // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ­procedure TForm1.FormMouseMove( Sender : TObject; Shift : TShiftState; X, Y : Integer ); var pos : Tposition; begin pos := chess_board.search_pos( X, Y );
51
Математическое и компьютерное моделирование
StatusBar1.SimpleText := ' ' + chr( 65 + ord( pos.x ) ) + ' ' + IntToStr( 9 - pos.y ); end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ­// по щелчку на клетке доски двигает в нее фигуру // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ­procedure TForm1.FormMouseDown( Sender : TObject; Button : TMouseButton; Shift : TShiftState; X, Y : Integer ); begin ID.pos := chess_board.search_pos( X, Y ); if ( ID.number = 2 ) then queen.move( ID.pos ); if ( ID.number = 3 ) then rook.move( ID.pos ); end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ­procedure TForm1.MenuExitClick( Sender: TObject ); begin close; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ­procedure TForm1.menuAboutClick(Sender: TObject); begin ShowMessage( 'Заготовка для шахмат'+ #13#10 + 'учебный пример' + #13#10 + 'В.Зенкин, 2005 г.' ); end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ­procedure TForm1.RadioGroup1Click(Sender: TObject); begin if RadioGroup1.ItemIndex = 0 then init_queen; if RadioGroup1.ItemIndex = 1 then init_rook; end; end. // конец файла chessMain.pas
На рисунке II. 3 представлен вид окна программы на этапе выполнения.
52
II. Программная реализация математической модели
Pиc. II.3.
II.5. Пример 1. Прыгающий мяч
Перейдем к программной реализации модели, построенной в I.3, в соответствии с планом, изложенным в II.3.
1. Мы должны иметь два объекта, которые назовем Y1 (без
учета сопротивления воздуха) и Y2 (с учетом сопротивления). В нашем случае легко видеть, что оба объекта имеют сходное по­ведение. Удобно вести расчеты отдельно для каждого из вре­менных промежутков [0, t
], [t
1
, t
1
2
], … , [t
, t
], … , где ti — мо-
i
i+1
менты удара мяча о землю. Поскольку в условии задачи сказано об анимационной иллюстрации движения мяча, необходимо знать: координату мяча в каждый заданный момент времени, время удара о землю, скорость при ударе, максимальное значе­ние координаты (необходима для масштабирования окна гра­фического вывода). Методы (обработчики сообщений), возвра­щающие эти параметры,
очевидно, будут общими для обоих объектов. Для объекта Y2, сверх того, нужно предусмотреть возврат значения скорости в каждый момент времени.
53
Математическое и компьютерное моделирование
4
2. Спроектируем соответствующую иерархию классов. В
базовом классе Tcoordinate сосредоточим общие обработчики сообщений, возвращающие координату мяча в каждый задан­ный момент времени (get_top_list), время удара (get_t_impact), скорость при ударе (get_v_impact), максимальную координату (get_Max_value). Перечисленных методов, очевидно, достаточ­но и для функционирования класса Ty1, а для класса Ty2 кроме них потребуется возвращать
значение скорости (get_v_list).
3. Количество точек N для вычислений на каждом из вре-
менных интервалов [
t
, t
] разумно предоставить задавать
i
i+1
пользователю, присоединив эту величину к множеству входных параметров модели. Для того чтобы время, затрачиваемое на расчеты координат, не влияло на время анимационного цикла на временных промежутках между ударами о землю, удобно все вычисления сделать до начала этого цикла, а при анимации счи­тывать уже готовые значения.
Следовательно, вычисленные зна­чения координат нужно хранить в списке, выделяя и возвращая под него память динамически на каждом временном интервале — метод calc_values, а метод get_top_list будет возвращать указа­тель на «вершину» этого списка top_coord_list. Для определения момента удара t_impact и скорости в момент удара v_impact, а так­же максимальной
координаты max_coord_value потребуются соот­ветствующие методы: calc_t_impact, calc_v_impact и calc_max_value. Для вычислений координаты и скорости нужно предусмотреть соответствующие методы — position, velocity, — причем в базовом классе они должны быть абстрактными и виртуальными, так как соответствующая информация будет доступна только в произ­водных классах (см. листинги программы).
В классе Ty2 потребуется метод calc_v,
рассчитывающий скорости точки в заданные моменты времени и сохраняющий их в списке, а метод get_v_list будет возвращать указатель на «вершину» этого списка top_v_list.
Поддержка анимации и графики вынесена в отдельный модуль ballFormUnit.pas (см. листинги), так как эти средства являются внешними по отношению к рассматриваемым объектам, системно зависимыми и могут быть
реализованы различными способами,
например средствами библиотек OpenGL или DirectX.
5
II. Программная реализация математической модели
5
α
α
Головной модуль mainUnit.pas содержит «движки» моде­лей и средства управления проектом.
Нетрудно видеть, что построенную компьютерную модель легко модифицировать, причем
без изменения уже написанного
кода. Например, пусть требуется исследовать движение мяча, брошенного под углом
к горизонту. Тогда для вертикальной
проекции координаты мяча можно воспользоваться классом Ty1
(или Ty2), заменив при инициализации объекта параметр v v
sin . И дополнительно нужно описать изменение горизон-
0
на
0
тальной проекции координатылибо выведя класс-наследник
Ty1, либо другим способом (наследованиене единственный
прием в объектно-ориентированном проектировании). На ри­сунке II. 4 показано окно программы на этапе выполнения.
Рис. II. 4.
Для сравнения решение этой же задачи посредством про­цедурного программирования можно посмотреть в книге [2].
II.6. Листинги примера 1
Для сокращения размера программного кода почти не применялась оптимизация. Эффективность всюду принесена в
5
Математическое и компьютерное моделирование
6
жертву читаемости. Все необходимые пояснения содержатся в комментариях.
II.6.1. Базовый класс
// файл coordinateUnit.pas unit coordinateUnit; interface // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - const eps = 1.0E-5; // точность расчетов; const g = 9.80665; // ускорение свободного падения; type value_list = ^list; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - list = record // односвязный список (стек) value : double; // для хранения значений link : value_list; // координаты-функции; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // координата - функция времениабстрактный базовый // класс, координаты position(t) записываются в список, в // "вершине" которого top_coord_list, t0 <= t <= t_impact // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type Tcoordinate = class protected t0 : double; // начальные значения времени y0 : double; // координаты; v0 : double; // и скорости; k : double; // коэффициент восстановления; t_impact : double; // момент удара; v_impact : double; // скорость в момент
удара; max_coord_value : double; // макс. значение координаты; top_coord_list : value_list; // указатель на "верх" списка; N : LongInt; // количество точек расчета; function position( t: double ): double; virtual; abstract; function velocity( t: double ): double; virtual; abstract; procedure calc_values; // опр. значений координат;
5
II. Программная реализация математической модели
7
procedure calc_t_impact; // опр. момента удара о "пол"; procedure calc_v_impact; // опр. скорости при ударе; procedure calc_max_value; // опр. максимальной высоты; public function get_top_list: value_list; function get_t_impact: double; function get_v_impact: double; function get_Max_value: double; constructor birth( tt0, yy0, vv0, kk: double; NN: LongInt ); destructor kill; virtual; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - implementation // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // определение момента удара (с точностью eps) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - procedure Tcoordinate.calc_t_impact; var t1, t2: double; const dt = 2*eps; begin // решение уравнения t1 := t0; // position( t_impact ) = 0; t2 := t1 + dt; while ( position( t2 ) > 0 ) do // пока не найдется отрица- begin // тельная или нулевая ко- t1 := t2; // ордината position; t2 := t2 + dt; end; t_impact := ( t1 + t2 )/2; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // возвращает время удара // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function Tcoordinate.get_t_impact: double; begin result := t_impact; end;
5
Математическое и компьютерное моделирование
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // определение скорости в момент удара // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - procedure Tcoordinate.calc_v_impact; begin v_impact := velocity( t_impact ); end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // возвращает скорость в момент удара // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function Tcoordinate.get_v_impact : double; begin result := v_impact; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // расчет значений координаты-функции на отр. [t0; t_impact] // c шагом delta_t и занесение их в список, на вершину кото- // рого указывает top_coord_list // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - procedure Tcoordinate.calc_values; var t, delta_t : double; ptr : value_list; begin if ( t0 >= t_impact ) then exit; t := t_impact; delta_t := ( t_impact - t0 )/N; while ( t >= t0 ) do // список заполняется значени- begin // ями функции по убыванию new( ptr ); // аргумента,поэтому, в "вер- ptr.value := position( t ); //
шине" стека окажется самое ptr.link := top_coord_list; // первое значение координаты; top_coord_list := ptr; t := t - delta_t; end; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
58
II. Программная реализация математической модели
// возвращает указатель на вершину списка координат точки // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function Tcoordinate.get_top_list: value_list; begin result := top_coord_list; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // определение максимальной высоты подъема (с точностью eps) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - procedure Tcoordinate.calc_max_value; var t1, t2, max_y1, max_y2 : double; const dt = 2*eps; begin if ( v0 = 0.0 ) then max_coord_value := y0 else begin max_y2 := y0; t1 := t0; // максимум достигается ДО t2 := t1 + dt; // первого удара о землю?; while ( velocity( t2 ) > 0.0 ) do begin t1 := t2; // пока скорость точки t2 := t2 + dt; // не сменит знак; end; max_y1:= position( ( t1 + t2 )/2.0 ); if ( v0 < 0.0 ) then // максимум достигается begin // ПОСЛЕ первого удара?; t2 := t1 - dt; while ( velocity( t2 ) < 0.0 ) do begin t1 := t2; // пока скорость точки t2 := t2 - dt; // не сменит
знак; end; max_y2 := k*k*position( ( t1 + t2 )/2.0 );
59
Математическое и компьютерное моделирование
0
end; if ( max_y1 > max_y2 ) then max_coord_value := max_y1 else max_coord_value := max_y2; end; // else ( v0 = 0.0 )... end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // возвращает максимальное значение координаты // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ­function Tcoordinate.get_Max_value: double; begin result := max_coord_value; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - constructor Tcoordinate.birth( tt0, yy0, vv0, kk: double; NN: LongInt ); begin inherited Create; t0 := tt0; y0 := yy0; v0 := vv0; k := kk; N := NN; new( top_coord_list ); top_coord_list.link := NIL; end; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - destructor Tcoordinate.Kill; var ptr : value_list; begin while ( top_coord_list.link <> NIL ) do begin // освобождение выделенной ptr := top_coord_list; // для хранения списка top_coord_list := top_coord_list^.link; dispose( ptr ); // координат памяти; end; dispose( top_coord_list ); inherited Destroy;
6
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]