Задача: На экране в случайных точках появляются звезды, и в обратном порядке гаснут.
Итак, задание есть. Теперь давайте подумаем, каким образом будем выполнять нашу программу и что для этого понадобиться. В первую очередь обратим внимание на самые главные вещи. Что у нас главное? Точки. Ведь именно они и будут основным объектом работы программы, не так ли? Значит из этого и будем исходить: как нам реализовать появление точек на экране. Продолжаем.
Вы уже знаете, что экран в ДОС разбит на строки и столбцы, причем все они имеют номера. Переход к требуемым координатам экрана осуществляется процедурой GotoXY из модуля Crt. Отсюда ясно, что каждая точка будет иметь две координаты, которые будет получать случайным образом. Но точка у нас будет не одна, а скажем, 20. Вот и получается, что:
20 точек * 2 координаты = 40 переменных
40 переменных не так уж и мало для раздела var, верно? Кроме того, это очень неудобно. Допустим, вы захотели изменить количество точек с 20-ти на 15. Придется стирать лишние переменные. Захотели увеличить с 15-ти до 30-ти: дописывать недостающие.
Вот здесь мы и подходим к необходимости использования массивов. Подумайте, не легче ли будет завести массив, каждый элемент которого - это координата точки? Определенно легче и удобней. Теперь описание двадцати переменных сведется к следующему:
Var
X: Array[1..20] of Byte;
Y: Array[1..20] of Byte;
Как вы видите, массивов два. Один - для хранения номера столбца (X), другой - строки (Y). В обоих массивах используется тип Byte, так как он самый подходящий для хранения координат экрана в текстовом режиме (80х25).
Но на этом подготовка к написанию программы не заканчивается и мы идем дальше. Давайте теперь задумаемся над тем, как же нам быстро изменять количество точек? Массивы заведены, как вы видите на 20 элементов. Кроме того, в самой программе придется обрабатывать эти массивы в цикле, который мы тоже будем делать до 20. Как же можно сделать так, чтобы и размер массивов и диапазон цикла изменялись всего лишь одним числом? Это вечная проблема оптимизации, у которой, к счастью, есть решение. Помните, я показывал предопределение переменных прямо в разделе const? Этим мы и воспользуемся. Модифицируем приведенный пример:
Const
n = 20;
Var
X: Array[1..n] of Byte;
Y: Array[1..n] of Byte;
Теперь изменение размера обоих массивов - это всего лишь редактирование значения единственной переменной. Но это не все достоинства данного метода. Вышеупомянутые циклы, которые будут проходить по массивам, тоже становяться максимально оптимизированными. Вот пример:
Const
n = 20;
....
For I := 1 to n do
....
Посмотрите внимательно. Видите, при изменении значения одной переменной меняется обработка данных всей программы? Это важно. Я специально подробно останавился на этом, чтобы вы поняли до конца принцип оптимизации программы. Очень часто и очень многие недооценивают это. Не забывайте предопределять такие вещи :)
Двигаясь дальше замечаем, что все необходимое для управления точками на экране у нас есть. Теперь остаются такие незначительные данные как переменные для циклов и т.п., их все вы определяйте по ходу написания программы. Можно разбираться, как писать саму программу.
Начнем. Перечислю необходимые задачи для написания программы:
Решить, как будут изображатсья звезды;
Разобраться, каким образом будет производиться вывод их в соотв. координаты;
Составить основной цикл программы;
Здесь я немного собьюсь с плана и оговорюсь о последнем пункте. Основной цикл программы - это ее работа до возникновения определенных условий. Здесь подумайте и сделайте такой цикл, чтобы все действия заключались внутри него, а само условие цилка контролировало действия пользователя на выход (или что там еще придумаете). Решайте сами, какой цикл вам лучше взять.
Ну а теперь по порядку. В первую очередь будем разбираться с самим изображением звезд. Давайте опрелимся, какими символами они будут изображаться и как они будут исчезать. У нас зведочки будут максимально приближены к Norton'овским, т.е. будут расти из точки до звезды, после чего гаснуть. Будет происходить это так:
Сначала выводиться точка - '.'
После выводиться звездочка - '*'
И напоследок выводиться большая здезда - (к сожалению, в Windows (в частности, в HTML документе) нельзя отобразить таковую).
Теперь она будет исчезать - будет выводиться пробел, которым затреться изображение звезды.
"" таким образом у нас получиться анимация.
С первыми двумя, равно как и с исчезанием - все ясно. Выводим символы процедурой Write и все дела. Но как вывести большую звезду? Дело в том, что с этим символом вы, возможно, и не знакомы. Чтобы понять, про что я говорю, откройте документ в Turbo Pascal (под DOS) и напечатайте что-нибудь (просто внесите в него изменения). Теперь посмотрите в левый нижний угол экрана, где указана пара чисел СТРОКА:СИМВОЛ. Видите, перед ней стоит звездочка, которая означает, что файл был изменен? Она не является той, которая расположена на клавиатуре на цифре "8" и на доп. разделе под огоньками "NumLock" и т.п. Она несколько больше, причем отсутсвует на клавиатуре, но существует во внутреннем наборе символов операционной системы.
Я не хочу сейчас рассказывать про само понятие набора символов (и связанные с этим темы - кодировки ANSI, ASCII и т.п.) - это немного не к месту, лучше я посвящу им отдельную статью. Пока скажу только, что помимо символов клавиатуры есть еще и другие, которые нельзя набрать, но можно вывести на экран с помощью программы. Это, к примеру, символы рамки, из которой составлено тоже окно редактора TP, Norton Commander и т.д, наш с вами символ звезды и многие другие.
Все они имеют порядковый номер, по которому и осуществляется их вывод. К примеру, столь необходимый нам символ большой звезды имеет номер 15. Чтобы получить символ с требующимся номером, служит фукнция:
Chr(Num: Byte): Char;
В качестве ее параметра задается сам номер символа, а от своей работы она возвращает этот символ, причем типа Char, которого она и является. Вот пока и все, что вам нужно знать, чтобы суметь напечатать звезду:
Write(Chr(15));
Как видите, я использую Chr прямо в процедуре Write. Помните, это функция, которая возвращает от своей работы определенное значение. А мы можем его использовать так, как нам захочеться, в том числе и выводить на экран.
Итак, задача отображения звезд тоже решена. Теперь надо заняться вопросом вывода этих здезд в определенное место экрана, координаты которого задаются нашими массивами. Здесь много вариантов! Однако я останавливаюсь... Вот это и есть задача для вас! Я довольно много рассказал, провел через непонятные или неочевидные вещи, ну а решать саму задачу советую самостоятельно. Это совсем несложно.
Когда вы ее сделаете (или не сделаете :) - можете посмотреть готовый вариант на сайте рассылки (http://prog.agava.ru), как я уже говорил, в новом разделе Уроки для начинающих программистов >> Исходные тексты.
В этом исходнике как раз и реализуются предложенные алгоритмы и приемы работы.