Чтение онлайн

на главную - закладки

Жанры

Шрифт:

7.6.1 Администратор экрана

Вначале было намерение написать администратор экрана на C (а не на С++), чтобы подчеркнуть разделение уровней реалзации. Это оказалось слишком утомительным, поэтому пришлось пойти на компромисс: используется стиль C (нет функций члнов, виртуальных функций, определяемых пользователем операций и т.п.), однако применяются конструкторы, надлежащим образом описываются и проверяются параметры функций и т.д. Оглядывясь назад, можно сказать, что администратор экрана очень пхож на C программу, которую потом модифицировали, чтобы вопользоваться средствами С++ не переписывая все полностью.

Экран представляется как двумерный массив символов, работу с которым осуществляют функции put_point и put_line, использующие при обращении с экраном структуру point:

// файл screen.h

const XMAX=40, YMAX=24;

struct point (* int x,y; point (**) point(int a, int b) (* x=a; y=b; *) *);

overload put_point; extern void put_point(int a, int b); inline void put_point(point p) (* put_point(p.x,p.y); *)

overload put_line; extern void put_line(int, int, int, int); inline void put_line(point a, point b) (* put_line(a.x,a.y,b.x,b.y); *)

extern void screen_init; extern void screen_refresh; extern void screen_clear;

#include «stream.h»

Перед первым использованием функции put экран надо инциализировать с помощью screen_init, а изменения в структре данных экрана отображаются на экране только после вызова screen_refresh. Как увидит пользователь, это «обновление» («refresh») осуществляется просто посредством печати новой копии экрана под его предыдущим вариантом. Вот функции и оределения данных для экрана:

#include «screen.h» #include «stream.h»

enum color (* black='*', white=' ' *);

char screen[XMAX][YNAX];

void screen_init (* for (int y=0; y«YMAX; y++) for (int x=0; x«XMAX; x++) screen[x][y] = white; *)

Точки печатаются, только если они есть на экране:

inline int on_screen(int a, int b) (* return 0«=a amp; amp; a«XMAX amp; amp; 0«=b amp; amp; b«YMAX; *)

void put_point(int a, int b) (* if (on_screen(a,b)) screen[a][b] = black; *)

Для рисования линий используется функция put_line:

void put_line(int x0, int y0, int x1, int y1) /* Строит линию от (x0,y0) до (x1,y1). Строится линия b(x-x0) + a(y-y0) = 0. Минимизирует abs(eps), где eps = 2*(b(x-x0)+ a(y-y0)). См. Newman and Sproull: ``Principles of Interactive Computer Graphics'' McGraw-Hill, New York, 1979, pp 33-44. */ (* register dx = 1; int a = x1 – x0; if (a « 0) dx = -1, a = -a; register dy = 1; int b = y1 – y0;

if (b « 0) dy = -1, b = -b; int two_a = 2*a; int two_b = 2*b; int xcrit = -b + two_a; register eps = 0; for (;;) (* put_point(x0,y0); if(x0==x1 amp; amp; y0==y1) break; if(eps „= xcrit) x0 += dx, eps += two_b; if(eps“=a !! a«=b) y0 += dy, eps -= two_a; *) *)

Предоставляются функции для очистки экрана и его обноления:

void screen_clear (* screen_init; *) // очистка

void screen_refresh // обновление (* for (int y=YMAX-1; 0«=y; y–) (* // сверху вниз for (int x=0; x«XMAX; x++) // слева направо cout.put(screen[x][y]); cout.put('\n'); *) *)

Функция ostream::put применяется для печати символов как символов; ostream::operator«« печатает символы как млые целые. Пока что вы может представлять себе, что эти опрделения доступны только в откомпилированном виде, который вы изменить не можете.

7.6.2 Библиотека фигур

Нам нужно определить общее понятие фигуры (shape). Это надо сделать таким образом, чтобы оно использовалось (как бзовый класс) всеми конкретными фигурами (например, кругами и квадратами), и так, чтобы любой фигурой можно было манипулровать исключительно через интерфейс, предоставляемый классом shape:

