Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Solomon.doc
Скачиваний:
17
Добавлен:
08.05.2019
Размер:
3.38 Mб
Скачать

Глава 8. Использование окон, графики, звука.

Введение

По традиции, все программные продукты фирмы Borland

International обладают первоклассными средствами для использо-

вания окон, графики и звука. Система программирования Тур-

бо-Пролог не является исключением. При помощи Турбо-Пролога

можно создать несколько окон, используя предоставляемые цвето-

вые палитры, установить цвет текста и цвет фона, изменить раз-

меры окон, переключить ввод и вывод с одного окна на другое.

Средства языка поддерживают Цветной Графический Адаптер и Рас-

ширенный Графический Адаптер, обеспечивая тем самым возможность

работать в различных графических режимах. Программа, используя

звуковые средства Турбо-Пролога, способна производить музыкаль-

ные тоны в широком диапазоне частот, управляя продолжитель-

ностью их звучания.

Программы, рассматриваемые до сих пор, осуществляли ввод и

вывод через окно, причем только текстовых строк. В этой главе

будет описано, как использовать в программах другие средства

Турбо-Пролога: многооконность, звук и графику.

Графика в системе программирования Турбо-Пролог в основном

реализуется предикатами dot и line. С помощью зтих предикатов

на экран дисплея выводятся изображения, состоящие из геометри-

ческих фигур. В данной главе будет показано, как использовать

предикаты line и dot, чтобы создать фигуры различной сложности.

Описываемые средства будут использованы для вычерчивания линей-

ных диаграмм *1), столбиковых диаграмм и круговых диаграмм.

Графику "черепашки" *2) поддерживают эти же средства. Это

позволяет использовать в программе обычную графику и графику

"черепашки" одновременно.

Турбо-Пролог располагает двумя предикатами для управления

звуком: sound и beep. При их описании будут изложены основные

концепции, касающиеся высоты и длительности звука, используемые

при построении музыкальных фрагментов.

----------------------------------------------------------------

1) Имеются в виду графики кусочно-линейных функций. -

- Прим.ред.

2) Turtle graphics (графика черепашки) - это образное наз-

вание графики, связанной с положением курсора - графики, ис-

пользующей только относительные команды. - Прим.ред.

----------------------------------------------------------------

Изучив материал данной главы, Вы сможете "оживить"

свои программы на Турбо-Прологе, используя многооконность, ин-

формативную графику и музыку.

8.1. Использование предикатов для работы с окнами

В систему программирования Турбо-Пролог включено пять пре-

дикатов, позволяющих программе управлять окнами различных раз-

меров. Это предикаты makewindow, shiftwindow, removewindow,

clearwindow и gotowindow. С их помощью можно создавать несколь-

ко окон, выполнять ввод и вывод в определенные окна и устанав-

ливать атрибуты окон.

8.1.1. Создание окон предикатом makewindow

Предикат makewindow является основой всех операций над ок-

нами в Турбо-Прологе. Его синтаксическая форма:

makewindow(Window_number,

Screen_attribute,

Frame_attribute,

Frame_string,

Starting_row,

Starting_column,

Window_height,

Window_width)

Значения восьми параметров определяют характеристики окна.

Параметр Window_number, целое число, идентифицирует окно в

программе. Это число используется в качестве ссылки предикатом

gotowindow и др.

Целочисленное значение, присвоенное аргументу

Screen_attribute, определяет цвета символов и фона. Выбираемые

значения атрибута зависят от того, какой монитор используется-

цветной или монохромный.

Вычисление значения screen_attribute для монохромного экрана

Целочисленные значения screen_attribute задают

комбинацию цветов текста и фона.

Для монохромных мониторов эти значения приведены в табл. 8.1.

---------------------------------------------------------------

Таблица 8.1. Значения атрибута экрана для монохромных мониторов.

---------------------------------------------------------------

Цвет текста Цвет фона Screen_attribute Примечание

---------------------------------------------------------------

Черный Черный 0 Пустой экран

Белый Черный 7 Позитивное изображение

Черный Белый 112 Негативное изображение

Названия "белый" и "черный" весьма условны. Так, под сло-

вом "белый" подразумевают цвет, которым набран текст на монито-

ре, и в действительности он либо серый либо желтый. Заметим,

что сочетание черного цвета текста с черным фоном дает пустой

экран. Белый текст на черном фоне получается на дисплее с пози-

тивным изображением, а черный текст на белом фоне - на дисплее

с негативным изображением.

На ряду с указанным существуют три необязательных атрибу-

та, задание которых определяет вывод символов с подчеркиванием,

изображение с высоким разрешением и вывод мерцающих символов.

Вывод символов с подчеркиванием реализуется, если к значению

аргумента screen_attribute добавить 1. Для получения изображе-

ния с высоким разрешением, нужно к основному значению атрибута

экрана добавить 8. Символы будут мерцающими,если к значению ат-

рибута экрана добавить 128.

Предположим, например, что имеется монохромный монитор и

вы хотите создать окно с позитивным изображением. В таком слу-

чае, значение аргумента Screen_attribute равно 7. При этом,

чтобы получить символы с подчеркиванием, нужно к 7 добавить 1

(результат 8). Для получения изображения с высоким разрешением

нужно к значению атрибута 7 добавить 8 (результат 15). И, нако-

нец, если вы хотите сделать символы мерцающими, к значению ат-

рибута 7 добавьте 128 (результат будет 135).

Вычисление значения screen_attribute для цветного экрана

Значения атрибутов экрана для цветного графического адап-

тера приведены в табл. 8.2 и 8.3.

---------------------------------------------------------------

Таблица 8.2. Соответствие между значением атрибута и

цветом текста для окон Турбо-Пролога

---------------------------------------------------------------

Цвет текста Значение атрибута

---------------------------------------------------------------

Черный 0

Синий 1

Зеленый 2

Голубой 3

Красный 4

Фиолетовый 5

Коричневый 6

Белый 7

Серый 8

Светло-синий 9

Светло-зеленый 10

Светло-голубой 11

Светло-красный 12

Светло-фиолетовый 13

Желтый 14

Интенсивно-белый 15

---------------------------------------------------------------

---------------------------------------------------------------

Таблица 8.3. Соответствие между значением атрибута и

цветом фона для окон Турбо-Пролога

---------------------------------------------------------------

Цвет фона Значение атрибута

---------------------------------------------------------------

Черный 0

Синий 16

Зеленый 32

Голубой 48

Красный 64

Фиолетовый 80

Коричневый 96

Белый 112

---------------------------------------------------------------

Чтобы вычислить значение screen_attribute для различных

комбинаций цветов, прежде всего выберите необходимый цвет текс-

та и цвет фона. Затем сложите соответствующие значения атрибу-

тов. Если вы хотите, чтобы символы мерцали, прибавьте к резуль-

тирующему значению 128. Вычисленное значение используется как

второй аргумент в предикате makewindow, т.е. screen_attribute.

Например, чтобы создать окно с белыми символами на черном

фоне, сложите 7 (белый текст) и 0 (черный фон).Их сумма 7 явля-

ется значением аргумента Screen_attribute для предиката

makewindow. Чтобы создать окно с красными символами на желтом

фоне, сложите 4 (красный текст) и 104 (желтый фон), результат

будет 108. Чтобы создать окно с синими символами на бледно

красном фоне, сложите 1 (синий текст) и 12 (бледно красный

фон). Их сумма - 41, используется как второй аргумент рассмат-

риваемого предиката.

Выбор рамки окна

Аргумент Frame_attribute предиката makewindow есть целое

число, значение которого определяет рамку окна. Если значение

атрибута - 0, окно не имеет видимой границы. Другие значения

определяют рамку окна с параметрами, указанными в табл. 8.4.

Часть значений атрибута рамки окна задает ее цвет. Это де-

лается аналогично заданию значения атрибута экрана. Если зада-

ется мерцающая граница, то она всегда будет белой, с мерцающей

тонкой линией (в середине границы), имеющей указанный цвет.

Аргумент Frame_string задает метку окна. Например, меткой

окна может быть "Главное Меню","Столбиковая Диаграмма","Вспомо-

гательное Меню" и "Окно Вывода". Строка, задаваемая в качестве

атрибута frame-string будет размещена в центре верхней линии

рамки окна. Значение метки окна также может быть не определено,

что соответствует отсутствию метки. В этом случае вводится ар-

гумент, состоящий из двух последовательных знаков кавычки.

---------------------------------------------------------------

Таблица 8.4. Значение атрибута, определяющего цвет

рамки окна в Турбо-Прологе

---------------------------------------------------------------

Значение атрибута Вид рамки окна

---------------------------------------------------------------

0 Нет рамки

1 Синяя рамка

2 Зеленая рамка

3 Светло-синяя рамка

4 Красная рамка

5 Фиолетовая рамка

6 Желтая рамка

7 Белая рамка

8 Коричневая рамка

-1 Мерцающая белая рамка

-2 Мерцающая желтая рамка

-3 Мерцающая фиолетовая рамка

-4 Мерцающая красная рамка

-5 Мерцающая светло-синяя рамка

-6 Мерцающая светло-зеленая рамка

-7 Мерцающая синяя рамка

-8 Мерцающая серая рамка

---------------------------------------------------------------

Определение размеров и положения окон

Аргумент Starting_row предиката makewindow есть целое чис-

ло, определяющее верхнюю строку (линию) создаваемого окна. Мак-

симальное количество строк, умещающихся на экране, 24. Значение

4 указывает, что окно начинается с четвертой строки. Для расс-

матриваемого аргумента можно использовать значения от 0 до 24.

Аргумент Starting_column предиката makewindow есть целое

число, указывающее крайний левый столбец окна. Максимальное

число столбцов, умещающихся на экране, 80. Поскольку столбцы

нумеруются, начиная с нуля, значение Starting_column, равное

9,определяет окно, начинающееся с 10-го столбца. Можно исполь-

зовать значения аргумента от 0 до 79.

Аргумент Window_height есть целое число, определяющее ко-

личество строк, занимаемых создаваемым окном. Максимально воз-

можное значение аргумента 25.

Аргумент Window_width есть целое число, указывающее число

столбцов, занимаемых окном. Максимальное значение аргумента 80.

Если случайно будут указаны такие значения номера верхней

строки и размера окна по вертикали, что нижняя строка окна ока-

жется за нижней границей экрана, Турбо-Пролог сообщит об ошибке

во время выполнения программы. Например, если указывается зна-

чение номера верхней строки 20 и размер окна по вертикали 7,

Турбо-Пролог выдаст сообщение об ошибке:

The parameters in makewindow are illegal.

Аналогично, если значения номера начального столбца и ши-

рины окна приведут к тому, что крайний правый столбец окна ока-

жется за правой границей экрана, то будет зафиксирована ошибка.

Такая ошибка будет получена, если указать значение номера на-

чального столбца 5 и ширину окна 79.

В приводимых ниже примерах используются пять описанных

атрибутов окна. В первом примере предикат,задающий окно, имеет

следующий вид:

makewindow(1,7,7,"FULL SCREEN",0,0,25,80)

Данному окну присвоен номер 1. Символы в нем будут белые,

фон черный, рамка белая и метка окна - "FULL SCREEN". Верхний

левый угол окна находится на строке 0, столбце 0, а само окно

имеет 25 строк и 80 столбцов. Рассматриваемое окно показано на

рис. 8.1.

Рисунок 8.1

Во втором примере, окно задается предикатом:

makewindow(2,4,1,"MENU",4,20,16,40)

Этому окну присвоен номер 2. Оно имеет метку "MENU". Сим-

волы в нем красные на черном фоне, и ограничено оно синей рам-

кой. Окно начинается с 4-й строки и 20-го столбца, имеет 16

строк и 40 столбцов. Черно-белое изображение окна показано на

рис. 8.2.

Рисунок 8.2

Если все аргументы предиката makewindow являются неозна-

ченными переменными, то им присваиваются значения параметров

текущего окна. Например, если предикат

makewindow(_,_,_,Title,_,_,_,_)

выполняется в то время, когда окно,показанное на рис. 8.2,

является текущим, переменной Title будет присвоено значение

Menu.

Упражнения

8.1. Напишите предикат makewindow для окна со следующими атри-

бутами:

Номер окна: 3

Цвет текста: голубой

Цвет фона: светло-серый

Атрибут рамки окна: красная рамка

Метка окна: "База Данных"

Начальная строка: 6

Начальный столбец: 10

Высота окна: 12

Ширина окна: 50

8.2. Напишите пригодный для выполнения предикат makewindow, ко-

торый создает окно, имеющее черный цвет символов, белый фон и

черную рамку. Разместите окно в верхней левой четверти экрана.

8.1.2. Использование других предикатов для работы с окнами

Создание окна требует указания всех его атрибутов; для

этого могут потребоваться определенные затраты времени. Однако

после того как атрибуты указаны, самая трудная часть работы мо-

жет считаться выполненной. Предикаты, рассматриваемые в следую-

щих секциях и используемые для различных методов управления ок-

нами, обычно имеют не более одного аргумента.

Предикат shiftwindow

Предикат shiftwindow используется для смены текущего окна

(переключения). Его форма:

shiftwindow(Window_number)

Параметр Window_number является целым числом, приписывае-

мым окну при его создании. (Это параметр Window_number предика-

та makewindow). Задание предиката shiftwindow(3) вызывает пере-

назначение всех операций ввода и вывода в окно, с номером 3.

В то же время Турбо-Пролог "помнит" предыдущие окна и их

атрибуты. Например, если окно 3 имеет такие атрибуты, что оно

будет перекрывать текущее окно (окно 4), то выполнение предика-

та shiftwindow(3) вызовет появление окна 3, в которое вложено

окно 4. Информация из окна 4, частично закрытая окном 3, сохра-

няется и появится на экране, когда произойдет переключение и

окно 4 вновь станет текущим.

Предикат gotowindow

Предикат gotowindow позволяет выполнять быстрое переключе-

ние между двумя окнами, которые не перекрываются. Его форма:

gotowindow(Window_number)

Как и в предыдущем случае, Window_number является номером,

присвоенным окну при его создании. Предположим, что в программе

