Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Практический курс математического и компьютерного моделирования. Учебно-практическое пособие
.pdf
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
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