struct shape (* shape (* shape_list.append(this); *)

virtual point north (*return point(0,0);*) // север virtual point south (*return point(0,0);*) // юг virtual point east (*return point(0,0);*) // восток virtual point neast (*return point(0,0);*)//северо-восток virtual point seast (*return point(0,0);*) // юго-восток

virtual void draw (**); // нарисовать virtual void move(int, int) (**); // переместить *);

Идея состоит в том, что расположение фигуры задается с помощью move, и фигура помещается на экран с помощью draw. Фигуры можно располагать относительно друг друга, ипользуя понятие точки соприкосновения, и эти точки перечислются после точек компаса (сторон света). Каждая конкретная фигура определяет свой смысл этих точек, и каждая определяет способ, которым она рисуется. Для экономии места здесь на смом деле определяются только необходимые в этом примере строны света. Конструктор shape::shape добавляет фигуру в список фигур shape_list. Этот список является gslist, то есть, одним из вариантов обобщенного односвязанного списка, определенного в #7.3.5. Он и соответствующий итератор были

сделаны так:

typedef shape* sp; declare(gslist,sp);

typedef gslist(sp) shape_lst; typedef gslist_iterator(sp) sp_iterator;

поэтому shape_list можно описать так:

shape_lst shape_list;

Линию можно построить либо по двум точкам, либо по точке и целому. В последнем случае создается горизонтальная линия, длину которой определяет целое. Знак целого указывает, каким концом является точка: левым или правым. Вот определение:

class line : public shape (* /* линия из 'w' в 'e' north определяется как ``выше центра и на север как до самой северной точки'' */ point w,e; public: point north (* return point((w.x+e.x)/2,e.y«w.y?w.y:e.y); *)

point south (* return point((w.x+e.x)/2,e.y«w.y?e.y:w.y); *)

void move(int a, int b) (* w.x += a; w.y += b; e.x += a; e.x += b; *) void draw (* put_line(w,e); *)

line(point a, point b) (* w = a; e = b; *) line(point a, int l) (* w = point(a.x+l-1,a.y); e = a; *) *);

Аналогично определяется прямоугольник rectangle:

class rectangle : public shape (* /* nw – n – ne ! ! ! ! w c e ! ! ! ! sw – s – se */ point sw,ne; public: point north (* return point((sw.x+ne.x)/2,ne.y); *) point south (* return point((sw.x+ne.x)/2,sw.y); *) point neast (* return ne; *) point swest (* return sw; *) void move (int a, int b) (* sw.x+=a; sw.y+=b; ne.x+=a; ne.y+=b; *) void draw; rectangle(point, point); *);

Прямоугольник строится по двум точкам. Код усложняется из-за необходимости выяснять относительное положение этих тчек:

rectangle::rectangle(point a, point b); (* if (a.x «= b.x) (* (* sw = a; ne = b; *) else (* sw = point(a.x,b.y); ne = point(b.x,a.y); *) *) else (* if (a.y «= b.y) (* sw = point(b.x,a.y); ne = point(a.x,b.y); *) else (* sw = b; ne = a; *) *) *)

Чтобы построить прямоугольник, строятся четыре его строны:

void rectangle::draw; (* point nw(sw.x,ne.y); point se(ne.x,sw.y); put_line(nw,ne); put_line(ne,se); put_line(se,sw); put_line(sw,nw); *)

Поделиться:
Популярные книги

Охотник на демонов

Шелег Дмитрий Витальевич
2. Живой лёд
Фантастика:
боевая фантастика
5.83
рейтинг книги
Охотник на демонов

Товарищ "Чума"

lanpirot
1. Товарищ "Чума"
Фантастика:
попаданцы
альтернативная история
4.00
рейтинг книги
Товарищ Чума

Локки 8. Потомок бога

Решетов Евгений Валерьевич
8. Локки
Фантастика:
фэнтези
боевая фантастика
героическая фантастика
попаданцы
5.00
рейтинг книги
Локки 8. Потомок бога

Последний реанорец. Том XII – Часть I

Павлов Вел
11. Высшая Речь
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний реанорец. Том XII – Часть I

Наследие Маозари 9

Панежин Евгений
9. Наследие Маозари
Фантастика:
попаданцы
постапокалипсис
рпг
сказочная фантастика
6.25
рейтинг книги
Наследие Маозари 9

Братва

Монах Евгений
Братва
Детективы:
криминальные детективы
7.17
рейтинг книги
Братва

Виконт. Книга 4. Колонист

Юллем Евгений
Псевдоним `Испанец`
Фантастика:
фэнтези
попаданцы
аниме
7.50
рейтинг книги
Виконт. Книга 4. Колонист

Ганнибал у ворот

Барка Ганнибал
Великие полководцы
Документальная литература:
биографии и мемуары
5.00
рейтинг книги
Ганнибал у ворот

Газлайтер. Том 31

Володин Григорий Григорьевич
31. История Телепата
Фантастика:
боевая фантастика
попаданцы
альтернативная история
фэнтези
6.25
рейтинг книги
Газлайтер. Том 31

Камень

Минин Станислав
1. Камень
Фантастика:
боевая фантастика
6.80
рейтинг книги
Камень

Философия

Коллектив авторов
Научно-образовательная:
философия
учебники
5.00
рейтинг книги
Философия

Апокалипсис

Мартин Джордж Р.Р.
Антология
Фантастика:
социально-философская фантастика
героическая фантастика
боевая фантастика
киберпанк
6.00
рейтинг книги
Апокалипсис

Жизнь, которой не было

Денис Палимов
1. Жизнь, которой не было
Фантастика:
городское фэнтези
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Жизнь, которой не было

Кромвель

Павлова Татьяна Александровна
611. Жизнь замечательных людей
Проза:
историческая проза
6.00
рейтинг книги
Кромвель