окна 2 и 3 не перекрываются, и окно 2 является текущим. Для то-

го чтобы сделать окно 3 текущим, используется предикат

gotowindow(3). Этот предикат выполняется быстрее, чем

shiftwindow, и поэтому его следует использовать для переключе-

ния между окнами, содержащими большое количество текста.

Предикат clearwindow

Данный предикат удаляет из текущего окна все текстовые и

графические изображения. Предикат не имеет аргументов:

clearwindow

Окно и рамка окна,если она имеется, не разрушаются. Окно

целиком закрашивается соответствующим цветом фона.

Предикат removewindow

Предикат removewindow удаляет текущее окно с экрана. Пре-

дикат аргументов не имеет, поэтому его синтаксис прост:

removewindow

Все текстовые и графические изображения, находящиеся в ок-

не, также удаляются. Если за данным окном находится другое ок-

но, то это окно и его содержимое становятся видимыми. Если уда-

ляется последнее из заданных окон, на экране появляется то

изображение, которое было на нем до создания окон.

8.2. Использование окон для ввода и вывода

Стандартные предикаты ввода и вывода - read, readint,

readchar, write и nl - также работают с любым текущим окном.

Это означает, что предикаты ввода и вывода работают с любым ок-

ном, которое было сделано текущим при помощи makewindow,

gotowindow или shiftwindow.

По умолчанию предполагается, что курсор расположен в верх-

нем левом углу окна. Однако можно использовать предикат cursor

и помещать курсор в любую позицию текущего окна. Этот пре-

дикат имеет вид:

cursor(Row_number,Column_number).

Аргументы Row_number и Column_number являются целыми чис-

лами, задающими номера строки и столбца, по отношению к верхней

строке и крайнему левому столбцу экрана. Строки и столбцы нуме-

руются начиная с нуля: предикат cursor(0,0) обеспечивает вывод

текста, начиная с верхнего левого угла экрана. Если случайно

указывается позиция курсора, выходящая за рамки текущего окна,

то во время выполнения программы Турбо-Пролог выдаст сообщение

об ошибке.

Например, следующие три предиката могут быть использованы

для вывода сообщения в центре экрана:

makewindow(1,7,7,"",1,1,8,28),

cursor(4,12),

write("Have a Nice Day").

Если опустить предикат cursor, данное сообщение будет вы-

ведено, начиная с левого верхнего угла окна. Аргументами преди-

ката cursor могут также быть переменные, которым присваиваются

целочисленные значения. Другой формой подцели, размещающей со-

общение в центре окна, будет:

makewindow(1,7,7,"",1,1,8,28),

Row = 4, Col = 12,

cursor(Row,Col),

write("Have a Nice Day").

Если в качестве аргументов предиката cursor используются

неозначенные переменные, то этим переменным присваиваются теку-

щие значения строки и столбца. Подцель:

makewindow(1,7,7,"",1,1,8,28),

Row = 4,Col = 12,

cursor(Row,Col),

write("Have a Nice Day"),

cursor(What_row,What_column).

присвоит переменной What_row значение 4, а переменной

What_column - значение 27.

8.3. Программы, использующие окна

В следующих разделах приводится учебный материал по работе

с предикатами управления окнами и написанию программ, использу-

ющих оконные средства Турбо-Пролога. Приводятся четыре выполни-

мых программы на Турбо-Прологе.

8.3.1. Вывод текста в окно

Используя предикаты, описанные ранее, вы можете писать

программы, которые используют несколько окон на экране дисплея.

Окна не только помогают создать удобный вывод информации, но

также позволяют сделать программы более понятными.

В качестве простого примера создадим окно с белыми симво-

лами на черном фоне (позитивное изображение), а затем выполним

описанную ниже последовательность, в результате которой реали-

зуется вывод текста в окно.

1. Создать окно.

2. Вывести текст в окно.

3. Удалить текст из окна.

4. Записать новый текст в окно.

5. Удалить окно.

Указанные шаги выполняются в программе Window (листинг 8.1).

Листинг 8.1

Целевым утверждением является правило

make_window_and_write. Первый предикат этого правила создает

окно с белыми символами на черном фоне и с белой рамкой. Окно

начинается со строки 6 и столбца 20. Оно имеет высоту 14 строк

и ширину 40 столбцов.

Следующие десять предикатов выводят текстовые данные в по-

зиции, определяемые предикатом cursor. Следующие шесть предика-

тов "просят" пользователя нажать клавишу пробела, для вывода

другого сообщения. После нажатия клавиши пробела (или любой

другой), программа очищает окно. Рис. 8.3 показывает экран до

того, как он будет очищен.

Следующие восемь предикатов выводят в окно новый текст.

Предпоследние три предиката вновь приглашают пользователя на-

жать клавишу пробела, а последний предикат удаляет окно. Экран

дисплея перед удалением окна показан на рис. 8.4.

Заметим, что предикат readchar(_) позволяет пользователю

сохранить изображение текста на экране так долго, как это необ-

ходимо. Просле первого выполнения readchar из окна удаляется

текст, а после второго удаляется само окно.

Число строк, используемых для вывода текста в окно, на 2

меньше, чем высота окна, указанная в предикате. Аналогично,

число столбцов, имеющихся в распоряжении для вывода, на 2 мень-

ше, чем указанная ширина окна. Как пример, рассмотрим окно,за-

даваемое предикатом

makewindow(1,7,7,"",7,55,8,16).

Высота этого окна 8 строк, а для вывода будут использованы

только 6. Ширина окна 16 столбцов, следовательно, для вывода

можно использовать 14 столбцов.

Рисунок 8.3

Рисунок 8.4

Упражнение

8.3. Измените программу Window так, чтобы выводился другой

текст (стихи или проза - по вашему желанию). Меняйте атрибуты

окна до тех пор, пока вы не сможете свободно создавать окна.

Изменяйте всякий раз только один атрибут, тогда вы будете иметь

возможность наблюдать эффект, вызванный каждой модификацией.

8.3.2. Создание нескольких окон

Создание нескольких окон и вывод текста в них, в Тур-

бо-Прологе особого труда не представляет. Предположим, что

программа должна иметь четыре окна, каждое из которых занимает

приблизительно четверть экрана и используется определенной за-

дачей программы. Окна необходимо пометить, причем желательно,

чтобы метки отражали их назначение. В последующем, после завер-

шения задач, приведенных ниже, окна необходимо удалить.

Следующие четыре предиката создают требуемые окна с белыми

символами на черном фоне.

makewindow(1,7,7,"Message area #1",4,4,8,34)

makewindow(1,7,7,"Message area #2",4,42,8,34)

makewindow(1,7,7,"Message area #3",12,4,8,34)

makewindow(1,7,7,"Message area #4",12,42,8,34).

Программа Message (листинг 8.2) является реализацией опи-

санной программы. Целевым утверждением программы является пра-

вило make_windows_and_write. Это правило состоит из предикатов,

создающих окна и выводящих в них текст. Текст в каждом из окон

определяет один из терминов искусственного интеллекта. Эти окна

показаны на рис. 8.5.

Листинг 8.2

Рисунок 8.5

Последние 12 предикатов програмы (в листинге они сгруппи-

рованны по три) удаляют окна одно за другим. Заметьте, что вы-

полнение предиката clearwindow перед удалением окна является

необязательным; предикат removewindow автоматически очищает ок-

но перед его удалением. Рис. 8.6 показывает экран после удале-

ния двух нижних окон. Заметьте, что с экрана удаляются как сами

окна, так и текст, содержащийся в них.

Рисунок 8.6

При создании нового окна, Турбо-Пролог "запоминает" теку-

щее окно. При удалении какого-либо окна, текущим становится

предыдущее окно.

Упражнения

8.4. Измените программу Message так, чтобы она могла удалять

окна в порядке 1, 2, 3, 4. Выполните программу, чтобы убедиться

в правильности изменений.

8.5. Измените программу Message так, чтобы весь текст выводился

красными символами. Если ваш компьютер имеет монохромный экран,

выведите в окнах 2 и 4 сообщения черными символами на белом фо-

не.

8.6. Добавьте в программу Message пятое окно, расположенное в

центре экрана. Выведите в это окно какой-либо текст. Для про-

верки изменений, выполните программу.

8.7. Измените программу Message так, чтобы в окно 5 выводилось

семь строк текста. Затем выполните программу. (Помните, что при

том размере по вертикали, которое окна имеют в программе,в них

может быть выведено не больше восьми строк текста, включая

строку приглашения к выходу из окна).

8.3.3. Создание перекрывающихся окон

Перекрывающиеся окна создаются так, чтобы они одновременно

удовлетворяли потребностям программ и были удобны для пользова-

теля. Порядок, в котором окна создаются, определяется реализа-

цией программы. Программа Overlap, приведенная в листинге 8.3,

иллюстрирует создание перекрывающихся окон.

Листинг 8.3

В данной программе, целью является правило

make_windows_write_text. Задача этого правила - создать четыре

перекрывающихся окна и вывести в них определенный текст. Текст

состоит из четырех предложений, описывающих историю существова-

ния звезды:

A STAR IS BORN Окно 4 (звезда родилась)

THE STAR SHINES Окно 3 (звезда светит)

THE STAR BURNS Окно 2 (звезда взорвалась)

A BLACK HOLE APPEARS Окно 1 (появилась черная дыра)

Окна создаются в том порядке, который задан их номерами, а

удаление производится в обратном порядке, т.е. начиная с окна

4. При таком порядке удаления сообщения с экрана исчезают пос-

тепенно. Заметьте, что окна на рис. 8.7 слегка сдвинуты друг

относительно друга. Это сделано для того, чтобы показать сущес-

твование нескольких окон одновременно.

Рисунок 8.7

Упражнение

8.8. Придумайте и напишите программу, создающую четыре перекры-

вающихся окна со следующим текстом:

Верхнее окно:

Who is the author of the book "Lake Woebegon Days"?

Второе окно:

Garrison Keillor

Третье окно:

What is the most popular main dish in th U.S.?

Четвертое окно:

Fried chicken.

Программа перед выполнением очередного шага должна запра-

шивать нажатие любой клавиши на клавиатуре компьютера.

8.3.4. Создание меню при помощи окон

Программы, дружелюбные по отношению к пользователю, проек-

тируют таким образом, чтобы он имел возможность выбрать одну

задачу из некоторого ряда, либо определить порядок выполнения

задач. Выбор часто оформляют в виде меню. После того как выбор

сделан, программа может либо выполнить указанную задачу, либо

предоставить дочернее меню, в котором перечислены подзадачи.

Одну из них также можно выбрать для выполнения. Представляется,

что оба указанных способа использования окон являются наиболее

эффективными при организации работы программ. На рис. 8.8 пока-

зана структурная схема меню некоторой системы, работающей с

файлами и использующей дочерние меню.

Рисунок 8.8

Основной модуль данной программы создает главное меню. Из

этого меню, пользователь может выбрать: 0 - выход из меню

(окончание программы), 1 - удалить файл, 2 - переименовать

файл, 3 - создать файл, 4 - выход в операционную систему. Глав-

ное и каждое дочернее меню выводятся в отдельные окна. Каждое

дочернее окно позволяет выполнить необходимое действие.

Рассмотренную систему меню реализует программа Menu (лис-

тинг 8.4). Ее целевым утверждением является правило

run_file_utility. Правило show_menu составляет главный модуль:

show_menu :-

repeat,

makewindow(1,7,7,"Main Menu",4,10,16,36),

nl,

write(" Menu Utilities"),nl,nl,

write(" 0 Exit"),nl,

write(" 1 Delete file"),nl,

write(" 2 Rename file"),nl,

write(" 3 Create file"),nl,

write(" 4 Exit to PC DOS"),nl,nl,

write("Please enter your choice:(0-4) "),

readint(X),

X < 5,

process(X),

X = 0, !.

Предикат repeat используется таким образом, что пользова-

тель всегда возвращается в главное меню по окончании выполнения

подмодуля; исключением является выбор 0, в этом случае выполне-

ние программы прекращается.

Заметьте, что данное правило использует один из вариантов

метода Отката После Неудачи (перечитайте гл. 3, если вам необ-

ходимо освежить в памяти этот метод). Предикат readint(X) счи-

тывает целочисленное значение и присваивает его переменной X.

Правило X < 5 проверяет, что введенное значение меньше 5. Если

введенное число больше или равно 5, это правило выполнится не-

успешно и произойдет откат. В противном случае правило закон-

чится успехом и будет сделана попытка выполнить следующее пра-

вило, process(X).

Каждое правило process содержит предикат makewindow и пре-

дикат write для вывода сообщения, идентифицирующего задачу и

сообщения "This process will be implemented later", что по-рус-

ски означает: Процесс будет реализован позднее. В окончательно

написанной программе, предикат write, выполняющий вывод послед-

него сообщения, будет предикатом, реализующим выбранную задачу.

Целью приведенной здесь программы является только иллюстрация

разработки меню, а не выполнение каких-либо конкретных задач.

Заметим, что каждая задача оканчивается удалением соответствую-

щего окна.

После того,как правило process заканчивается успешно, де-

лается попытка выполнить остальные правила. Если X равно нулю,

отсечение (!) препятствует откату к правилу repeat, и программа

заканчивается.

Листинг 8.4

На рис. 8.9 показано главное меню и окно для задачи, в

функции которой входит удаление файла. Заметим, что пользова-

тель не будет иметь затруднений в определении окна текущей за-

дачи, поскольку окна имеют метки. Метка текущего окна File

Deletion отчетливо видна в середине верхней границы его рамки .

Упражнения

8.9 Выполните все возможные ветви программы Menu, и убедитесь в

том, что она возвращается в главное меню по окончании выполне-

ния каждой задачи.

8.10 Измените размеры окон,цвета текста и фона для того, чтобы

определить наиболее подходящие вам комбинации цветов.

8.11 Замените вывод сообщения в правиле process(2) правилом,

реализующим переименование файла (используйте информацию гл. 7

о предикатах Турбо-Пролога для работы с файлами).

Рисунок 8.9

8.4. Использование графики в программе

Программирование графики на Турбо-Прологе доставляет удо-

