
- •Часть I. Этапы решения задачи на компьютере 7
- •Часть II. Задачи. Алгоритмизация и программирование 15
- •Часть III. Теоретические положения и примеры программ 188
- •Введение
- •Часть I. Этапы решения задачи на компьютере
- •1.1 Постановка и формализация условий задачи
- •1.2 Алгоритмизация задачи
- •1.2.1 Интерпретация объектов
- •1.2.2 Вычислительная схема
- •1.2.3 Вычислительная схема решаемой задачи
- •1.2.4 Составление блок-схемы
- •1.2.5 Трассировка
- •1.3 Составление программы на языке Паскаль
- •1.4 Подготовка текста программы на машинном носителе
- •1.5 Трансляция (компиляция) программы
- •1.6 Компоновка (редактирование связей)
- •1.7 Запуск программы на исполнение
- •1.8 Анализ результатов
- •Часть II. Задачи. Алгоритмизация и программирование классических вычислительных процессов
- •1 Линейный вычислительный процесс
- •1.1 Программирование формул
- •1.2 Формализация и алгоритмизация задачи
- •2 Разветвляющийся вычислительный процесс
- •2.1 Программирование формул
- •2.2 Формализация и алгоритмизация графических задач
- •2 .3 Параметрические задачи
- •3 Циклические вычислительные процессы
- •3.1 Арифметический цикл
- •Вычисление произведения n сомножителей.
- •Табулирование функции на конечном отрезке.
- •3.2 Итерационный цикл
- •Вычисление предела последовательности с заданной точностью.
- •Вычисление суммы бесконечного ряда с заданной точностью.
- •3.3 Арифметические циклы с рекуррентными соотношениями
- •3.4 Итерационные циклы с рекуррентными соотношениями
- •3.5 Двойной вложенный цикл
- •4. Пользовательские алгебраические функции
- •4.1 Применение функции в линейных и разветвляющихся вычислительных процессах
- •4.2 Использование функции в циклических процессах
- •4.3 Табуляция функции
- •5 Одномерные числовые массивы
- •5.1 Работа с компонентами массива
- •5.2 Работа с векторами
- •6 Двумерные числовые массивы
- •6.1 Работа с элементами массива
- •6.2 Работа с векторами и матрицами
- •6.3 Использование процедур и функций для работы с массивами
- •7 Работа со строками
- •7.1 Анализ и преобразование текста строки
- •7.2 Работа со строковыми функциями и процедурами
- •8 Работа со списками
- •8.1 Стеки
- •8.2 Очереди
- •8.3 Бинарные деревья
- •9 Работа с текстовыми файлами
- •10 Работа с файлами записей
- •11 Компьютерная графика
- •12 Анимация изображений
- •Часть III. Теоретические положения и примеры программ
- •1 Вычисление определителя квадратной матрицы
- •2.2 Использование записей для описания таблиц
- •Работа с полями записи
- •Использование оператора with … do
- •Ввод данных в массив записей с клавиатуры
- •2.3 Вложение записей
- •Присвоение значений полям вложенных записей
- •3 Файлы записей
- •3.1 Структура файла
- •3.2 Встроенные процедуры и функции обработки файлов
- •3.3 Организация последовательного доступа к записям файла
- •3.4 Организация прямого доступа к компонентам файла
- •3.5 Создание индексного файла
- •3.6 Работа с файлом произвольного доступа
- •Просмотр файла
- •Редактирование записей
- •Изменение структуры основного файла
- •Использование клавиш для управления программой
- •Удаление записи из файла
- •Добавление записи в файл
- •3.7 Информационное взаимодействие текстовых файлов и файлов записей
- •Экспорт данных. Копирование информации из файла записей в текстовый файл
- •Импорт данных. Копирование информации из текстового файла в файл записей
- •3.8 Запросы к файлам записей
- •Запрос с группировкой
- •4 Графическое программирование
- •4.1 Управление видеорежимом
- •Инициализация видеорежима. Процедура InitGraph
- •Закрытие видеорежима. Процедура CloseGraph
- •Создание графического окна. Процедура SetViewPort
- •Закрытие графического окна. Процедура ClearDevice
- •4.2 Построение графических фигур
- •Построение прямой линии. Процедуры SetColor, SetLineStyle, Line, LineRel, LineTo
- •Построение прямоугольника. Процедуры Rectangle и Bar
- •Построение окружности. Процедура Circle
- •Построение дуги окружности. Процедура Arc
- •Построение эллипса. Процедуры Ellipse, FillEllipse
- •Построение сектора. Процедуры PieSlice, Sector
- •4.3 Корректировка изображения Процедуры GetAspectRatio, SetAspectRatio
- •4.4 Создание пользовательского шаблона заливки
- •Заливка замкнутой области. Процедура FloodFill
- •Построение и окраска произвольного рисунка на примере замка
- •Построение и заливка правильного многоугольника
- •4.5 Работа с текстом
- •Выбор стандартного шрифта. Процедура SetTextStyle
- •Коррекция стандартного шрифта. Процедура SetUserCharSize
- •Вывод числовых величин на экран
- •5 Анимация изображений
- •5.1 Дублирования спрайта цветом фона
- •5.2 Манипулирование фрагментами изображения
- •5.3 Использование страниц видеопамяти
- •6 Сообщения об ошибках
- •6.1 Ошибки стадии компиляции
- •6.2 Ошибки стадии выполнения
- •Ошибки ввода-вывода
- •Фатальные ошибки
- •Библиографический список
5 Анимация изображений
Программы, которые строят, перемещают, изменяют форму различных изображений на экране в соответствии с заранее разработанным сценарием, называются анимационными. Хорошо продуманный, увязанный с возможностями ПК (характеристиками адаптера монитора, быстродействием, наличием и объемом внешних носителей) сценарий - основа любой анимационной программы. Анимационные программы, как правило, требуют применения довольно сложных алгоритмов и часто используют большой объем данных. Данные, на основании которых осуществляется движение логически выделенных (например, сюжетом игры) фигур или их фрагментов. Для "оживления" графических рисунков используют самые различные ухищрения, некоторые из них будут рассмотрены в данном параграфе.
Анимационные программы работают с двумя классами объектов: спрайтами и средой. Спрайтом называют логически законченный движущийся элемент изображения на экране. Среда - это фон, по которому происходит движение спрайта. Существует много различных способов заставить спрайт двигаться. Все они подразделяются на две группы: комбинационные и морфологические.
В основе комбинационных методов лежат различные модификации следующего алгоритма: вывести вариант спрайта на экран; стереть спрайт; вывести с некоторым перемещением другой вариант спрайта и т.д. Программа в соответствии с алгоритмом выводит варианты спрайта, как бы перемещая по экрану. Так как этот процесс происходит быстро, то для инерционного человеческого глаза создается полная иллюзия непрерывного движения.
Морфологические методы анимации манипулируют спрайтами на основе выполнения одного или нескольких правил. Наиболее эффективно они реализуются средствами объектно-ориентированного программирования, поэтому в рамках этой книги мы их рассматривать не будем.
5.1 Дублирования спрайта цветом фона
Самый простой метод анимации заключается в следующем. На экране формируется постоянная картинка (фон). Затем в том месте где фон однороден выводится спрайт любым цветом, отличным от цвета фона. Через определенный период времени спрайт или его часть формируется цветом, совпадающим с фоном, что вызывает эффект "исчезновение изображения" (фрагмента). Затем спрайт или его часть выводится в другом месте тем же цветом, что и первый, и т.д.
В качестве первого примера использования этого метода рассмотрим простейшую анимационную программу, которая создает на черном фоне имитирующем межмолекулярное пространство спрайт, изображающий атом.
Пример 27. Составить программу для вывода в центре экрана монитора атома в виде ярко голубого ядра и двух эллиптических орбит, меняющих свое положение во времени (см. рис. 3.17).
Рис. 3.17 Атом - ядро и орбиты двух электронов
Алгоритм программы:
Перевести монитор в графический режим.
Найти координаты центра экрана X и Y.
Найти величины xasp и yasp для корректировки изображения.
В цикле строить ядро и две орбиты атома (см. процедуру ORBIT). Выход из цикла при нажатии любой клавиши.
Program PR27;
Uses CRT, GRAPH;
Const RA=12; CA=11; {Радиус и цвет ядра атома}
Var n, r, X, Y : integer;
drivervar, modevar: integer;
xasp, yasp : word;
Procedure ORBIT(C: INTEGER);
Begin
setcolor (CA); {РИСУЕМ (ВОССТАНАВЛИВАЕМ) ЯДРО}
circle (X, Y, RA);
SetFillStyle(11, CA); FloodFill(X, Y, CA);
setcolor (C); {РИСУЕМ ОРБИТЫ ЗАДАННЫМ ЦВЕТОМ}
ellipse (X,Y,0,360,r,100*round(xasp) div yasp);
ellipse (X,Y,0,360,100,r*round(xasp) div yasp);
delay(200); {ВРЕМЕННАЯ ЗАДЕРЖКА ДЛЯ ФИКСАЦИИ ПОЛОЖЕНИЯ ОРБИТ}
setcolor (black); {Рисуем орбиты цветом фона}
ellipse (X,Y,0,360,r,100*round(xasp) div yasp);
ellipse (X,Y,0,360,100,r*round(xasp) div yasp)
End;
Begin
drivervar := detect;
initgraph (drivervar, modevar, 'd:\tp\bgi');
X:=GetMaxX div 2; Y:=GetMaxY div 2; {ВЫЧИСЛЕНИЕ КООРДИНАТ ЦЕНТРА}
getaspectratio(xasp, yasp);
r:=0; setbkcolor(black); cleardevice;
while not keypressed {ДЕЛАЕМ ДО НАЖАТИЯ ЛЮБОЙ КЛАВИШИ}
do begin
for n:=0 to 50
do Begin
ORBIT(15); {БЕЛЫЕ ОРБИТЫ ЭЛЕКТРОНОВ}
r:=r+2 {ЭЛЛИПС ОРБИТ РАСШИРЯЕТСЯ}
End;
for n:=50 downto 0
do Begin
r:=r-2; {ЭЛЛИПС ОРБИТ СУЖАЕТСЯ}
ORBIT(14) {ЖЕЛТЫЕ ОРБИТЫ ЭЛЕКТРОНОВ}
End
End;
CloseGraph {ЗАКРЫТИЕ ГРАФИЧЕСКОГО ВИДЕОРЕЖИМА}
End.
В качестве второго примера иллюстрирующего рассматриваемый метод возьмем известную демонстрационную программу, получившую ласковое название – “Спиралька”.
Пример 28. Заставка с щадящим режимом работы монитора. По черному экрану монитора по восьмеркам относительно центра перемещается спираль, меняющая размеры и цвет во времени (см. фрагмент на рис. 3.18).
Рис. 3.18 Полет пружинки
Program PR28;
Uses Graph, CRT;
CONST R1=200; KOL=30;
VAR
X, Y, R: ARRAY [1..KOL] OF INTEGER;
N,V,M,X1,Y1,I,J: INTEGER;
A, B: REAL;
Procedure GrInit; {ИНИЦИАЛИЗАЦИЯ РЕЖИМА ГРАФИКИ}
Var GraphDriver: Integer; {ДЛЯ ГРАФИЧЕСКОГО АДАПТЕРА}
GraphMode : Integer; {ДЛЯ ГРАФИЧЕСКОГО РЕЖИМА}
ErrorCode : Integer; {ДЛЯ КОДА ОШИБКИ}
Begin
GraphDriver:= Detect; {РЕЖИМ АВТО ОПРЕДЕЛЕНИЯ}
InitGraph(GraphDriver, GraphMode, 'D:\tp\bgi'); {ИНИЦИАЛИЗАЦИЯ}
End;
Begin GrInit;
FOR I:=1 TO KOL DO BEGIN X[I]:=0 ; Y[I]:=0 ; R[I]:=0 END;
SETFILLSTYLE(1,0); BAR(1,1,640,480); A:=1 ;
REPEAT
V := RANDOM(4)+0;
FOR M := 1 TO 10
DO BEGIN
R[1]:= TRUNC(40*COS(1.0*A*PI/180)); {РАДИУС КОЛЬЦА}
X[1]:= TRUNC(R1*COS(1.5*A*PI/180/1))+300; {Координата центра X}
Y[1]:= TRUNC(R1*SIN(1.0*A*PI/180/1))+250; {Координата центра Y}
FOR J:=2 TO KOL {РИСУЕМ КОЛЬЦА}
DO BEGIN
I:=KOL-J+2; X[I]:=X[I-1]; Y[I]:=Y[I-1]; R[I]:=R[I-1];
SetColor(I DIV 5 +8); {МЕНЯЕМ ЦВЕТ КОЛЕЦ}
ELLIPSE(X[I],Y[I],0,360,60+0*R[I],60+R[I]);
if keypressed then Exit
END;
SetColor(0); {ПОВТОРНО РИСУЕМ КОЛЬЦА ЦВЕТОМ ФОНА}
ELLIPSE(X[KOL],Y[KOL],0,360,60+0*R[KOL],60+R[KOL]);
A := A + V
END
UNTIL KEYPRESSED {НАЖАТИЕ ЛЮБОЙ КЛАВИШИ - КОНЕЦ ПРОГРАММЫ}
END.
В качестве третьего примера иллюстрирующего рассматриваемый метод возьмем программу изображающую зимний пейзаж. Падающий снег, сугробы и заснеженный домик в ночи.
Пример 29. Смоделировать падение 500 снежинок на землю и крышу дома (см. рис. 3.19).
Рис. 3.19 Заснеженный домик
Ниже приведен код программы. Положение снежинок фиксируется с помощью их координат, хранимых в одномерных массивах x[i] и y[i].
Program PR29; {BOBKOV ANDREW, ГРУППА ИС-11}
uses crt, graph;
const N=500; {ЧИСЛО СНЕЖИНОК}
var key: char;
GrDriver, GrMode: integer;
i,x1,y1:integer;
st: boolean;
x, y: array[1..n] of integer;
procedure DOM;
begin
setColor(8); setFillStyle(11,8); SetLineStyle(0,3,3);
line(200,250,200,298); line(210,250,210,285); {ТРУБА}
line(210,250,205,245); line(200,250,205,245);
SetColor(6); SetLineStyle(0,3,3); SetFillStyle(2,15);
Bar(200, 300, 400, 480); {Стены домика}
line(180,315,300,200); line(420,315,300,200); {СКАТЫ КРЫШИ}
SetFillStyle(8,14); Bar(265,400,330,350); {ОКНО ДОМА}
SetColor(12); circle(300,250,10); {ЧЕРДАЧНОЕ ОКНО}
SetColor(7);
rectangle(-2,-2,GetMaxX+2,GetMaxY) {РАМКА, ВИДНА КАК ЗЕМЛЯ}
end;
begin
initGraph(GrDriver,GrMode,'d:\tp\bgi');
DOM; {Построение домика}
randomize;
for i:= 1 to n {ГЕНЕРАЦИЯ КООРДИНАТ 500 СНЕЖИНОК}
do begin
X[i]:=random(GetMaxX); Y[i]:=random(GetMaxY);
end;
repeat {Имитация падающего снега. Бесконечный цикл}
for i:= 1 to n {ДЛЯ КАЖДОЙ ИЗ 500 СНЕЖИНОК ДЕЛАЕМ}
do begin
if y[i]<GetMaxY
then begin {ОПРЕДЕЛЕНИЕ НОВЫХ КООРДИНАТ СНЕЖИНКИ}
st:=false; x1:=x[i]; y1:=y[i];
if getPixel(x[i],y[i]+1)=0
then begin inc(Y[i],1) end
else begin
if GetPixel(x[i]+1,y[i]+1)=0
then begin inc(x[i]); inc(y[i]) end
else begin
if GetPixel(x[i]-1,y[i]+1)=0
then begin dec(x[i]); inc(y[i]) end
else begin {ПОЯВЛЕНИЕ НОВОЙ СНЕЖИНКИ}
x[i]:=random(GetMaxX); y[i]:=0; st:= true
end
end
end;
if not st then PutPixel(x1,y1,0); {Стираем снежинку}
PutPixel(x[i],y[i],15) {Отображаем снежинку на новом
месте}
End
else begin PutPixel(x[i],y[i],15);
y[i]:=0; x[i]:=random(GetMaxX) {Появление новой
Снежинки}
end
end;
until KeyPressed;
setbkcolor(3); {Утро}
setfillstyle(1,14); FillEllipse(100,100,40,40); {СОЛНЦЕ}
repeat {Имитация таяния снега}
for i:= 1 to n
do begin
if y[i]<GetMaxY
then begin
st:= false; x1:=x[i]; y1:=y[i];
if GetPixel(x[i],y[i]+1)=0 then begin inc(Y[i],1) end
else begin
if GetPixel(x[i],y[i]+1)=15
then begin inc(y[i],1);
PutPixel(x[i],y[i],0); y[i]:=0;
x[i]:=random(GetMaxX)
end
else if GetPixel(x[i]+1,y[i]+1)=15
then begin
inc(x[i]);inc(y[i]);PutPixel(x[i],y[i],0);
x[i]:=random(GetMaxX); y[i]:=0
end
else if GetPixel(x[i]-1,y[i]+1)=15
then begin
dec(x[i]); inc(y[i]);
PutPixel(x[i],y[i],0);
x[i]:=random(GetMaxX); y[i]:=0
end
else begin PutPixel(x[i],y[i],0);
x[i]:=random(GetMaxX); y[i]:=0
end
end
end
else begin x[i]:=random(GetMaxX); y[i]:=0 end
end
until KeyPressed;
CloseGraph
end.