6.7. Использование циклов для придания интерфейсу программ динамических функций
Динамические функции интерфейса задают ему дополнительные свойства, которые изменяются по времени – например, периодическое изменение цвета, перемещение по экрану элементов информационного сообщения, выдача переменных звуковых сигналов и т.д.
Рассмотрим их реализацию при помощи операторов ввода (read, readln) и вывода (write, writeln) самого языка Паскаль, а также подпрограмм из его стандартной библиотеки CRT.
Поскольку динамические свойства интерфейса предусматривают периодическое повторение сходных действий, то для их реализации необходимо использовать циклы – как арифметические, так и итерационные.
Для того, чтобы пользователь успел проанализировать динамическое изменение изображения на экране, в тело цикла необходимо включать процедуру delay(ms), задающую паузу в работе программы на ms миллисекунд. За счет изменения времени паузы движение можно задавать неравномерным.
При задании перемещений элементам текстового интерфейса необходимо учитывать, что координаты знакомест символов на текстовом экране ограничены размерами [1:80] по горизонтали и [1:25] по вертикали. Необходимо расчетным путем прогнозировать контакт с границей экрана либо вставлять соответствующие проверки. Законы перемещения можно выбирать равномерные, неравномерные (с возрастанием времени паузы - замедление движения, с сокращением паузы - ускорение). Также можно задавать перемещения случайным образом.
Рассмотрим решение типовых задач изменения цвета и перемещения элементов вывода по текстовому экрану монитора.
Пример 1. Разработать программу, реализующую перемещение произвольной строковой переменной (слова) Str вдоль первой строки текстового поля экрана монитора слева направо с возрастающей скоростью (начальное время задержки 200 мс, на каждом шаге убывает на 5, но не должно быть меньшим 5 мс). При достижении границы экрана перемещение слова заканчивается и программа завершает свою работу.
Решение. Введем дополнительно целочисленную переменную LPass для задания числа пробелов в первой строке перед выводом слова. Применяя функцию Length для определения длины строковой переменной Str, получим следующий код:
program move_word_left_right;
uses Crt;
var N,i,LPass:integer;Str:string;
begin {открытие тела программы}
ClrScr; writeln('Vvedite slovo');{начальная очистка экрана, запрос на ввод слова Str }
Readln (Str); N:= Length(Str); { ввод слова Str и определение его длины N }
LPass:=1; i:=200;{задание начальных значений величин LPass, i}
while(N+LPass)<=80 do{проверка окончания цикла - умещается ли пропуск и слово в строке}
begin
ClrScr;GotoXY(LPass,1);writeln(Str);{очистка экрана, подвод курсора, вывод слова}
LPass:= LPass+1; {наращивание длины пропуска в начале строки}
i:=i-5; if i<5 then i:=5; {коррекция времени}
Delay(i) { задержка на i миллисекунд }
end;
ReadKey; {ожидание нажатия клавиши для перехода от пользовательского экрана в основной}
end. {конец раздела операторов и всей программы}
Пример 2. Разработать программу, реализующую перемещение заданного символа S со знакоместа с координатами (N,M) вниз с возрастающей скоростью (начальное время задержки 250 мс, на каждом шаге убывает на 10, но не должно быть меньшим 20 мс). При достижении нижней границы экрана перемещение символа заканчивается и программа завершает свою работу.
Решение. Перемещение символа обеспечивается тем, что на каждой итерации содержимое экрана очищается, а затем курсор подводится к новому месту вывода, сдвинутому на одну строку вниз, после чего символ выводится на экран. Код программы дан с необходимыми комментариями:
program move_symbol_up;
uses Crt;
var N,M,i:integer; S:char;
begin {открытие тела программы}
ClrScr; writeln('Vvedite symbol');{начальная очистка экрана и запрос на ввод символа S}
Read (S); { ввод символа S}
writeln('Vvedite symbol enter coordinates N (1-25),M (1-80)');{запрос на ввод начальных координат символа S}
Read (N,M); { ввод N,M – начальных координат символа S}
i:=250; { задание начального значения длины ожидания в мксек}
while(N)<=25 do{проверка оконч. цикла - умещается ли вставляемая строка в экран}
begin
ClrScr;GotoXY(M,N);write(S); {очистка экрана, подвод курсора, вывод символа S }
N:=N+1; {наращивание пропуска строк на единицу}
i:=i-10; if i<20 then i:=20; {коррекция времени ожидания}
Delay(i) {задержка на i миллисекунд }
end;
ReadKey; {ожидание нажатия клавиши для перехода от пользовательского экрана в основной}
end. {конец раздела операторов и всей программы}
Пример 3. Разработать программу, в которой вводится строковая величина (слово) Str. Затем должно происходить циклическое изменение цвета символов (в соответствии с таблицей цветов библиотеки CRT) в слове Str и его печать в новой строке. Всего должно произойти 50 смен цвета. Время задержки перед каждым изменением цвета задать равным 200 мс.
Решение. Для численного обозначения цвета введем целую переменную. Ее величину в каждой итерации цикла наращиваем на 1. Если она превышает 15, уменьшаем ее на 16. Код программы с необходимыми комментариями:
program word_var_color;
uses Crt;
var i,Clr:integer; Str: string;
begin {открытие тела программы}
ClrScr; writeln('Vvedite slovo');{начальная очистка экрана, запрос на ввод слова Str }
Read (Str); { ввод слова Str}
Clr:=-1; {задание начального номера цвета}
for i:=1 to 50 do{цикл, в котором изменяется цвет и выводится заданное слово}
begin
Clr:=Clr+1; {наращивание номера цвета на единицу }
if Clr>15 then Clr:=Clr-16;{проверка и необходимая коррекция номера цвета }
TextColor(Clr); {задание номера цвета буквам}
writeln(Str); {вывод слова в следующей строке }
Delay(200) { задержка на 200 миллисекунд }
end;
ReadKey; {ожидание нажатия клавиши для перехода от пользовательского экрана в основной}
end. {конец раздела операторов и всей программы}
Начиная с версии 2.4.2. , Free Pascal наряду с обычными циклами Паскаля поддерживает цикл вида For...in, в котором переменной цикла принимает в порядке возрастания все возможные значения из заданного порядкового типа. Этот вид циклов рассмотрен в Главе 9.
Вопросы для проверки знаний.
1. Чем динамические функции интерфейса отличаются от статических ?
2. Для чего в тело цикла, выполняющего изменение элементов интерфейса необходимо включать процедуру delay ?
3. Каким образом обеспечивается равномерное и неравномерное изменение свойств элементов интерфейса ?
4. Какие геометрические ограничения накладывает перемещение элементов интерфейса по экрану ?
Практическое задание.
1. Разработать программу, реализующую перемещение заданного символа S с произвольного знакоместа экрана с координатами (N,M) в диагональном направлении (вниз и вправо с возрастающей скоростью). При достижении правой или нижней границы экрана перемещение символа заканчивается и программа завершает свою работу.