вольствие,а графические средства Турбо-Пролога обладают мощными

возможностями. Вы сможете создавать графические изображения вы-

сокой точности на экране монитора, и в этом разделе показано,

как это сделать.

Графические предикаты Турбо-Пролога поддерживают Цветной

Графический Адаптер (CGA) фирмы IBM и Расширенный Графический

Адаптер (EGA) фирмы IBM, а также совместимые с ними. Описывае-

мые здесь атрибуты относятся именно к этим адаптерам. Информа-

цию по использованию других существующих графических адаптеров

частично совместимых с указанными можно найти в конкретной до-

кументации. (За исключением Монохромных Адаптеров - графика для

них не используется).

Программы, приведенные в этой книге, написаны для CGA, так

как он является наиболее часто используемым графическим адапте-

ром. Отметим, что все режимы работы с CGA поддерживаются в EGA

(противное не верно), следовательно все программы, выполняемые

на компьютере с CGA, выполнимы на компьютере с EGA (при этом,

конечно, используются не все возможности EGA).

Управление графическими режимами и цветами в Турбо-Прологе

осуществляется с помощью параметров, задаваемых в предикатах

graphics и makewindow. Предикат graphics используется для вклю-

чения графического режима CGA или EGA. В разд. 8.2. было расс-

казано о применении предиката makewindow в текстовом режиме.

Как вы помните, цвет текста в окне и цвет рамки настраиваются

параметрами Screen_attribute и Frame_attribute. Эти параметры

управляют теми же свойствами окна и в графическом режиме, но в

этом случае они работают иначе. В данном разделе будет показа-

но, как выбирать параметры в графическом режиме.

Предикаты dot и line используются для изображения объектов

в графическом режиме. Ниже будет описано как их использовать.

Однако прежде необходимо усвоить некоторые сведения, касающиеся

разрешающей способности и различных графических режимов, под-

держиваемых CGA и EGA.

Предикат graphics и параметры Screen_attribute и

Frame_attribute предиката makewindow взаимодействуют довольно

сложным образом. И если говорить о версии 1.1, то можно ска-

зать, что Турбо-Пролог в этом случае ведет себя причудливо. Од-

нако данное замечание не касается более поздних версий Тур-

бо-Пролога. В табл. 8.11 собраны сведения о параметрах графи-

ческого режима для предикатов graphics, makewindow, line и dot.

Они должны помочь сделать правильный выбор.

Информация, приведенная в табл. 8.9, 8.10 и 8.11 была по-

лучена во время работы на компьютере IBM PC AT, оборудованном

EGA и Расширенным Цветным Дисплеем фирмы IBM (Extended Color

Display). Информация по EGA не приводится в документе Turbo

Prolog Owner's Handbook фирмы Borland International. Вы можете

смело использовать графические предикаты, описанные здесь, од-

нако надо понимать, что результаты, получаемые на отличных от

IBM PC AT компьютерах либо при работе с более поздней версией

Турбо-Пролога, могут отличаться от приведенных здесь.

8.4.1. Разрешающая способность изображения и

режимы графического адаптера

Монитор компьютера, работающий в графическом режиме, можно

рассматривать как поверхность, состоящую из крошечных светящих-

ся лампочек различных цветов. Они обычно называются элементами

изображения, или пикселами (pixels). (Picture elements - эле-

менты, из которых состоит рисунок.) Графическое изображение в

действительности представляет собой составное изображение, фор-

мируемое посредством включения или выключения пикселов.

Важнейшей характеристикой графического изображения являет-

ся разрешающая способность графического экрана. Разрешение эк-

рана определяется числом пикселов, размещенных на экране по го-

ризонтали и по вертикали. Чем выше разрешение, тем выше качест-

во изображения. Действительно, представим экран как поверх-

ность, покрытую светящимися лампочками: поверхность с 640 х 200

лампочками может воспроизвести значительно более детальное

изображение, чем поверхность с 320 х 200 лампочками.

Количество пикселов экрана определяется режимом работы

графического адаптера. Как CGA, так и EGA имеют режимы работы,

называемые режимами со средним (medium-resolution) и высоким

разрешением (high-resolution). При среднем разрешении экран де-

лится на 320 пикселов по горизонтали; при высоком разрешении,

он делится на 640 пикселов по горизонтали. В обоих режимах эк-

ран имеет 200 пикселов по вертикали. (EGA имеет еще один режим,

называемый улучшенным разрешением (enhanced resolution), при

котором экран делится на 640 пикселов по горизонтали и 350 пик-

селов по вертикали. Использование этого режима работы рассмат-

ривается в дальнейшем в этой главе.)

Разрешение экрана и возможные цвета для различных режимов

работы CGA и EGA приводятся в табл. 8.5.

---------------------------------------------------------------

Таблица 8.5. Графические режимы

---------------------------------------------------------------

Разрешение Гориз х Вертик Количество К-во столбцов

цветов текста

---------------------------------------------------------------

Среднее(CGA) 320*200 4 40

Высокое(CGA) 640*200 2 80

Среднее(EGA) 320*200 16 40

Высокое(EGA) 640*200 16 80

Улучшенное(EGA) 640*350 13 80

---------------------------------------------------------------

8.4.2. Предикат graphics

Создание графического изображения в Турбо-Прологе начина-

ется с перевода экрана в графический режим работы. Для этой це-

ли используется предикат graphics. Его форма:

graphics(Mode,Palette,Color)

Три параметра этого предиката управляют дисплеем в графи-

ческом режиме. Выбор значений параметров рассматривается в сле-

дующих разделах.

Заметим, что при выполнении предиката graphics экран очи-

щается; все изображения, созданные в текстовом режиме, пропада-

ют. Также заметим (как показано в табл. 8.6), что текстовые

символы в графическом режиме со средним разрешением в два раза

шире символов в режиме с высоким разрешеним (и в текстовом ре-

жиме); при среднем разрешении строка экрана может содержать не

более 40 символов. Параметр Width предиката makewindow задает

число символов (не число пикселов) как в текстовом, так и в

графическом режиме. Таким образом, при создании окна необходимо

следить за тем, чтобы его размеры не превосходили размеров эк-

рана. В противном случае, во время выполнения программы будет

зафиксирована ошибка. Справочный материал по выбору необходимых

значений приводится в разд.8.4.3.

Предикат text переводит дисплей в текстовый режим.

Параметр Mode

Параметр Mode является целым числом от 1 до 5, предназна-

ченным для выбора графического режима. Режимы разрешения и со-

ответствующие значения параметра mode приведены в табл. 8.6.

---------------------------------------------------------------

Таблица 8.6. Разрешение и параметр Mode

---------------------------------------------------------------

Разрешение Параметр Mode

---------------------------------------------------------------

Среднее(CGA) 1

Высокое(CGA) 2

Среднее(EGA) 3

Высокое(EGA) 4

Улучшенное(EGA) 5

---------------------------------------------------------------

Цветной Графический Адаптер (CGA) поддерживает режимы 1 и

2. Расширенный Графический Адаптер (EGA) поддерживает режимы

3,4 и 5. Таким образом, выбор значения параметра Mode необходи-

мо осуществлять в соответствии с типом имеющегося на машине

адаптера. Как указано ранее, прочие графические адаптеры явля-

ются совместимыми в разной степени с рассмотренными адаптерами;

изучите документацию по адаптеру и используйте соответствующие

режимы для вашего компьютера. Необходимо тщательно изучить до-

кументацию по адаптеру, так как выбор режима работы, не совмес-

тимого с конфигурацией аппаратуры, вызовет непредсказуемое по-

ведение программы.

Параметр palette

Параметр palette является целым числом с возможными значе-

ниями 0 и 1. Этот параметр используется для выбора одной из

двух доступных цветовых палитр. В табл. 8.7 показаны цвета,

имеющиеся в каждой из этих палитр. Числа 1,2 и 3 используются

для задания номера графического об'екта, например линии или

точки.

---------------------------------------------------------------

Таблица 8.7. Цветовые палитры и выбор цвета

---------------------------------------------------------------

Номер

палитры Цвета:

---------------------------------------------------------------

1 2 3

0 Зеленый Красный Желтый(CGA)

Коричневый(EGA)

1 Голубой Фиолетовый Белый

---------------------------------------------------------------

В режимах 1, 3, 4 и 5, значение параметра Palette также

определяет цвет текста, появляющегося на экране и не находяще-

гося внутри какого-либо окна. В этих режимах данный текст имеет

цвет 2 текущей палитры. Таким образом, текст будет красным для

палитры 0 и фиолетовым для палитры 1.

В режиме 1 параметр Palette также определяет выбор цвета

для рамок окон и цвета текста в окнах. Полное описание задания

цветов для данного случая приводится в разд. 8.4.3.

Для режима 5 цвет рамки окна (если ваша программа задает

окна) также определяется текущей палитрой. Рамка окна будет

иметь цвет 1 текущей палитры: серый для палитры 0 и голубой для

палитры 1.(Как указывалось ранее, взаимодействие графических

параметров является довольно сложным, поэтому следует обратить-

ся к табл. 8.11, когда вы начнете писать собственные программы

с графикой.)

Параметр Color

Параметр Color является целым числом, используемым для вы-

бора цветов на графическом дисплее. Возможные цвета определяют-

ся текущим графическим режимом. Режимы 1, 2, 3 и 4 дают возмож-

ность выбора 16 цветов, как показано в табл. 8.8. В режиме 2

цвет фона всегда черный, независимо от значения, присвоенного

параметру Color; в этом режиме параметр Color определяет цвет

об'ектов переднего плана, включая текст, линии,точки и рамки

окон. В режимах 1, 3 и 4, однако, параметр Color определяет

цвет фона графического дисплея. В режиме 5 имеется 13 возможных

цветов, как показано в табл. 8.9.

---------------------------------------------------------------

Таблица 8.8. Выбор цвета в графических режимах 1, 2, 3 и 4

---------------------------------------------------------------

Цвет фона Значение Color

---------------------------------------------------------------

Черный 0

Синий 1

Зеленый 2

Голубой 3

Красный 4

Фиолетовый 5

Коричневый 6

Белый 7

Серый 8

Светло-синий 9

Светло-зеленый 10

Светло-голубой 11

Светло-красный 12

Светло-фиолетовый 13

Желтый 14

Интенсивно-белый 15

---------------------------------------------------------------

---------------------------------------------------------------

Таблица 8.9. Выбор цвета в графическом режиме 5

---------------------------------------------------------------

Цвет фона Значение Color

---------------------------------------------------------------

Черный 0

Синий 1

Зеленый 2

Голубой 3

Красный 4

Фиолетовый 5

Средне-зеленый 6

Белый 7

Темно-зеленый 8

Светло-синий 9

Светло-зеленый 10

Светло-голубой 11

Коричневый 12

---------------------------------------------------------------

8.4.3. Предикат makewindow и графический режим

Ранее в этой главе было показано, как использовать преди-

кат makewindow в текстовом режиме. В графическом режиме этот

предикат используется аналогичным образом, но имеются некоторые

важные отличия, описываемые в этом разделе. Как и прежде, зави-

симости между режимами и параметрами могут показаться сложными;

вам может потребоваться обратиться к табл. 8.11, когда вы нач-

нете писать свои графические программы,работающие с окнами.

Параметры Screen_attribute, Frame_attribute, Column и

Width предиката makewindow используются различным образом в

графическом и текстовом режимах. Различия рассматриваются в

следующих разделах.

Параметры Column и Width

Графические режимы 2 и 4 выводят текст на экран по стро-

кам, причем каждая строка для вывода символов (или столбцов)

имеет только 40 позиций. Следовательно, необходимо следить за

тем, чтобы значения, присваиваемые параметрам Row и Column, не

задавали окна с правой границей, превышающей предел 40 столб-

цов. Если же такое случится, ошибка не будет обнаружена во вре-

мя компиляции программы. Данная ошибка будет зафиксирована

только при выполнении программы.

Чтобы избежать этой ошибки, убедитесь в том, что сумма

значений параметров Column и Width не превосходит 39. (Напом-

ним, что столбцы нумеруются, начиная с 0). Если, например, па-

раметру Column присвоено значение 4 (это указывает на то, что

крайним правым столбцом окна является пятый столбец экрана), то

максимальным допустимым значением параметра Width будет 35.

Параметры Screen_attribute и Frame_attribute

Как указано в описании использования предиката makewindow

в текстовом режиме, значение параметра Screen_attribute вычис-

ляется сложением значений, соответствующих требуемым цветам фо-

на и текста. В графическом режиме, однако, цвет фона определя-

ется текущим режимом и значением параметра Color предиката

grarhics. Таким образом, в графическом режиме нельзя присвоить

различные цвета фона создаваемым окнам; цвет фона всегда такой,

как и цвет всего экрана.

В графическом режиме можно управлять цветом текста в окне,

но не цветом фона. Таким образом, значение параметра

Screen_color определяет только цвет текста в графическом режи-

ме. Действие этого параметра зависит от текущего графического

режима. Для режима 1 цвет текста в окне задает параметр

Screen_attribute, вместе с параметром Palette предиката

graphics.

Действие параметра Frame_attribute в графическом и тексто-

вом режиме также различаются. Так, в текстовом режиме рамка ок-

на создается, если параметру Frame_attribute присвоено ненуле-

вое значение (положительное или отрицательное), а в графическом

режиме запрещено использовать отрицательные значения. Таким об-

разом, мигающая рамка окна в графическом режиме отсутствует.

Подобно Screen_attribute, Frame_attribute вместе с параметром

Palette предиката graphics задает цвет рамки окна для режима 1.

(Сказанное выше справедливо только для адаптеров фирмы IBM).

В режиме 1 возможными значениями параметров

Screen_attribute и Frame_attribute являются числа 1, 2 и 3;

текст в окне и рамка окна будут иметь цвет, задаваемый текущей

палитрой. Для палитры 0, например, значение Screen_attribute

равное 1 задает серый текст, а значение Frame_attribute равное

2 определяет красную рамку окна. Для палитры 1 значение

Screen_attribute равное 2 дает фиолетовый текст, а значение

Frame_attribute равное 3 задает белую рамку окна. (Используйте

табл. 8.7 для определения возможных цветов в каждой из палитр.)

В режиме 5 значение Frame_attribute определяет единствен-

ное: имеет окно рамку или нет. Рамка у окна будет, если значе-

ние Frame_attribute не равно нулю. При этом рамка будет иметь

цвет 1 текущей палитры: серый для палитры 0, и голубой для па-

литры 1.

Возможные значения Screen_attribute и соответствующие им

цвета, имеющие место для режима 5, приведены в табл. 8.10. За-

метим, что цвета, указываемые значениями 1, 3, 9 и 11, зависят

от текущей палитры.

---------------------------------------------------------------

Таблица 8.10. Значения screen_attribute для графического

режима 5

---------------------------------------------------------------

Значение Цвет

---------------------------------------------------------------

0 (Текст отсутствует)

1 Зеленый(палитра 0), Голубой(палитра 1)

2 (Текст отсутствует)

3 Зеленый(палитра 0), Голубой(палитра 1)

4 Красный

5 Белый

6 Красный

7 Белый

8 (Текст отсутствует)

9 Зеленый(палитра 0), Голубой(палитра 1)

10 (Текст отсутствует)

11 Зеленый(палитра 0), Голубой(палитра 1)

12 Красный

13 Белый

14 Белый

---------------------------------------------------------------

8.4.4. Предикаты line и dot

После того, как мы рассмотрели использование в графическом

режиме предикатов graphics и makewindow, приступим к обсуждению

предикатов, в функции которых входит создание на экране изобра-

жений. Это предикаты line и dot. Предикат line имеет форму:

line(Row_1,Column_1,Row_2,Column_2,Palette_color)

а предикат dot имеет форму:

dot(Row,Column,Palette_color)

Все параметры этих предикатов имеют целочисленные значе-

ния. Параметры, указывающие строку (row) и столбец (column) за-

дают расположение концевых точек линии для предиката line и по-

ложение точки для предиката dot. Не считая некоторых исключе-

ний, параметр Palette_color определяет цвет линии или точки.

В режимах 1 и 3 цвет, определяемый параметром

Palette_color, зависит от текущей палитры. (Текущая палитра за-

дается параметром Palette предиката graphics.) Цвет точки или

линии для данных режимов работы определяется в табл. 8.7.

Для режимов 2, 4 и 5 параметр Palette_color в действитель-

ности не задает цвет линии или точки. Точки и линии при значе-

нии Palette_color равном 2 на экран не выводятся. В режиме 2

при значении Palette_color равном 1 или 3, точки и линии рису-

ются в цвете, заданном параметром Color предиката graphics. В

режимах 4 и 5, точки и линии изображаются в цвете 1 текущей па-

литры, вне зависимости от того, равно заданное для предиката

dot или line значение Palette_color 1 или 3.

Оба этих предиката используют координатную систему, отли-

чающуюся от той, которая была рассмотрена для случая текстового

режима работы. В графическом режиме координаты точки на экране

изменяются от 0 до 31999 по горизонтали и вертикали. Точка с

координатами (0,0) задает левый верхний угол экрана, точка

(0,31999) - верхний правый угол, точка (31999,0) - нижний левый

угол, и точка (31999,31999) - правый нижний угол.

8.4.5. Сводка по графическим режимам и значениям параметров

для них

В табл. 8.11 приведены сведения по всем графическим режи-

мам.

Выберите в таблице строку, соответствующую интересующему

вас режиму. Информация в данной строке указывает параметры, ис-

пользуемые для задания цветов фона экрана, текста экрана, текс-

та окна, рамки и графических объектов. Сравните имена парамет-

ров в таблице с именами, приведенными в следующем примере:

graphics(Mode,Palette,Color)

makewindow(Number,Screen_attribute,

Frame_attribute,

" Title ",

Row,Column,

Depth,Width)

Чтобы выбрать числовые значения цветов, обращайтесь к таб-

лицам, указанным в таблице 8.11. Они были приведены выше. Пом-

ните, что значение Frame_attribute равное нулю задает окно без

рамки.

8.5. Изображение объектов предикатами line и dot

При помощи графических предикатов line и dot можно созда-

вать графические объекты простой и сложной формы. К простым от-

носятся прямоугольники, треугольники, окружности и эллипсы. Эти

фигуры можно использовать для создания сложных изображений де-

ревьев, листьев, веток, домов, животных, пейзажей.

---------------------------------------------------------------

Таблица 8.11. Параметры графического режима

---------------------------------------------------------------

Режим Фон Текст Текст Рамка Графические

экрана экрана окна окна объекты

---------------------------------------------------------------

1 Screen_ Palette Screen_ Frame_ Palette_

attribute 0-красный attribute attribute color

Табл.8.8 1-фиолетов. Табл.8.8 (1, 2 или 3 Соотв.

цвет из тек. текущей

палитры) палитре

2 Всегда Color Color Color Color

черный Табл.8.8 Табл.8.8 Табл.8.8 (Рисуются

только объ-

екты с

Palette_

color 1

или 3.)

3 Color Palette Screen_ Frame_ Palette_

Табл.8.8 0-красный attribute attribute color

1-фиолетов. Табл.8.8 Табл.8.8 Соотв.

текущей

палитре

4 Color Palette Screen_ Frame_ Color

Табл.8.8 0-красный attribute attribute (Рисуются

1-фиолетов. Табл.8.8 Табл.8.8* только объ-

екты с

Palette_

color 1

или 3.)

5 Color Palette Screen_ Palette Palette

Табл.8.8 0-красный attribute 0-зеленый 0-зеленый

1-фиолетов. Табл.8.10 1-голубой 1-голубой

(Рисуются

только объ-

екты с

Palette_

color 1

или 3.)

---------------------------------------------------------------

*Замечание: Соответственно значению атрибута 1, 2 или 3,

цвет выбирается из текущей палитры

---------------------------------------------------------------

Для изображения, например, прямоугольника, можно использо-

вать несколько предикатов line. Результатом работы правила

draw_a_rectangle :-

line(2000,2000,2000,12000,1),

line(2000,12000,8000,12000,1),

line(8000,12000,8000,2000,1),

line(8000,2000,2000,2000,1).

будет прямоугольник с пропорциями, приблизительно, 3 х 5 , в

верхнем левом углу экрана.

Аргумент Palette_color равный 1 задает серую линию для па-

литры 0 или голубую линию для палитры 1 (данный случай принад-

лежит к исключениям, указанным в табл. 8.11).

Чтобы получить точку в том месте, где начинается процесс

изображения прямоугольника, укажите следующие координаты и цвет

в предикате

dot(2000,2000,1).

Предикаты

dot(2000,2000,1),

dot(3000,3000,1),

dot(1000,3000,1).

могут быть использованы для изображения вершин треугольника в

левой верхней четверти экрана.

8.5.1. Изображение окружности

Окружность принадлежит к простым фигурам. Все точки окруж-

ности равноудалены от ее центра. Из элементарной тригонометрии

следует, что координаты Column и Row для любой точки окружности

могут быть вычислены при помощи радиуса и координат центра

Center_column и Center_row (см. рис. 8.10). Имеют место следую-

щие соотношения:

Row = Center_row - R х cos A (1)

Column = Center_column + R х sin A (2)

Предикаты Турбо-Пролога sin и cos требуют задания аргумен-

тов, выраженных в радианах (360 градусов = 2 х П рад). Для ок-

ружности, значения переменной А изменяются от 0 до 6.283 (2 х

П) рад приблизительно. Если увеличивать значение А на 0.02 рад

для каждой следующей точки, то будет получено около 314 точек

окружности. Такое количество точек достаточно для изображения

окружности. После того, как получены значения Row и Column, с

помощью предиката dot можно получить точку выбранного цвета.

Рисунок 8.10

При программировании компьютерной графики необходимо учи-

тывать некоторые технические аспекты, усложняющие задачу прог-

раммиста. Разработчики графических мониторов и адаптеров ис-

пользуют отличающуюся от рассмотренной шкалу горизонтальных и

вертикальных размеров. Эти размеры масштабируются посредством

параметра, называемого видовым отношением (aspect ratio). Видо-

вое отношение определяется как отношение высоты экрана к его

ширине и измеряатся в единицах линий электронного луча, помеща-

ющихся на экране (video scan lines). Для большинства стандарт-

ных экранов видовое отношение равно приблизительно 5/7.

В связи с этим, формулы, определяющие координаты изобража-

емых точек, должны быть изменены в соответствии с видовым отно-

шением. Рисунок окружности показывает необходимость этих изме-

нений: если сформировать изображение окружности при помощи зна-

чений, определяемых уравнениями (1) и (2), то будет получен эл-

липс. Для учета видового отношения, необходимо заменить уравне-

ние (1) на другое.

Row = Center_row - 1.40 х R х cos A (3)

Значение видового отношения зависит от типа водео-монито-

ра. И, следовательно, коэффициент в уравнении (3) может менять-

ся для различных типов мониторов.

8.5.2. Реализация простых изображений

Примеры типичного использования предикатов line и dot мож-

но найти в листинге 8.5 программы Shapes. Данная программа ри-

сует три простых фигуры в различных четвертях экрана и выводит

пояснительный текст в оставшуюся четверть экрана. Структурная

схема программы приводится на рис. 8.11. Картинка, получающаяся

в результате работы программы Shapes показана на рис. 8.12.

Рисунок 8.11

Листинг 8.5

Рисунок 8.12

Основным модулем программы является модуль draw_figures. Он

выполняет вызовы подмодулей make_window, write_captions,

draw_rectangle, draw_triangle и draw_ellipse. Все правила дан-

ной программы весьма просты.

Подмодуль, рисующий эллипс, содержит рекурсивное правило

draw_ellipse(A). Параметр А используется для передачи значения

угла от главного правила к подправилу:

draw_ellipse(A) :-

A >= 6.28, !.

draw_ellipse(A) :-

Center_row = 18000, Center_col = 5000, R = 3600,

Row_r = Center_row - R * cos(A),

Column_r = Center_col + R * sin(A),

real_int(Row_r,Row),real_int(Column_r,Column),

dot(Row,Column,1),

A1 = A + 0.02,

draw_ellipse(A1).

Первое предложение данного правила выполняется успешно,

если А присвоено значение большее или равное 6.28.; таким обра-

зом правило устанавливает верхний предел значения А. Предикат

dot рисует точку в месте, указываемом значениями Row и Column,

а следующее подправило увеличивает значение угла А на 0.02 ра-

диана.

Обратимся к рис. 8.12. Заметим, что первым рисуется прямо-

угольник, затем треугольник,а затем и зллипс. Заметим также,

что время на получение изображения эллипса значительно больше

времени, за которое рисуется прямоугольник.Это объясняется тет,

что большая часть времени тратится на вычисление значений Row и

Column. Как видно из рисунка, более длинная ось эллипса направ-

лена по горизонтали. Это объясняется тем, что при вычислении

значений Column видовое отношение не используется. Таким обра-

зом, отсутствие учета видового отношения приводит к тому, что

вертикальная ось эллипса короче его горизонтальной оси, несмот-

ря на то, что при вычислении горизонтальной и вертикальной ко-

ординаты используется одно и то же значение R.

Упражнения

8.12. Измените программу Shapes так, чтобы цвета фона и текста

были другими (вспомните таблицы палитр). Выполните программу и

оцените ее работу.

8.13. Измените программу, заменив предикат

Row_r = Center_row - R * cos(A)

в draw_ellipse на предикат

Row_r = Center_row - 1.40 * R * cos(A)

Затем выполните программу. Что произошло с эллипсом?

8.14. Модифицируйте программу Shapes, заменив

A1 = A + 0.02

в правиле draw_ellipse на

A1 = A + 0.05

Выполните программу. Как изменилось изображение эллипса?

8.6. Деловая графика

Столбиковые и круговые диаграммы часио используются в де-

ловой практике, поскольку с их помощью можно наглядно предста-

вить, например, такие показатели, как число проданных или число

произведенных изделий за определенный отрезок времени и в опре-

деленном месте. Эти диаграммы особенно хороши тогда, когда нуж-

но оценить тенденции развития производства, не требуя вывода на

экран его количественных показателей. Ниже будут приведены

программы, иллюстрирующие основы деловой графики. Они реализуют

методы получения линейных графиков, столбиковых и круговых ди-

аграмм и пригодны для выполнения.

8.6.1. Линейный график

Линейный график можно легко нарисовать при помощи предика-

та line. Например, представим себе гипотетическую компанию

Mid-West Beer Distributors,Inc. Объем продажи компании в первой

половине 1986 г. представлен в табл. 8.12.

---------------------------------------------------------------

Таблица 8.12 Объем продажи компании Mid-West Beer Distributors

---------------------------------------------------------------

Месяц (1986) Объем продажи (х 1000 дол.)

---------------------------------------------------------------

Январь 6000

Февраль 9000

Март 10000

Апрель 6000

Май 7000

Июнь 9000

---------------------------------------------------------------

Необходимо нарисовать линейный график изменения объемов

продажи по месяцам, с соответствующими пояснениями. Ниже приве-

дены шаги, которые необходимо выполнить для достижения постав-

ленной цели.

1. Создать окно.

2. Вывести главный заголовок и подзаголовки.

3. Нарисовать оси x и y, и вывести метки осей.

4. Провести линии между точками данных.

5. Вывести метки, соответствующие месяцам, по оси х.

Листинг 8.6

Приведенная в листинге 8.6. программа LineGraph свидетель-

ствует о том, что указанные шаги можно реализовать единственным

правилом. Таковым является правило draw_line_graph. Второе пра-

вило prompt_exit предлагает пользователю нажать клавишу пробела

и затем удаляет окно.

Предикат graphics(2,0,7) задает черно-белый экран с высо-

ким разрешением. Предикат makewindow задает черно-белое окно с

меткой Line Graph, имеющее высоту 20 строк и ширину 60 столб-

цов. Левый верхний угол окна находится на строке 2, столбце 10.

Следующим шагом, выполняемым предикатом draw_line_graph,

является изображение осей и отметка точек на оси x. Для данного

графика первой точкой на оси y будет точка с координатами

(4000,3000), а последней - с координатами (16000,3000). Коорди-

наты начальной и конечной точек осей, а также координата точки,

соответствующей данным первого месяца продажи, приведены на

рис. 8.13. (Заметьте, что концевые точки задаются абсолютными

координатами экрана, а не значениями смещения относительно осей

x и y).

Рисунок 8.13

На оси x, с шагом 2000 точек, размещены названия месяцев

(см. рис. 8.14). По оси y отложены значения объемов продажи.

При этом приращение объемов продажи составляет 200 дол., также

с шагом 2000 точек. Вывод текста описывается в следующем разде-

ле данной главы.

Точки будущего графика задаются значениями абсолютных ко-

ординат экрана по горизонтали и по вертикали. Например, точка

графика, соответствующая данным за январь, имеет координаты

(10000,5000). Координата 10000 по вертикали получается вычита-

нием соответствующего значения данных 6000 (объем продажи) из

координаты по вертикали 16000, которую имеют все точки на оси

х. Значение получается вычитанием, а не сложением, потому что

точки, расположенные выше на экране, имеют меньшие (а не боль-

шие) значения координат по вертикали.

Для вычисления значений координат точек графика по верти-

кали можно использовать простую формулу.

Коорд. = Коорд.оси x - ( Данное * Масштаб)

Для данного графика масштаб равен 1. При изображении гра-

фиков необходимо определять масштаб при помощи вычислений или

экспериментально. Один из способов вычисления масштаба состоит

в вычитании координаты наиболее высоко расположенной точки гра-

фика по вертикали (10000 в данном случае) из соответствующей

координаты самой низкой точки (в данном случае - координата то-

чек оси х) и последующем делении результата на самое большое

значение, задаваемое в данных, используемых для построения гра-

фика. Например, если наибольшим значением, которое должно быть

изображено при помощи графика, является 12000, масштаб будет:

(16000 - 10000) / 12000

или 1/2.

Значения координат точек графика по горизонтали получаются

сложением шага, 2000 в данном случае, со значением координаты

по горизонтали для точек оси y. Значение координаты по горизон-

тали точки графика, соответствующей данным за январь 5000,полу-

чается суммированием 2000 и координаты начала координатной сис-

темы линейного графика по горизонтали 3000.

В табл. 8.13 приведены названия месяцев, объемы продажи,

значения координат точек данных, соответствующие шестимесячному

периоду, отображаемому данным графиком.

---------------------------------------------------------------

Таблица 8.13. Значения координат для Диаграммы продажи

--------------------------------------------------------------

Продажа Коорд. по верт. Коорд. по гориз.

Месяц Объем (коорд.точек оси х (коорд. оси у+

по верт. - об.прод.) шаг 2000)

--------------------------------------------------------------

Янв 6000 10000 5000

Фев 9000 7000 7000

Март 10000 6000 9000

Апр 6000 10000 11000

Май 7000 9000 13000

Июнь 9000 6000 15000

---------------------------------------------------------------

После того, как все 6 точек найдены, проводят 5 линий, со-

единяющих эти точки одна за другой. В результате получается ли-

нейный график (см. рис. 8.14.). Как видим, объемы продажи на

полученном графике могут изменяться от 0 до 10000 дол.

Заметьте, что линии, проведенные между точками данных,

имеют неровную границу. Это, к сожалению, типично для диаго-

нально расположенных линий, изображаемых на дисплее в графичес-

ком режиме.

Рисунок 8.14.

Упражнения

8.15. Модифицируйте программу Line Graph, изменив параметры

цветов. Выполните измененную программу и оцените отличия.

8.16. Некое учреждение E-Z Office Supplies за последние 6 меся-

цев 1986 года имеет следующие доходы:

______________________________________________________________

Месяц Продажа(х 10 дол.)

______________________________________________________________

Июль 6000

Август 7500

Сентябрь 11000

Октябрь 10250

Ноябрь 9500

Декабрь 12325

_____________________________________________________________

Используя программу LineGraph в качестве примера, напишите

программу на Турбо-Прологе, строящую линейный график для зтих

данных.

8.17. Какие изменения необходимо внести в программу LineGraph,

чтобы она обрабатывала данные за 12 месяцев в году? Кратко опи-

шите эти изменения.

8.6.2. Простая столбиковая диаграмма

Простая столбиковая диаграмма получается в Турбо-Прологе

так же легко, как и линейный график. В качестве примера будет

рассмотрена статистика объемов продажи компании, использованная

для построения линейного графика в предыдущем разделе. Однако

потребуется внести некоторое изменение в последовательность ша-

гов, которая использовалась для построения линейного графа, а

именно, вместо линий, соединяющих точки данных, будут проведены

столбики к оси x от каждой из точек.

Программа BarGraph, приведенная в листинге 8.7, аналогична

программе LineGraph с той лишь разницей, что она содержит пре-

дикаты для проведения шести вертикальных столбиков. Для получе-

ния каждого столбика требуется три предиката line - два для то-

го, чтобы провести вертикальную линию от оси x к точке данных,

и один для построения горизонтальной линии, создающей верхнюю

границу столбика. Например, чтобы получить столбик для данных

за январь, требуются предикаты:

line(16000,5000,10000,5000,1),

line(16000,5500,10000,5500,1),

line(10000,5000,10000,5500,1).

Листинг 8.7

На рис. 8.15 приводится столбиковая диаграмма, полученная

при помощи программы BarGraph. Заметим, что каждый столбик име-

ет ширину 500 пиксел.

Рисунок 8.15

Упражнения

8.18. Измените программу BarGraph так, чтобы столбики были в

два раза шире.

8.19. Напишите программу получения столбиковой диаграммы для

данных из упр. 8.17. Используйте свои комбинации цветов для

создания красивого изображения на экране.

8.6.3. Круговая диаграмма

Круговую диаграмму в Турбо-Прологе можно получить совмест-

но используя предикаты line и dot , как это было показано ранее

в данной главе. Рис. 8.16 демонстрирует методику построения

круговой диаграммы, которая включает в себя следующие этапы:

1. Нарисовать линии радиусов, ограничивающих элементы кру-

говой диаграммы, с пропорциональными значениям данных углами

между ними.

2. Вычислить места расположения идентифицирующих их меток

и вывести их на экран.

3. Нарисовать окружность, ограничивающую диаграмму.

Каждый из перечисленных этапов состоит из нескольких ша-

гов, описываемых в следующих разделах. Рассматриваемый здесь

пример использует данные компании Mid-West Beer

Distributors,Inc. Это сделано специально, чтобы дать возмож-

ность сравнить все полученные диаграммы.

Величины углов элементов круговой диаграммы, определяются

из значений объемов продажи, приведенных в табл. 8.12, и тем

самым определяется расположение радиальных линий.

Для примера рассмотрим вычисление угла элемента круговой

диаграммы, соответствующего данным за январь. Прежде всего,

посредством суммирования всех значений объема продажи за шести-

месячный период и деления значения объема продажи за январь на

получившуюся сумму, вычисляется относительный размер элемента

круговой диаграммы. Относительный размер этого элемента есть

6000/47000, что приблизительно составляет 0,1277. Теперь преоб-

разуем это значение в величину угла круговой диаграммы. Полный

разворот окружности имеет 6,283184 рад, следовательно величина

угла для элемента круговой диаграммы, соответствующего январю,

будет составлять 0,1277х6,283184, или около 0,802 рад. Радиусы,

ограничивающие этот угол, на рис. 8.16 обозначены цифрами 0 и

1.

Заметим, что вращение угла осуществляется по часовой

стрелке, в то время как общепринятым является задание углов в

направлении, противоположном направлению вращения часовой

стрелки. На наш взгляд, "чтение" по часовой стрелке является

более естественным для пользователей.

Рисунок 8.16

Начальной границей каждого последующего элемента круговой

диаграммы является конечная граница предшествующего элемента.

Программировать будет проще, если конечную границу каждого эле-

мента круговой диаграммы получать с помощью абсолютного угла,

равного сумме относительных углов всех предшествующих элемен-

тов. Таким образом угловые значения концевых границ всех эле-

ментов круговой диаграммы вычисляются относительно одной на-

чальной границы (радиуса 0 на рис. 8.16). Например, элементу

диаграммы, соответствующему данным за февраль, поставлен в со-

ответствие угол в 1.203 рад. (между радиусами 1 и 2); угол меж-

ду радиусами 2 и 0 составляет 0.802 рад + 1.203 рад, или 2.005

рад.

Относительные размеры и соответствующие угловые значения

остальных элементов круговой диаграммы вычисляются аналогичным

образом. Относительные размеры элементов круговой диаграммы,

соответствующие им углы в радианах и угловые значения для ко-

нечных граничных линий приведены в табл. 8.14. Из нее вы полу-

чите, например, что конечная граница элемента круговой диаграм-

мы для данных за июнь соответствует 6.283 рад или 360 градусов.

Это значение показывает, что был размечен полный круг; конечную

границу элемента круговой диаграммы, соответствующего данным за

июнь, рисовать не надо.

---------------------------------------------------------------

Таблица 8.14. Угловые значения для элементов диаграммы

---------------------------------------------------------------

Месяц Размер элемента диагр. Относит. угол Абс.угол кон.

абсолютный дольный элем. диагр. границы диагр.

---------------------------------------------------------------

Янв 6000 0.1277 0.802 0.802

Фев 9000 0.1915 1.203 2.005

Март 10000 0.2128 1.337 3.342

Апр 6000 0.1277 0.802 4.144

Май 7000 0.1489 0.936 5.080

Июнь 9000 0.1915 1.203 6.283

---------------------------------------------------------------

Как видим, процедура полученя граничных точек элементов

круговой диаграммы не сложна. Вычисления осуществляются по той

же формуле, что и вычисления координат точек окружности (см.

разд. 8.5.1.).

Приступим теперь к размещению меток, которое заключается в

определении координат точек, находящихся вне круговой диаграммы

на биссектрисах относительных углов элементов круговой диаграм-

мы. В качестве начальной линии, относительно которой будем отс-

читываль углы, примем радиус 0 (рис.8.16.). Тогда угол между

биссектрисой какого-либо элемента круговой диаграммы и началь-

ным радиусом (0) равен сумме угла между радиусом 0, начальным

радиусом данного элемента и половиной угла, соответствующего

данному элементу диаграммы. Например, угол, соответствующий

элементу круговой диаграммы, представляющему, данные за фев-

раль, равен 1.203 рад; угол до предыдущей радиальной линии ра-

вен 0.802 рад (как показано в табл. 8.14). Угол до биссектриссы

элемента диаграммы,соответствующего февралю, равен

(0.802 + 1.203 / 2) рад

или 1.404 рад. В табл. 8.15 приведены значения углов до биссек-

трисс элементов диаграммы.

---------------------------------------------------------------

Таблица 8.15. Углы, соответствующие меткам круговой диаграммы

---------------------------------------------------------------

Месяц Угол (рад)

---------------------------------------------------------------

Янв 0.401

Фев 1.404

Март 2.674

Апр 3.743

Май 4.612

Июнь 5.681

---------------------------------------------------------------

Координаты Row и Column полученных таким образом точек ис-

пользуются для вычисления номеров строки и столбца. В графичес-

ком режиме аргументы предиката cursor указываются в виде номе-

ров строки и столбца, как и в случае текстового режима. Следо-

вательно, значения координат 32000х32000 графического экрана

необходимо преобразовать в значения строки и столбца 25х80, ис-

пользуемые для определения положения курсора. Коэффициенты пре-

образования получаются делением 32000 на 25 для строк, и на 80

- для столбцов, что дает соответственно 1280 и 400. Следова-

тельно, формулы преобразования имеют следующий вид:

Char_row = Row / 1280,

Char_col = Column / 400,

где Char_row и Char_col - значения строки и столбца курсора,

Row, Column - координаты графического экрана. (Полученные зна-

чения необходимо округлить до целых).

Описанный в данной главе метод изображения окружности,

применяется также для получения границы круговой диаграммы.

На рис. 8.17 приведена структура программы, результатом

работы которой является круговая диаграмма. Помните, что наибо-

лее удобный и практичный способ реализации программы есть тот,

при котором каждому модулю соответствует отдельное правило.

Правило draw_pie_graph реализует главный модуль программы.

draw_pie_graph :-

make_window,

write_titles,

cut_pie([0.0, 0.802, 2.01, 3.345, 4.147, 5.083]),

cut_pie_labels([0.401, 1.404, 2.674, 3.743, 4.612, 5.681],

["Jan","Feb","Mar","Apr","May","Jun"]),

draw_circle(0.0).

Заметим, что все компоненты правила draw_pie_graph являют-

ся правилами или подмодулями. Такой способ создания модулей яв-

ляется надежным и эффективным.

Рисунок 8.17

Программа PieGraph, приведенная в листинге 8.8, имеет опи-

санную структуру. Правило make_window является несложным. Точно

такое же правило используется в программе LineGraph. Правило

write_titles также имеет аналог в программе LineGraph.

Листинг 8.8

Заметим, что правило cut_pie для вычисления конечных точек

радиусов использует тригонометрические функции, обсуждавшиеся

ранее.

cut_pie([]).

cut_pie([Angle | Other_angles]) :-

Center_row = 15000, Center_col = 11500,

Radius = 5000,

End_row_real = Center_row - Radius*1.40*cos(Angle),

End_col_real = Center_col + Radius*sin(Angle),

real_int(End_row_real,End_row_int),

real_int(End_col_real,End_col_int),

line(Center_row,Center_col,End_row_int,End_col_int,1),

cut_pie(Other_angles).

Значения номера строки умножаются на коэффициент 1.40 для

компенсации видового отношения монитора экрана. Однако различ-

ные экраны имеют различный коэффициент видового отношения, поэ-

тому, для того чтобы получить "настоящую" окружность на экране

дисплея какого-либо компьютера, этот коэффициент, возможно,

придется изменить. Получающиеся вещественнозначные числа преоб-

разуются (и округляются) к целым при помощи правила real_int и

результат используется для изображения радиусов круговой диаг-

раммы.

Правило cut_pie использует метод голова-хвост для доступа

к отдельным элементам списка углов. Обратитесь к гл. 5, если

этот метод недостаточно знаком вам.

Правило put_pie_labels аналогично правилу cut_pie. Заме-

тим, однако, что значения Center_row и Center_col отличаются от

значений, использованных в cut_pie. Точки, соответствующие цен-

трам меток, удалены от центра круга так, что метки месяцев рас-

полагаются равномерно вокруг окружности. Значения 32000х32000

графических координат преобразуются в 25х80 значений столбца и

строки для определения местоположения меток.

Подобно cut_pie, put_pie_labels также использует метод го-

лова-хвост для доступа к элементам списка. Этот предикат, одна-

ко, имеет два списка значений: список углов и список меток.

Подправило draw_circle(A) рисует окружность, являющуюся

границей диаграммы. Это правило выполняется аналогично правилу

draw_ellipse в программе Shapes. Для компенсации видового отно-

шения экрана используется коэффициент 1.40 . На рис. 8.18 пока-

зана круговая диаграмма, получаемая данной программой.

Рисунок 8.18

Упражнения

8.20. Измените программу PieGraph, увеличив размеры круга так,

чтобы метки элементов диаграммы попали внутрь круга. Указание:

Необходимо модифицировать правила, осуществляющие вывод как ра-

диальных линий, так и граничной окружности.

8.21. Измените программу PieGraph, чтобы выводилась круговая

диаграмма для данных, приведенных в упр. 8.16.

8.7.Использование графики черепашки ( Turtle graphics)

Турбо-Пролог обладает широким спектром графических возмож-

ностей, где наряду с рассмотренными можно встретить некое сред-

ство, именуемое графикой черепашки. Из данного раздела станет

ясна разница между традиционной графикой, реализуемой с помощью

абсолютных координат, и графикой черепашки. В первом случае все

координаты отсчитываются от угла рамки экрана и, таким образом,

являются абсолютными. Во втором же, координаты каждого следую-

щего положения курсора вычисляются, основываясь на его предыду-

щем положении и, следовательно, являются относительными. По

опыту известно, что графика, основанная на текущем положении

курсора, т.е. графика черепашки, легче осваивается начинающими

программистами и поэтому чаще используется для обучения.

Проведем некоторую аналогию, из которой, кстати, станет

ясно как появилось такое название графика черепашки.

Представим себе, что по экрану вместо курсора передвигает-

ся маленькая черепашка, у которой к хвосту привязано пишущее

перо. Поднимая и опуская хвост, черепаха поднимает и опускает

пишущее перо. Если перо опущено, то при движении черепахи оно

чертит линию; если перо поднято, то линия отсутствует. Направ-

ление перемещения черепахи может изменяться посредством враще-

ния черепахи, а расстояние, на которое черепаха перемещается,

может быть задано. Предикаты, реализующие графику черепашки,

приведены ниже.

8.7.1. Предикаты графики черепашки

Встроенные предикаты Турбо-Пролога обеспечивают полную

поддержку графики черепашки, таковыми являются предикаты penup,

pendown, pencolor, forward, back, right, left и penpos. Перед

их использованием необходимо перевести экран в графический ре-

жим предикатом graphics.

Предикат penup используется тогда, когда движущаяся чере-

пашка не должна оставлять за собой "след". Данный предикат ар-

гументов не имеет. Предикат pendown противоположен по действию

предикату penup и используется в том случае, когда черепашка

должна оставлять за собой "след".

Предикат pencolor устанавливает цвет "следа" черепахи. Он

имеет вид:

pencolor(Color_number)

где Color_number - целое число, с помощью которого выбирается

один из возможных цветов цветовой палитры (см. табл. 8.7). Нап-

ример, предикат вида pencolor(1) устанавливает серый цвет из

палитры 0. Аналогично, предикат вида pencolor(2) устанавливает

фиолетовый цвет из палитры 1.

Предикат forward используется для передвижения черепахи

вперед на указанное расстояние. Он имеет вид:

forward(Step_size)

где Step_size - числом в диапазоне от 1 до 31999. Предикат back

выполняется аналогично, но перемещает черепаху назад. Например,

предикат вида back(500) передвинет черепаху на 500 единиц на-

зад.В том случае, если черепашка переместится за границу экра-

на, ошибка зафиксирована не будет; однако, все, что было нари-

совано за границей экрана, на экране не появится.

Предикаты right и left используются для вращения черепахи.

Каждый из этих предикатов имеет аргумент, задающий угол в гра-

дусах. Они имеют вид:

left(Angle)

Предикат вида left(45) поворачивает черепаху на 45 граду-

сов влево.

Заметим, что аргумент предикатов left и right задает вра-

щение, отсчитываемое от текущего положения. Другими словами,

этот аргумент определяет угол между новым положением и тем нап-

равлением, по которому двигалась бы черепаха, если бы left и

right не были использованы. Например, предикаты

pendown,

forward(2000),

left(45),

forward(2000)

заставят черепаху нарисовать две линии сектора, с углом 135

градусов (или 180 градусов - 45 градусов) между ними.

Предикат penpos используется для того, чтобы поместить

курсор в задаваемую координатами позицию и "прицелить" его в

заданном направлении. Он имеет вид:

penpos(Row,Column,Angle)

Например, предикат вида penpos(1000,2000,0) помещает чере-

пашку на строку 1000, столбец 2000 и "нацеливает" ее голову в

направлении 0 градусов.

В начале выполнения программы значение угла, соответствую-

щего направлению головы черепахи, принимается А=0 и отвечает

направлению точно вниз - иными словами, направлению увеличения

величины Row. Предикат вида

penpos(3000,15000,180)

помещает черепаху в точку (3000,15000) и ориентирует черепаху

так, что ее голова указывает точно вверх.

Предикат penpos, наряду с указанным выше, может использо-

ваться для определения положения черепахи. Так, если аргумента-

ми penpos являются неозначенные переменные, то penpos присваи-

вает им значения, соответствующие текущему положению и ориенти-

ровке черепашки.

Два следующих примера иллюстрируют использование предика-

тов графики черепашки.

В качестве первого примера попытаемся изобразить верти-

кальный отрезок длинной 8000 единиц и начинающийся в точке

(1000,16000). Направление черепашки в данном случае равно 0

градусов (точно вниз), а величина перемещения - 8000. Следова-

тельно, правило будет иметь вид:

draw_straight_line :-

penpos(1000,16000,0),

pendown,

pencolor(1),

forward(8000).

В качестве второго примера, попытаемся замкнутую фигуру,

начиная с точки (20000,16000). Фигура состоит из прямолинейных

отрезков длинной 1000 единиц. Данная фигура может быть получена

посредством вращения черепашки на 2 градуса вправо после каждо-

го шага, начиная с направления, принятого по умолчанию. Следую-

щие простые правила выполняют данную цель:

draw_figure :-

graphics(2,0,7),

penpos(20000,16000,0),

pendown,

closed_figure(500).

closed_figure(A) :- A >= 30000, !.

closed_figure(Ao) :-

forward(100),

right(2),

A = Ao + 50,

closed_figure(A).

Заметим, что альтернативное утверждение

closed_figure(A) :- A >= 30000, !.

используется для задания условия окончания рекурсивного вызова.

Это правило выполняется успешно, когда присвоенное A значение

больше, чем 30000. Если бы данное альтернативное утверждение

отсутствовало, программа вошла бы в бесконечный цикл из-за на-

личия рекурсивных вызовов closed_figure. Обратитесь к материалу

гл. 4, если данный момент вам не ясен.

8.7.2. Графические рисунки

Предикаты графики черепашки успешно используются для соз-

дания изображений. С их помощью, например, можно создать нес-

ложный рисунок, на котором будут изображены дом и дерево. Прос-

тая программа, реализующая этот замысел, будет содержать следу-

ющее целевое правило:

make_picture :-

setup_graphics,

draw_house,

draw_tree.

Конкретный вид трех компонент целевого правила зависит от

реализации. Программа Picture, приведенная в листинге 8.9,

представляет собой одну из возможных реализаций.

Листинг 8.9

В программе, правило setup_graphics устанавливает белый

фон экрана с черным изображением и окно размером 18 строк на 50

столбцов, окаймленное рамкой.

Правило draw_house рисует дом, составленный из прямолиней-

ных отрезков. Первые четыре строки предиката ответственны за

изображение остова дома (прямоугольника). Следующие две строки

помещают курсор в левый верхний угол остова. Следующие три

строки рисуют крышу (два прямолинейных отрезка, направленных

под углом 45 градусов к горизонтали).

Следующая группа из трех строк помещает черепашку в нижний

левый угол двери (другой прямоугольник). Последующие четыре

строки рисуют дверь.

Правило draw_tree рисует дерево. Это правило состоит из

предикатов, помещающих курсор в основание дерева(первые две

строки) предикатов, изображающих прямолинейную часть дерева

(следующие три строки) и правила draw_circle. Последнее правило

рисует половину окружности, являющуюся частью дерева. Графичес-

кое изображение, создаваемое данной программой, приведено на

рис. 8.19.

Рисунок 8.19

Упражнение

8.22. Выполните программу Picture. Сравните время, затрачивае-

мое на изображение круговой части дерева, с временем построения

линейной части рисунка. Теперь измените программу, изобразив

дерево более тщательно. Используйте линованную бумагу для опре-

деления эскиза дерева.

8.7.3. Абстрактные рисунки. Движущаяся спираль

Предикаты графики черепашки предоставляют пользователю эф-

фективные средства для создания достаточно сложных абстрактных

рисунков. Программа Spiral (листинг 8.10) один из примеров то-

го, что можно сделать при помощи лишь нескольких предикатов.

Листинг 8.10

Графический вывод программы Spiral представляет собой на-

бор прямолинейных отрезков с увеличивающимися длинами. Каждый

последующий отрезок составляет с предыдущим угол 10 градусов.

Спираль начинается в верхнем левом углу экрана, в точке

(1400,1600). После изображения каждого отрезка, центр спирали

перемещается на 100 точек по горизонтали и вертикали.

Правило do_graphics устанавливает черный фон, на который

выводит текст Moving Spiral белого цвета. Правило do_penpos ри-

сует собственно спираль.

Подцель do_penpos(1400,1600,0) передает значения перемен-

ных R0, C0 и A0 правилу, находящемуся в разделе clauses прог-

раммы. Предикат R0 < 1400 налагает ограничение на длину отрез-

ка. Следующие два предиката помещают перо в начальную позицию

(1400,1600) и ориентируют голову черепашки вниз. Предикат

pendown приводит перо в состояние готовности.

Следующие три предиката увеличивают значения координат на

100 точек, а величину угла - на 10 градусов. После чего преди-

каты forward и left рисуют отрезок. Следующий предикат penpos

переводит черепашку в новое положение и придает ей новую ориен-

тацию. Данная последовательность предикатов рекурсивно повторя-

ется до тех пор, пока выполняется ограничение на максимальную

длину отрезка (1400).

На рис. 8.20 показана спираль, полученная с помощью прог-

раммы Spiral. Применяя предикаты графики черепашки можно изоб-

ражать много различных абстрактных объектов; их вид и форма ог-

раничивается лишь вашей фантазией. Следующие упражнения помогут

вам лучше освоить применение предикатов графики черепашки.

Рисунок 8.20

Упражнения

8.23. Выполните программу Spiral. Теперь измените ее так, чтобы

длина отрезков была одинакова. Выполните модифицированную прог-

рамму. Указание: изменение внесите в предикат forward(R).

8.24. Модифицируйте программу Spiral, чтобы спираль начиналась

в нижнем правом углу и двигалась в направлении верхнего левого

угла.

8.8. Использование звука и музыки

Кроме поддержки многооконности и цветной графики, Тур-

бо-Пролог предоставляет звуковые средства. Если программист ис-

пользует какие-либо из средств, описываемых в данной главе, в

своей программе, можно утверждать, что она будет лучше органи-

зована и более дружелюбна по отношению к пользователю. В этом

разделе описываются средства Турбо-Пролога по генерации звука и

их использование в программах.

8.8.1. Предикаты генерации звука

Турбо-Пролог поддерживает два предиката генерации звука:

sound и beep. Предикат beep генерирует звук высокой тональнос-

ти. Его вид прост, поскольку этот предикат параметров не имеет.

Правило на Турбо-Прологе, генерирующее три звуковых сигнала,

есть:

do_beep :-

beep,

beep,

beep.

Правило beep используется для различных целей, например

для того, чтобы привлечь внимание пользователя в ситуации, ког-

да требуется ввод какой-либо информации либо чтобы уведомить о

наличии ошибочного состояния.

Эти и другие функции реализуются более эффективно, если

пользователь уверенно овладел всем спектром средств Турбо-Про-

лога по генерации звука. Турбо-Пролог позволяет производить

сигналы во всем диапазоне слышимых человеком звуков. Предикат

sound имеет следующий вид:

sound(Duration,Frequency)

Значение параметра Duration задает длительность звукового

сигнала в сотых долях секунды. Значение параметра Frequency оп-

ределяет частоту генерируемого звука (высота звука). После

весьма непродолжительной практики вы так овладеете предикатом

sound, что сможете с его помощью воспроизводить любую из извес-

тных вам мелодий классической и современной музыки.

Даже простые музыкальные фрагменты сделают любую программу

более интересной и информативной. Вы без промедления будете от-

вечать на все запросы на ввод какой-либо информации, изменяя

продолжительность и частоту звучания, сможете генерировать раз-

личные звуки, с помощью которых будете знать о различных этапах

выполнения программы. Следующее правило иллюстрирует этот ме-

тод.

make_a_note :-

sound(5,165),

sound(10,247).

Данное правило генерирует ноту ми в течение 0.05 с., и но-

ту си - 0.10 с.

Звуки, генерируемые в данном примере, выбираются из диапа-

зона музыкальных частот. В табл. 8.16 представлены ноты, высота

которых соответствует первой октаве; этот диапазон приятен для

слуха. Первый столбец задает музыкальную ноту, второй - частоту

в колебаниях в секунду.

---------------------------------------------------------------

Таблица 8.16. Музыкальные ноты и соответствующие частоты

---------------------------------------------------------------

Нота Частота

---------------------------------------------------------------

До 262

До-диез 278

Ре 294

Ре-диез 302

Ми 330

Фа 350

Фа-диез 370

Си 392

Си-диез 416

Ля 440

Ля-диез 466

Соль 494

До 524

---------------------------------------------------------------

8.8.2. Музыкальные фрагменты

Используя данные табл. 8.16, вы сможете вставлять в прог-

рамму музыкальные фрагменты. Музыкальный фрагмент - короткая,

энергичная и легко распознаваемая последовательность нот. Таких

фрагментов существует достаточно много, но вы, наверное, захо-

тите создать свои собственные, чтобы придать программе черты

"неповторимости". Ниже приведенные правила подтверждают тот

факт, что создать музыкальный фрагмент не сложно. Правило, ге-

нерирующее фрагмент, имеет вид:

do_yea_team :-

sound(4,392),

sound(4,440),

sound(4,494),

sound(8,440),

sound(4,494),

sound(12,392).

В следующем разделе будет показано, что не только этот, но

и другие музыкальные фрагменты могут быть включены в программы

на ТУРБО-ПРОЛОГе столь же легко.

8.8.3. Несложная программа компьютерного обучения с

музыкальными фрагментами

Теперь, когда вы научились создавать музыкальные фрагмен-

ты, то можете включать их в свои программы. В качестве примера,

рассмотрим несложную программу компьютерного обучения (Computer

Assisted Instruction, CAI), сложению целых чисел. Схема прог-

раммы базируется на следующих процедурах:

1. Используя генератор случайных чисел Турбо-Пролога, по-

лучить два целых числа и вычислить их сумму.

2. Вывести на экран те же два числа. Предложить пользова-

телю вычислить их сумму. Сравнить сумму, вычисленную пользова-

телем, с полученной ранее. Если они равны, перейти к шагу 3. В

противном случае перейти к шагу 4.

3. Вывести сообщение, уведомляющее пользователя о том, что

его ответ правилен. Перейти к шагу 1.

4. Вывести пользователю сообщение о неправильности ответа.

Перейти к шагу 2.

На рис. 8.21 приведена структурная диаграмма программы

компьютерного обучения, реализующей данную схему. Главный мо-

дуль do_cai является целью программы. Он осуществляет вызов мо-

дуля make_exercise_set. Этот модуль, в свою очередь, вызывает

два других модуля: gen_rand_num, генерирующий два случайных це-

лых числа, и test_and_reward, принимающий ответ пользователя и

проверяющий его правильность. Если ответ правилен,

test_and_reward вызывает модуль say_good_work. Если ответ неп-

равилен, он вызывает модуль say_more_work.

Рисунок 8.21

Правило say_good_work выводит сообщение пользователю о

правильном ответе и исполняет музыкальный фрагмент, соответст-

вующий "успеху" пользователя. Аналогично, правило say_more_work

выводит пользователю сообщение об ошибочности ответа, после че-

го раздаются три звуковых сигнала.

Программа GoodWork (листинг 8.11) реализует рассмотренную

программу компьютерного обучения. Ее целью является do_cai:

do_cai :-

makewindow(1,7,7,"CAI SIMPLE ADDITIONS",

2,20,20,34),

nl, write("Here are the exercises!"),

make_exercise_set(3),

nl, write(" Have fun, bye!"),

nl, write("Press the space bar"),

readchar(_),

removewindow.

Это правило создает черно-белое окно, имеющее граничную

рамку и состоящее из 20 строк и 34 столбцов. Правило do_cai вы-

зывает модуль make_exercise_set, выполняющий собственно упраж-

нения на сложение чисел. При возврате из этого модуля, главный

модуль приглашает пользователя нажать клавишу пробела, после

чего программа заканчивается.

Листинг 8.11

Правило make_exercise_set задает три контрольных вопроса.

Для каждого вопроса правилом gen_rand_num генерируется два слу-

чайных числа. Встроенным предикатом Турбо-Пролога, генерирующим

случайные числа, является random(Y), где Y - переменная, прини-

мающая вещественные значения. Данный предикат присваивает пере-

менной, являющейся аргументом, значение случайного числа боль-

шее либо равное 0, но меньшее 1. Выражение

Y*5 + 1

определяет случайные вещественные числа от 1 до 6, в зависимос-

ти от присвоенного Y значения. Чтобы присвоить переменной X

значение случайного целого числа в диапазоне от 1 до 5, исполь-

зуется правило:

X = Y*5 + 1

Так как аргумент предиката gen_rand_num объявляется целым

в разделе predicates, X получает случайное целочисленное значе-

ние в диапазоне от 1 до 5. Система округляет вещественное зна-

чение до ближайшего целого.

Два случайных числа, сгенерированных описанным образом,

выводятся на экран. Модуль make_exercise_set использует подпра-

вило C = A + B для вычисления суммы (S) двух чисел. Затем поль-

зователю предлагается ввести значение суммы двух случайных чи-

сел; значение, введенное пользователем, присваивается перемен-

ной U. Ответ пользователя оценивается правилом test_and_reward.

Если C = U, то ответ пользователя правилен. В противном случае

ответ неправилен.

На рис. 8.22 показано, как выглядит экран в случае пра-

вильного ответа. Сообщение, выводимое в окно GoodWork, несом-

ненно обнадеживает пользователя, а приятные звуки, раздающиеся

а это время, укрепляют его уверенность в собственной правоте.

На рис. 8.23 показано, как выглядит экран в случае неправильно-

го ответа. Сообщение в серьезном и обнадеживающем тоне указыва-

ет пользователю, что ему необходимо совершенствоваться. Звуки в

данном случае предназначены для стимулирования прользователя к

лучшей работе.

Использование нескольких окон упрощает взаимодействие

пользователя с программой. Такая простота очень желательна. Ис-

пользование музыкальных фрагментов как поощрение весьма эффек-

тивно, особенно для молодых пользователей. Указание при помощи

музыкальных средств на необходимость дальнейшей работы или сти-

мулирование хорошей работы, использующее музыкальные фрагменты,

хорошо действует на учащихся.

Рисунок 8.22

Рисунок 8.23

Упражнения

8.25. Выполните программу GoodWork, и проверьте все возможные

варианты ответов, т.е. наряду с правильными, давайте и непра-

вильные.

8.26. Измените программу так, чтобы она выводила правильный от-

вет в дополнение к сообщению You need improvement. Надеемся,

что это также поможет пользователю в обучении.

8.27. Измените программу так, чтобы складывались числа в диапа-

зоне от 20 до 80. Указание: Модифицируйте предикат (X=Y*5+1).

Заключение

В этой главе описаны предикаты Турбо-Пролога для работы с

окнами, показано, что встроенные предикаты ввода-вывода исполь-

зуются и для окон. Описано использование предиката cursor для

вывода текста в любое место окна. Показано, что в совокупности,

данные предикаты позволяют писать программы с удобным и хорошо

организованным выводом на экран. Многооконность, перекрывающие-

ся окна и оконные меню теперь находятся в вашем распоряжении.

В данной главе также производится ознакомление с элемента-

ми компьютерной графики и с графическими средствами, поддержи-

ваемыми Турбо-Прологом. Описывается взаимодействие аргументов

предикатов graphics, makewindow, dot и line, управляющих цвета-

ми и другими атрибутами изображения на графическом экране.

Рассказывается, как посредством предикатов line и dot соз-

давать графические изображения в программе. Применяя эти навы-

ки, вы получаете возможность использования простых средств де-

ловой графики, включая линейные, столбиковые и круговые диаг-

раммы. Также излагаются математические основы, используемые при

переводе входных данных в форму, подходящую для графического

изображения.

В данной главе описывается также графика черепашки. Иллюс-

трируется использование предикатов графики черепашки в програм-

мах, создающих графические изображения правильных объектов, а

также более сложные, абстрактные рисунки.

Наконец, описываются предикаты Турбо-Пролога, генерирующие

звук, и их использование. За счет их в программы можно включать

музыкальные фрагменты. Также приведены некоторые методы, ис-

пользуемые при написании дружелюбных к пользователю программ

компьютерного обучения, в которых применяются несколько окон и

звуковые сигналы, придающие программам высоко профессиональный

характер.

Надписи на рисунках ГЛАВЫ 8.

Рис 8.1 Окно Турбо-Пролога, имеющее наибольшие размеры

(25 строк * 80 столбцов).

Рис 8.2 Окно средних размеров (16 строк * 40 столбцов).

Рис 8.3 Окно текста, выводимое первым в программе Window.

Рис 8.4 Окно текста, выводимое вторым в программе Window.

Рис 8.5 Четыре неперекрывающихся окна, создаваемых

программой Message.

Рис 8.6 Вид экрана после удаления двух низших окон.

Рис 8.7 Четыре окна, создаваемых программой Overlap.

Рис 8.8 Структурная диаграмма системы меню.

Рис 8.9 Окна, создаваемые программой Menu.

Рис 8.10 Математическая зависимость между радиусом, центром и ок-

ружностью.

Рис 8.11 Структурная диаграмма программы Shapes.

Рис 8.12 Простые фигуры, изображаемые предикатами dot и line.

Рис 8.13 Оси координат и одна точка линейной диаграммы.

Рис 8.14 Простая линейная диаграмма.

Рис 8.15 Простая столбиковая диаграмма.

Рис 8.16 Методика, применяемая для построения круговой диаграммы.

Рис 8.17 Структурная диаграмма программы PieGraph.

Рис 8.18 Вид вывода программы PieGraph.

Рис 8.19 Вид вывода программы Picture.

Рис 8.20 Вид вывода программы Spiral.

Рис 8.21 Структурная диаграмма простой программы компьютерного

обучения.

Рис 8.22 Вид вывода программы компьютерного обучения в случае

правильного ответа.

Рис 8.23 Вид вывода программы компьютерного обучения в случае

неправильного ответа.

-----------------------------------------------------------------

Листинг 8.1

/* Программа: Window Файл: PROG0801.PRO*/

/* Назначение: Создание окна в центре экрана */

predicates

make_window_and_write

goal

make_window_and_write.

clauses

make_window_and_write:-

makewindow(1,7,7,

" A Message Window",

6,20,14,40),

cursor(3,14),

write("New House"),

cursor(5,10),

write("When an old house"),

cursor(6,10),

write("gets new paint,"),

cursor(7,10),

write("it is a new house."),

cursor(9,16),

write("anonymous poet"),

nl,nl,

write("To read another message,"),nl,

write("press the space bar."),

readchar(_),

clearwindow,

cursor(2,5),

write("? ? ? ? ? ? ? ? ?"),

cursor(4,10),

write("The future of arts"),

cursor(5,10),

write("in the electronic age"),

cursor(6,10),

write("is hidhly debatable."),

cursor(9,7),

write("To exit, press the space bar"),

readchar(_),

removewindow,

exit.

----------------------------------------------------------------------

----------------------------------------------------------------------

Листинг 8.2

/* Программа: Message Файл: PROG0802.PRO */

/* Назначение: Создание четырех отдельных окон, имеющих рамки */

/* и работающих с черно-белым текстом */

predicates

make_windows_and_write

goal

make_windows_and_write.

clauses

make_windows_and_write:-

makewindow(1,7,7,

"Message area #1",

4,4,8,34),

nl,write("Modus ponens"),

nl,write(" A basic rule of logic that"),

nl,write("asserts IF a condition is true,"),

nl,write("THEN an action is true."),nl,

makewindow(2,7,7,

"Message area #2",

4,42,8,34),

nl,write("Himico"),

nl,write(" The name chousen by Japanese"),

nl,write("scientists for their parallel"),

nl,write("PROLOG programming language."),nl,

makewindow(3,7,7,

"Message area #3",

12,4,8,34),

nl,write("Unification"),

nl,write(" A term used in Prolog to"),

nl,write("indicate the matching of"),

nl,write("patterns and assigning values."),nl,

makewindow(4,7,7,

"Message area #4",

12,42,4,34),

nl,write("Knowledgebase System"),

nl,write(" A computer program to do"),

nl,write("symbolic processing of"),

nl,write("knowledgebase."),nl,

write("To exit ,press the space bar"),

readchar(_),

removewindow,

write("To exit ,press the space bar"),

readchar(_),

removewindow,

write("To exit ,press the space bar"),

readchar(_),

removewindow,

write("To exit ,press the space bar"),

readchar(_),

removewindow,

exit.

----------------------------------------------------------------------

----------------------------------------------------------------------

Листинг 8.3

/* Программа: Overlar Файл: PROG0803.PRO */

/* Назначение: Создание перекрывающихся окон */

predicates

make_windows_write_text

goal

make_windows_write_text.

clauses

make_windows_write_text:-

makewindow(1,7,7,

"Life of a star",3,12,10,40),

cursor(3,8),

write("A BLACK HOLE APPEARS."),nl,

makewindow(2,7,7,

"Life of a star",5,14,10,40),

shiftwindow(2),

cursor(3,12),

write("THE STAR BURNS."),nl,

makewindow(3,7,7,

"Life of a star",7,16,10,40),

shiftwindow(3),

cursor(3,11),

write("THE STAR SHINES"),nl,

makewindow(4,7,7,

"Life of a star",9,18,10,40),

shiftwindow(4),

cursor(3,11),

write("A STAR IS BORN"),nl,

cursor(6,4),

write("Press the space bar"),

readchar(_),

removewindow,

cursor(6,2),

write("Press the space bar"),

readchar(_),

removewindow,

cursor(6,2),

write("Press the space bar"),

readchar(_),

removewindow,

cursor(7,2),

write("Press the space bar"),

readchar(_),

removewindow,

exit.

----------------------------------------------------------------------

----------------------------------------------------------------------

Листинг 8.4

/* Программа: Menu Файл: PROG0804.PRO */

/* Назначение: Иллюстрация создания меню при помощи окон */

predicates

repeat

process(integer)

show_menu

run_file_utility

goal

run_file_utility.

clauses

run_file_utility:-

show_menu,

nl,write("Press the SPACE BAR"),

readchar(_),

exit.

repeat.

repeat :- repeat.

show_menu :-

repeat,

makewindow(1,7,7,

"Main Menu",4,10,16,36),

nl,

write(" Menu Utilities"),nl,nl,

write(" 0 Exit"),nl,

write(" 1 Delete file"),nl,

write(" 2 Rename file"),nl,

write(" 3 Create file"),nl,

write(" 4 Exit to PC DOS"),nl,nl,

write("Please enter your choice:(0-4)"),

readint(X),

X < 5,

process(X),

X = 0, !.

process(0):-

nl,write(" You exit the menu. Bye!"),nl.

process(1):-

makewindow(2,7,7,

"File Deletion",12,36,10,36),

write("This is file deletion utility."),

nl,nl,

write("This process will be"),nl,

write("implemented later."),nl,nl,

write("When ready, press the space bar."),

readchar(_),

removewindow.

process(2):-

makewindow(3,7,7,

"File Renaming",10,40,10,36),

write("This is file renaming utility."),

nl,nl,

write("This process will be"),nl,

write("implemented later."),nl,nl,

write("When ready, press the space bar."),

readchar(_),

removewindow.

process(3):-

makewindow(4,7,7,

"File Creation",5,10,15,60),

write("This is file creation utility."),

nl,nl,

write("This process will be"),nl,

write("implemented later."),nl,nl,

write("When ready, press the space bar."),

readchar(_),

removewindow.

process(4):-

makewindow(5,7,7,

"Temp exit to PC DOS",10,40,10,35),

write("You exit to PC DOS."),nl,

write("See you later !"),nl,nl,

write("When ready, press the space bar."),

readchar(_),

removewindow.

----------------------------------------------------------------------

----------------------------------------------------------------------

Листинг 8.5

/* Программа: Shapes Файл: PROG0805.PRO */

/* Назначение: Изображение простых фигур посредством черно-белых */

/* окон и графики */

predicates

draw_figures

make_window

write_captions

draw_rectangle

draw_triangle

draw_ellipse(real)

real_int(real,integer)

goal

draw_figures.

clauses

draw_figures:-

make_window,

write_captions,

draw_rectangle,

draw_triangle,

draw_ellipse(0.02),

write("Press a key."),

readchar(_),

exit.

make_window:-

graphics(2,0,7),

makewindow(1,7,7,

" REGULAR SHAPES",

1,10,23,60).

write_captions:-

cursor(4,10),write("RECTANGLE"),

cursor(7,38),write("TRIANGLE"),

cursor15,9),write("ELLIPSE"),

cursor(14,29),

write("Use 'line' predicate"),

cursor(16,29),

write("and 'dot' predicate"),

cursor(20,4).

draw_rectangle:-

line(2000,2000,2000,10000,1),

line(2000,10000,9000,10000,1),

line(9000,10000,9000,2000,1),

line(9000,2000,2000,2000,1).

draw_triangle:-

line(12000,12000,12000,20000,1),

line(12000,20000,4000,18000,1),

line(4000,18000,12000,12000,1).

draw_ellipse(A):-

A >= 6.28,!.

draw_ellipse(A):-

Center_row= 20000, Center_col = 5000,R=3600,

Row_r = Center_row - R * cos(A),

Column_r = Center_col + R * sin(A),

real_int(Row_r,Row),real_int(Column_r,Column),

dot(Row,Column,1),

A1 = A + 0.02,

draw_ellipse(A1).

real_int(R,I):- R = I.

----------------------------------------------------------------------

----------------------------------------------------------------------

Листинг 8.6

/* Программа: LineGraph Файл: PROG0806.PRO */

/* Назначение: Вывод простой линейной диаграммы */

domains

predicates

draw_line_graph

prompt_exit

goal

draw_line_graph,

prompt_exit.

clauses

draw_line_graph:-

graphics(2,0,7),

makewindow(1,7,7,

"Line Graph",

2,10,23,60),

cursor(1,13),

write(MID-WEST BEER DISTRIBUTORS, INC."),

cursor(2,15),

write("Sales:January - June,1986"),

line(16000,3000,16000,20000,1),

line(16000,3000,4000,3000,1),

cursor(13,11),write("Jan"),

cursor(13,16),write("Feb"),

cursor(13,21),write("Mar"),

cursor(13,26),write("Apr"),

cursor(13,31),write("May"),

cursor(13,36),write("Jun"),

cursor(15,20),

write("M O N T H S"),

cursor(17,15),

write("Sales: in units of $1000K"),

line(10000,5000,7000,7000,1),

line(7000,7000,6000,9000,1),

line(6000,9000,10000,11000,1),

line(10000,11000,9000,13000,1),

line(9000,13000,7000,15000,1),

cursor( 4,3),write("10 -"),

cursor( 6,3),write(" 8 -"),

cursor( 8,3),write(" 6 -"),

cursor(10,3),write(" 4 -"),

cursor(12,3),write(" 2 -").

prompt_exit:-

cursor(19,35),

write("Press the SPACE BAR."),

readchar(_),

removewindow,

exit.

----------------------------------------------------------------------

----------------------------------------------------------------------

Листинг 8.7

/* Программа: BarGraph Файл: PROG0807.PRO */

/* Назначение : Изображение простой столбиковой диаграммы */

predicates

draw_bar_graph

prompt_exit

goal

draw_bar_graph,

prompt_exit.

clauses

draw_bar_graph:-

graphics(2,1,7),

makewindow(1,7,7,

"Bar Graph",2,10,23,60),

/* вывод заголовка и подзаголовка */

cursor(1,13),

write("MID-WEST BEER DISTRIBUTORS, INC."),

cursor(2,15),

write("Sales:January - June, 1986"),

/* Вывод осей и помещение меток */

line(16000,3000,16000,20000,1),

line(1600,3000,4000,3000,1),

cursor(13,12),write("Jan"),

cursor(13,17),write("Feb"),

cursor(13,22),write("Mar"),

cursor(13,27),write("Apr"),

cursor(13,32),write("May"),

cursor(13,37),write("Jun"),

cursor(15,20),

write("M O N T H S"),

cursor(17,15),

write("Sales: in units of $1000K"),

/* вывод столбиков, соответствующих данным*/

line(16000,5000,10000,5000,1),

line(16000,5500,10000,5500,1),

line(10000,5000,10000,5500,1),

line(16000,7000,7000,7000,1),

line(16000,7500,7000,7500,1),

line(7000,7000,7000,7500,1),

line(16000,9000,6000,9000,1),

line(16000,9500,6000,9500,1),

line(6000,9000,6000,9500,1),

line(16000,11000,10000,11000,1),

line(16000,11500,10000,11500,1),

line(10000,11000,10000,11500,1),

line(16000,13000,9000,13000,1),

line(16000,13500,9000,13500,1),

line(9000,13000,9000,13500,1),

line(16000,15000,7000,15000,1),

line(16000,15500,7000,15500,1),

line(7000,15000,7000,15500,1),

/* вывод меток вертикальной шкалы отсчета*/

cursor( 4,2),write(10-"),

cursor( 6,2),write( 8-"),

cursor( 8,2),write( 6-"),

cursor(10,2),write( 4-"),

cursor(12,2),write( 2-").

/* правило, определяющее приглашение к выходу */

prompt_exit:-

cursor(19,38),

write("Press the SPACE BAR."),

readchar(_),

removewindow,

exit.

----------------------------------------------------------------------

----------------------------------------------------------------------

Листинг 8.8

/* Программа: PieGraph Файл: PROG0808.PRO */

/* Назначение: Вывод круговой диаграммы при помощи */

/* предикатов работы с окнами и графикой */

domains

real_list = real*

string_list = string*

predicates

draw_pie_graph

make_window

write_titles

cut_pie(real_list)

put_pie_labels(real_list,string_list)

draw_circle(real),

real_int(real,integer)

goal

draw_pie_graph,

cursor(20,2),

write("Press the SPACE BAR"),

readchar(_),

exit.

clauses

draw_pie_graph:-

make_window,

write_titles,

cut_pie([0.0, 0.802, 2.01, 3.345, 4.147, 5.083]),

put_pie_labels([0.401, 1.404, 2.674, 3.743, 4.612, 5.681],

["Jan","Feb","Mar","Apr","May","Jun"]),

draw_circle(0.0).

make_window:-

graphics(2,0,7),

makewindow(1,7,7,"Pie Graph",1,10,23,60).

write_titles:-

cursor(1,13),

write("MID-WEST BEER DISTRIBUTORS, INC."),

cursor(2,16),

write("Sales: First Quarter, 1986").

cut_pie([]).

cut_pie([Angle|Other_angles]):-

Center_row = 15000,Center_col = 11500,

Radius = 5000,

End_row_real = Center_row - Radius * 1.40 * cos(Angle),

End_col_real = Center_col + Radius * sin(Angle),

real_int(End_row_real,End_row_int),

real_int(End_col_real,End_col_int),

line(Center_row,Center_col,End_row_int,End_col_int,1),

cut_pie(Other_angle).

put_pie_labels([],[]).

put_pie_labels([Angle|Other_angles],

[Label|Other_labels] ):-

Center_row = 14500,Center_col = 11000,

Radius = 6500,

Label_row = Center_row - Radius * 1.40 * cos(Angle),

Label_col = Center_col + Radius * sin(Angle)

Row_real = Label_row / 1280, Col_real = Label_col / 400,

real_int(Row_real,Row), real_int(Col_real,Col),

cursor(Row,Col),

write(Label),

put_pie_labels(Other_angles,Other_labels).

draw_circle(Angle) :- Angle >= 6.28, !.

draw_circle(Angle) :-

Center_row = 15000, Center_col = 11500, Radius = 5000,

Dot_row_real = Center_row - Radius * 1.40 * cos(Angle),

Dot_col_real = Center_col + Radius * sin(Angle),

real_int(Dot_row_real,Dot_row),

real_int(Dot_col_real,Dot_col),

dot(Dot_row,Dot_col,1),

Angle1 = Angle + 0.02,

draw_circle(Angle1).

real_int(Re,In) :- Re = In.

----------------------------------------------------------------------

----------------------------------------------------------------------

Листинг 8.9

/* Программа: House Файл: PROG0809.PRO */

/* Назначение: Показывает использование предикатов графики, */

/* связанной с курсором */

predicates

make_picture

setup_graphics

draw_house

draw_tree

draw_hemisphere(integer)

goal

make_picture.

clauses

make_picture:-

setup_graphics,

draw_house,

draw_tree,

cursor(16,40),

write("Press the SPACE BAR"),

readchar(_),

exit.

setup_graphics:-

graphics(2,0,7),

makewindow(1,1,7,

"A Little House",1,5,22,75).

draw_house:-

pendown,

left(90),forward(7000),right(90),

forward(5000),right(90),forward(7000),

right(90),forward(5000),

penup,

right(180),forward(5000),

pendown,

left(45),forward(5000),left(90),

forward(5000),right(135),

penup,

back(5000),right(90),forward(3000),

left(90),

pendown,

forward(3000),right)90),

forward(1000),right(90),forward(3000),

right(90).

draw_tree:-

penup,

forward(9020),right(90),

pendown,

forward(9020),right(90),forward(2750),

back(5580),left(90),

draw_hemisphere(0).

draw_hemisphere(Count) :- Count >= 360.

draw_hemisphere(Count) :-

forward(50),right(1),

Count1 = Count + 2,

draw_hemisphere(Count1).

----------------------------------------------------------------------

----------------------------------------------------------------------

Листинг 8.10

/* Программа: Spiral Файл: PROG0810.PRO */

/* Назначение: изображение передвигающейся спирали */

predicates

do_graphics

do_penpos(integer,integer,integer)

goal

do_graphics.

clauses

do_graphics:-

graphics(2,0,7),

do_penpos(1400,1600,0),

cursor(20,60),

write("MOVING SPIRAL"),

cursor(23,1),

write("Press the SPACE BAR"),

readchar(_).

do_penpos(R0,_,_) :- R0 >= 14000.

do_penpos(R0,C0,A0) :-

penpos(R0,C0,A0),

pendown,

R = R0 + 100,

C = C0 + 100,

A = A0 + 10,

forward(R),left(A),

penpos(R,C,A),

do_penpos(R,C,A).

----------------------------------------------------------------------

----------------------------------------------------------------------

Листинг 8.11

/* Программа: GoodWork Файл: PROG0811.PRO */

/* Назначение: Обучение простому сложению */

predicates

gen_rand_num(integer)

say_good_work

say_more_work

test_and_reward(integer,integer)

make_exercise_set(integer)

do_cai

goal

do_cai.

clauses

gen_rand_num(X):-

random(Y),

X = Y * 5 + 1.

say_good_work:-

makewindow(2,7,7,

"Good Work",12,40,8,30),

nl,write("You are right."),nl,nl,

write(" LISTEN TO THE MUSIC !"),nl,nl,

sound(4,262),sound(4,350),

sound(4,440),sound(8,516),

sound(4,440),sound(12,516),

nl,nl,write("Press space bar"),

readchar(_),

removewindow.

say_more_work:-

makewindow(3,7,7,

"More Work",14,6,7,28),

write("You need improvement."),nl,nl,

write(" BEEP, BEEP,BEEP !"),nl,nl,

beep,beep,beep,

write("Press space bar"),

readchar(_),

removewindow.

test_and_reward(C,U) :-

C = U,

say_good_work.

test_and_reward(C,U) :-

C <> U,

say_more_work.

make_exercise_set(0) :- !.

make_exercise_set(Count):-

gen_rand_num(A),

nl,write("1st. number is ",A),nl,

gen_rand_num(B),

write("2nd. number is ",B),nl,

C = A + B,

write("What is the sum ?"),nl,

readint(U),

test_and_reward(C,U),

Newcount = Count - 1,

make_exercise_set(Newcount).

do_cai:-

makewindow(1,7,7,"CAI SIMPLE ADDITIONS",2,20,20,34),

nl,write("Here are the exercises !"),

make_exercise_set(3),

nl,write(" Have fun, bye !"),

nl,write("Press space bar"),

readchar(_),

removewindow.

-------------------------------------------------------------

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]