Об"єктно-орієнтовані засоби програмування
Клас TShapeLst описаний як ядро і базовий клас будь-якого списку фігур, тому його єдиний неабстрактний метод Repaint просто викликає метод Draw кожного з елементів списку, перебираючи їх від першого (FirstItem) до останнього (Item→Next = = 0). Реалізація власне завдання на курсову роботу починається тільки з класу TTriangleLst. Його метод Generate генерує задану як вхідний параметр кількість… Читати ще >
Об"єктно-орієнтовані засоби програмування (реферат, курсова, диплом, контрольна)
Міністерство освіти та науки України
Вінницький Державний Технічний університет кафедра обчислювальної техніки
Курсова робота з дисципліни
«Програмування»
Тема:
Об`єктно-орієнтовані засоби програмування
Допущена до захисту
Розробив студент Групи 1КС — 01
Осадчук Андрій Залікова книжка № 178
Керівник Черняк О.І.
Вінниця 2002
Завдання до курсової роботи
У файлі задано координати вершин трикутників і координати верщин відрізка. Вивести на екран ці трикутники і відрізок. Другим кольором вивести найменший за площею трикутник. Записати в інший файл координати вершин тих трикутників, які перетинаються з відрізком.
Аннотація
Курсова робота виконувалась з метою якомога точніше відобразити вимоги індивідуального завдання.
Було спроектовано і описано ряд класів, що відображали сутність геометричних фігур, і їх (класів) методів, в яких і реалізовано рішення завдання.
Використання декількох функцій-не членів обумовлено і оправдано глобальністю реалізованих в них дій, і загальною їх необхідністю. Описати клас, членами якого вони були б і зробити цей клас другом для всіх інших не елегантне (в даному випадку) і ємке рішення, не зв`язане з основним завданням.
Опис таких типів, як Boolean і Byte здійснено для спрощення розуміння коду програми і уточнення дій, що можна проводити над даними цих типів.
Класи описувались, як в першу чергу, незалежні і повністю сформовані сутності, тому наявність в них можливо «лишніх» полей і методів обумовлена високою їх якістю. Спочатку була поставлена задача написати дієспособні класи, без зв`язку з індивідуальним завданням і їх властивості — прямий цього наслідок. Практика забезпечення класів повним набором властивостей з самого початку роботи над проектом, окупає себе в процесі його реалізації, коли раптом знадобляться поля, що на початку роботи необхідними не здавалися, або, навіть, не були.
На початку роботи над проектом було прийнято рішення не використовувати для збереження об`єктів змінних статичних типів даних, таких як масиви чи інші, схожі структури.
Як альтернатива їм були вибрані динамічні списки, що забезпечують необхідну гнучкість і, окрім того, були бажаною реалізацією, що зазначалось в завдані до курсової роботи.
Таким чином робота повністю відповідає поставленим в індивідуальному завданні вимогам і є рішенням запропонованої задачі.
Зміст
- Завдання до курсової роботи
- Аннотація
- Зміст
- Вступ
- Загальна структура роботи
- Розробка алгоритму виконання основного завдання і програмна його реалізація
- Список використаних джерел
- Додатки
Вступ
Ця курсова робота висвітлює підтримку об`єктно-орієнтованого програмуваня в мові С++. Використані майже всі можливості мови і наведені приклади всіх властивостей ООП — наслідування, поліформізм, інкапсуляція, віртуальні, абстрактні і InLine функції. Також приведені приклади організації двозв’язного списку об'єктів в динамічній пам`яті, показчиків на об'єкти і стандартних функцій роботи з вільною пам`яттю.
Загальна структура роботи
Курсова робота складається з файлу проекту, написаного на мові Borland C++ version 3.1 (розширення .cpp) і його скомпільованого варіанту (розщирення .exe).
Також можуть бути (але не обов`язково) присутні файли з збереженими даними «Test.dat» і «Tria.dat» .
Розробка алгоритму виконання основного завдання на курсову роботу і програмна його реалізація з використанням засобів об`єктно-орієнтованого програмування
Абревіатура ОПП означає об`єктно-орієнтоване програмування. ОПП — це концепція програмування що розглядає сукупність даних і дій, що можна проводити над ними, як одне ціле, об`єкт. На відміну від класичного стилю програмування при якому програма складалася з ряду підпрограм, що оперували даними-параметрами, поданими на вхід підпрограмі, в ОПП дані більш захищені від помилкового втручання, або використання. Це стає добре помітно у великих програмах, де одні і тіж дані використовуються багатьма функціями і помилкова їх корекція (в наслідок не дотримання задуманої програмістом послідовності, наприклад) може мати фатальні наслідки. В добре продуманій об`єктно-орієнтованій програмі така ситуація просто неможлива, в зв`язку з чим дані недоступні будь-якому впливу ззовні, а код методів (функцій-членів) класу виключає допущення помилок (при певному підході, звичайно).
Отож, сформулювати концепцію ООП можна так: ООП — це дані, що доповнені функціями для роботи з ними і тільки ними. Це називається — інкапсуляція.
В такому симбіозі спостерігаються і інші, не пов`язані з захистом даних властивості ООП. Головним чином мається на увазі те, що завдяки таким його властивостям, як наслідування та поліформізм різко зменшується час на розробку будь-якого проекту.
Один раз добре написаний об`єкт може бути використано безліч разів, без необхідності його дублювати, тестувати і, як воно зазвичай буває, переписувати. Завдяки тому, що всі (чи майже всі) дані в програмі пов`язані і нерідко мають багато спільного, скориставшись відомим математичним прийомом, можна винести усі спільні риси «за дужки» і опрацювати окремо. А один раз добре відпрацьоване ядро можна доповнювати різними властивостями для будь-яких конкретних випадків.
На прикладі геометричної фігури це буде виглядати так. Потрібно знайти всі риси фігури, що є спільними для всіх фігур. Ці риси стануть основою класу «Фігура».
В першу чергу — це положення. Тому у кожної (будь-якої, квадрата чи кола) фігури мають бути її координати (X і Y). Ще одною властивістю фігури є, наприклад, її колір. Це основні властивості класу «Фігура», їх прийнято називати її властивостями (або полями об`єкта). Після визначення властивостей об`єкта, потрібно визначити, які дії можна провести над ним. Для фігури — це переміщення (що випливає з наявності у неї координат) і зміна кольору (аналогічно). Також фігуру можна вивести на екран, що є логічним результатом її існування.
Цих три дії — переміщення, зміна кольору і рисування фігури є методами об`єкта «Фігура».
Таким чином отримали остаточно сформований клас «Фігура».
Опишемо клас «Квадрат». У нього є всі властивості фігури: координати і колір, його можна перемішувати і т. д. Але у нього є нові, притаманні саме йому властивості, наприклад — розмір сторін.
При класичному підході до програмування сутностей, необхідно ще раз описати в програмі, що у квадрата є колір, координати і т. д. Але з ООП цього робити непотрібно. Зазначимо у програмі, що клас «Фігура» є базовим для класу «Квадрат», тоді класу «Квадрат» стануть доступні всі властивості класу «Фігура». Якщо у «Фігури» було б декілька десятків (сотень) властивостей, це стало б суттєвою економією часу. Також це зменшує кількість помилок в описах класів і їх методів.
Або інший приклад. Нехай на базі класу «Фігура» було написано декілька класів — «квадрат», «коло», «трикутник» і т. д. І виникла необхідність їх пронумерувати. В такому випадку кожен клас має мати властивість «номер».
При написанні програми в класичному, не об'єктному, стилі, потрібно було б до кожного з описів класів («квадрата», «кола» …) додавати властивість «номер». Це довго і не гарантує, що програміст не забуде жодної з описаних фігур. В з ООП, коли описано базовий клас «Фігура», до його властивостей потрібно просто додати ще одну — «номер», і тоді всі класи, для яких «Фігура» є базовим (нащадки класу «Фігура») зразу отримають властивість «номер». Таким чином, ООП зберігає час і сили програміста, а здатність класу-нащадка мати доступ до властивостей класу-предка (базового класу) називається наслідуванням.
Розглянемо ще таку ситуацію. Клас «Фігура» має метод відображення її на екрані. Цей метод мають і всі її нащадки. Але квадрат і коло мають виводити себе на екран по різному! На даному етапі всі нащадки класу «Фігура» виводять себе на екран однаково — так само, як сама фігура. Так як «Фігура» — поняття абстрактне, то вони виводити себе на екран не будуть взагалі. У цієї проблеми в ООП є рішення. А саме: ті методи, що мають однакову назву і виконують однакову дію, але по-різному для кожного з нащадків, слід описувати як віртуальні. Метод класу, що описаний як віртуальний, не буде використовувати такий самий метод предка, а свій власний, що і треба було реалізувати. Можливість різних класів мати методи з однаковими назвами, що виконують при цьому різні дії називається поліформізмом.
Таким чином, клас — це визначений програмістом тип даних, що має свої поля даних і методи (функції), що оперують цими даними.
Але саме визначення класу «Квадрат» ще не призводить до появи квадрату на екрані. І взагалі, квадратів може бути декілька, різного кольору, в різних місцях на екрані.
Кожен з них є об`єктом класу «Квадрат». Виходячи з цього можна можна дати визначення поняттю «об`єкт». Отже, об`єкт класу — це конкретний елемент типу даних, що має властивості свого класу і при цьому є його практичною реалізацією. Тобто, при опису класу вказується тільки те, що у об'єкта «квадрат» мають бути координати, а у об`єктів «Квадрат1», «Квадрат2», «Квадрат3» і т. д., ці координати конкретизуються. Опис класу завжди один, об`єктів класу — скільки завгодно.
В програмі описано такі класи:
TPoint. Це структура, з полями Х і У, що забезпечують програмне представлення точки на координаційній площині.
TShape. Предок всіх фігур, є нащадком TListItem і тому має відповідні властивості для використання вTShapeLst. В цьому класі описані основні, спільні для всіх фігур, властивості, що зберігають інформацію про колір, номер, пересічення і т.д. Також описані методи для роботи з цими властивостями.
TLine. Нащадок TShape. Окрім властивостей, описаних у своєму предку, має координати точок кінців і довжину. Також доповнені методи TShape.
TTriangle. Нащадок TShape. Має площу і три сторони — A, B, C.
TShapeLst. Нащадок TList. Описаний для зберігання списку об`єктів TShape і його нащадків. Описане поле Smaller вказуює на найменший об`єкт в списку. Методи базового класу доповнені новими — Repaint, що забезпечує прорисовку всіх членів в списку, LoadFromFile та SaveToFile, які забезпечують операції з файлами. Останні два на рівні TShapeLst абстрактні.
TTRiangleLst. Нащадок TShapeLst. Не вносить нових полей, але окрім конкретної реалізації методів LoadFromFile і SaveToFile, доповнює клас методами для фільтрації списку фігур згідно з умовою індивідуального завдання.
Функція Power є авторською реалізацією функції піднесення в квадрат. Це стало необхідним коли виявилось, що стандартна функція Sqr не дає бажаного результату — вона не вірно працює з занадто великими числами, що виникають в результаті обробки координат об'єктів по запропонованому в роботі алгоритму.
Функція GetLength, що отримує на вході два об`єкта типу TPoint, повертає відстань між точками, чиї координати визначені цими об`єктами.
Таким чином реалізовано ієрархію класів, основою якої є TListItem і TList, що забезпечує програмі велику гнучкість, та TShape і TShapeLst, що забезпечує підтримку графічних об`єктів і роботи з ними.
Короткий опис методів описаних у програмі класів з обґрунтуванням використаних алгоритмів. Так як реалізація власне завдання на курсову роботу починається з класу TShape, є сенс не розглядати класи TList і TListItem особливо докладно, вони відповідають за низькорівневі операції з пам`яттю, її виділенням та звільненням для об'єктів.
Методи класу TShape не відрізняються нічим вартим уваги. Їх дія очевидна і не потребує додаткових пояснень.
Методи TLine теж виконують тільки службову функцію ініціалізації об`єктів класу і їх прорисовки.
Клас TShapeLst описаний як ядро і базовий клас будь-якого списку фігур, тому його єдиний неабстрактний метод Repaint просто викликає метод Draw кожного з елементів списку, перебираючи їх від першого (FirstItem) до останнього (Item->Next = = 0). Реалізація власне завдання на курсову роботу починається тільки з класу TTriangleLst. Його метод Generate генерує задану як вхідний параметр кількість елементів списку з довільними координатами. Змістовний алгоритм відсутній, а маштаб розмірів об`єктів вибраний довільно, і не заперечує умові.
Метод LoadFromFile є альтернативою методу Generate і за допомогою звичайних функцій роботи з файлами і потоками заповнює раніше збережений на диску список відрізків. SaveToFile виконує роль, протилежну методу LoadFromFile — зберігає на диску згенерований методом Generate список елементів.
За допомогою цих трьох методів реалізовано зв`язок між елементами і їх координатами у файл .
Методом SetBiggSmall ініціалізується поле Smaller класу TTriangleLst. За таким алгоритмом: перебираючи всі відрізки від другого до останнього потрібно порівняти їх з кожним відрізком (від першого — до останнього) в списку (окрім самого себе). В разі, якщо відрізок менший від Smaller (що спочатку вказує на перший елемент списку) то Smaller змінює своє значення на значення активного на даній ітерації елементу списку.
Функція Cross є основою програми, вона повертає булевський результат пересічення двох відрізків, поданих на вхід функції. В тілі функції відбувається складна перевірка координат відрізків, на основі системи рівнянь прямої.
Метод Filter концептуально не відрізняється від SetBiggSmall. Перебираючи всі елементи списку, для кожного (з допомогою функції Cross) перевіряється його пересічення з будь-яким іншим, і в разі позитивного результату перевірки результат відображається в полі Crossed класу TTriangle. Таким чином виконується фільтрація елементів згідно завдання курсової роботи.
Власне код функції main виконує послідовний визов функцій-членів і додаткових пояснень не потребує.
функція файл поле power
Список використаних джерел Методичні вказівки до виконання курсової роботи. Вінниця, ВДТУ — 1998.
Страуструп Б. «Язык программирования Си++». Москва, «Радио и связь» — 1991.
Керниган, Ричи. Язык C. В электронном виде.
Додатки
Додаток А. Лістинг програми
#include
#include
#include
#include
#include
#include
#include
enum Boolean
{
False = 0, True = 1
};
typedef char Byte;
struct TListItem;
struct TListItem
{
TListItem* Next;
TListItem* Prev;
};
class TList
{
public:
int ItemCount;
TListItem* FirstItem;
TListItem* CurrItem;
TList ();
virtual void Add (TListItem* Item);
virtual void Del ();
virtual void Clear ();
virtual ~TList ();
};
//*** TList methods
TList:TList ()
{
ItemCount = 0;
FirstItem = 0;
CurrItem = FirstItem;
};
void TList: Add (TListItem* Item)
{
Item->Next = 0;
Item->Prev = CurrItem;
if (CurrItem ≠ 0)
CurrItem->Next = Item;
else
FirstItem = Item;
CurrItem = Item;
ItemCount++;
};
void TList: Del ()
{
TListItem* Item;
TListItem* PrevItem;
PrevItem = CurrItem->Prev;
Item = CurrItem->Next;
Item->Prev = PrevItem;
delete (CurrItem);
CurrItem = Item;
ItemCount—;
};
void TList: Clear ()
{
CurrItem = FirstItem;
while (FirstItem ≠ 0)
{
FirstItem = FirstItem->Next;
Del ();
CurrItem = FirstItem;
};
};
TList:~TList ()
{
Clear ();
};
//*** Ctrls
#define VK_ESC 27
#define VK_ENTER 13
#define VK_LEFT 75
#define VK_RIGHT 77
#define VK_UP 72
#define VK_DOWN 80
#define VK_DEL 83
#define VK_BACK 8
#define LF = 10
#define CF = 13
#define CR = CF+LF
typedef char TCaption[12+1];
enum TExitFlag
{
efExit, efNext, efPrev
};
class TObject: public TListItem
{
//*** Abstract
};
class TApplication;
typedef void (*PButtonClick)(void* Sender);
typedef void (TApplication:*PAppButtonClick)(void* Sender);
class TControl: public TObject
{
//*** Предок всех элементов управления,
//*** содержит свойства для работы в TControlList
public:
Byte X, Y;
Byte Color, BkCol, ActiveCol;
Boolean Active;
TExitFlag ExitFlag;
int Tag;
TCaption Caption;
TControl (Byte AX, Byte AY, TCaption ACaption, Byte ACol, Byte ABkCol, Byte AActiveCol, int ATag);
virtual void SetClr (Byte AItem, Byte ACol);
virtual void Enter ();
virtual void Exit ();
virtual void Draw () = 0;
~TControl (){};
};
class TButton: public TControl
{
public:
TApplication* Owner;
PAppButtonClick onClick;
TButton (TApplication* AOwner, Byte AX, Byte AY, TCaption ACaption, int ATag, PAppButtonClick AClick);
virtual void Draw ();
virtual void Enter ();
virtual void Run ();
~TButton (){};
};
class TControlLst: public TList
{
//*** Динамический список элементов управления
public:
TControlLst ();
void Run ();
virtual void Repaint ();
};
class TApplication
{
public:
TApplication (){};
};
class TProga;
void ReadKey (char* Key, Boolean* CtrlKey);
//*** Types and declarations
struct TPoint
{
int X, Y;
};
class TLinePnt: public TListItem
{
public:
TPoint Pnt;
TLinePnt (){}
};
struct TRect
{
int Left, Top, Right, Bottom;
};
class TShape: public TListItem
{
//*** Предок всех фигур,
//*** содержит свойства для работы в TShapeList
public:
Boolean Crossed;
Byte Color;
int Tag;
TShape (){Color = RED; Tag = 0;};
TShape (Byte ACol, int ATag);
virtual void SetClr (Byte ACol);
virtual void Draw () = 0;
virtual ~TShape ();
};
class TLine: public TShape
{
public:
TPoint A, B;
float Len;
TLine ():TShape (){};
TLine (TPoint AA, TPoint AB, Byte ACol, int ATag);
float SetLen ();
virtual void Draw ();
};
class TTriangle: public TShape
{
public:
TLine A, B, C;
float Area;
Boolean Smaller;
TTriangle (TPoint AA, TPoint AB, TPoint AC, Byte ACol, int ATag);
virtual void Draw ();
float SetArea ();
virtual void SetClr (Byte ACol);
};
class TShapeLst: public TList
{
//*** Динамический список фигур ***)
public:
TShape* Smaller;
TShapeLst ();
virtual void Repaint ();
virtual void LoadFromFile (char* FileName) = 0;
virtual void SaveToFile (char* FileName) = 0;
};
class TTriangleLst: public TShapeLst
{
public:
TLine* Line;
TTriangleLst ();
virtual void Generate (int ACount);
virtual void LoadFromFile (char* FileName);
virtual void SaveToFile (char* FileName);
void SaveCrossedTria (char* FileName);
virtual void Filter ();
virtual Boolean Cross (TLine* Item, TLine* SubItem);
virtual void SetBiggSmall ();
virtual void Repaint ();
};
long Power (long X)
{
return (X*X);
};
float GetLength (TPoint P1, TPoint P2)
{
float Result;
Result = Power (P2.X — P1. X) + Power (P2.Y — P1. Y);
if (Result > 0)
Result = sqrt (Result);
else//*** Иначе координаты двух точек равны
Result = 0;
return (Result);
};
//*** TShape methods
void TShape: TShape (Byte ACol, int ATag)
{
Color = ACol;
Tag = ATag;
};
void TShape: SetClr (Byte ACol)
{
Color = ACol;
};
TShape:~TShape ()
{
//*** must be
};
//*** TLine methods
TLine:TLine (TPoint AA, TPoint AB, Byte ACol, int ATag): TShape (ACol, ATag)
{
A = AA;
B = AB;
Len = SetLen ();
Crossed = False;
};
float TLine: SetLen ()
{
return (GetLength (A, B));
};
void TLine: Draw ()
{
if (Crossed)
setcolor (YELLOW);
else
setcolor (Color);
line (A.X, A. Y, B. X, B. Y);
};
//*** TTriangle methods
TTriangle:TTriangle (TPoint AA, TPoint AB, TPoint AC, Byte ACol, int ATag):
TShape (ACol, ATag)
{
A = TLine (AA, AB, Color, 0);
B = TLine (AB, AC, Color, 0);
C = TLine (AC, AA, Color, 0);
Smaller = False;
Area = SetArea ();
Crossed = False;
};
float TTriangle: SetArea ()
{
float P = A. Len + B. Len + C. Len;
return (sqrt (P*(P-A.Len)*(P-B.Len)*(P-C.Len)));
};
void TTriangle: SetClr (Byte ACol)
{
A.SetClr (ACol);
B.SetClr (ACol);
C.SetClr (ACol);
};
void TTriangle: Draw ()
{
if (Crossed)
{
A.SetClr (YELLOW);
B.SetClr (YELLOW);
C.SetClr (YELLOW);
};
if (Smaller)
{
A.SetClr (BLUE);
B.SetClr (BLUE);
C.SetClr (BLUE);
};
A.Draw ();
B.Draw ();
C.Draw ();
};
//*** TShapeLst methods
TShapeLst:TShapeLst ():TList ()
{
Smaller = 0;
};
void TShapeLst: Repaint ()
{
TShape* Item;
Item = (TShape*)FirstItem;
while (Item)
{
Item->Draw ();
Item = (TShape*)Item->Next;
};
};
//*** TTrianlgeLst methods
TTriangleLst:TTriangleLst (): TShapeLst ()
{
//*** must be
};
void TTriangleLst: Generate (int ACount)
{
int I;
TPoint A, B, C;
TTriangle* T;
for (I = 1; I <= ACount; I++)
{
A.X = 50+random (450);
A.Y = 100+random (200);
B.X = A. X+random (50);
B.Y = A. Y-random (100);
C.X = B. X + (B.X — A. X);
C.Y = A. Y;
T = new TTriangle (A, B, C, GREEN, I);
Add (T);
};
A.X = 50+random (450);
A.Y = 100+random (200);
B.X = 50+random (400);
B.Y = 100+random (300);
Line = new TLine (A, B, WHITE, 0);
};
void TTriangleLst: LoadFromFile (char* FileName)
{
TTriangle* Item;
TPoint A, B, C;
filebuf f;
if (f.open (FileName, ios: in) == 0)
printf («Не могу открыть входной файл %s», FileName);
istream from (&f);
from >> (A.X);
from.get ();
from >> (A.Y);
from.get ();
from >> (B.X);
from.get ();
from >> (B.Y);
from.get ();
from.get ();
Line = new TLine (A, B, WHITE, 0);
while (!(from.eof ()))
{
from >> (A.X);
from.get ();
from >> (A.Y);
from.get ();
from >> (B.X);
from.get ();
from >> (B.Y);
from.get ();
from >> (C.X);
from.get ();
from >> (C.Y);
from.get ();
from.get ();
Item = new TTriangle (A, B, C, GREEN, 0);
Add (Item);
};
f.close ();
};
void TTriangleLst: SaveToFile (char* FileName)
{
TTriangle* Item;
remove (FileName);
filebuf f;
if (f.open (FileName, ios: out) == 0)
printf («Не могу открыть выходной файл %s», FileName);
ostream to (&f);
to << (Line->A.X) << 'n';
to << (Line->A.Y) << 'n';
to << (Line->B.X) << 'n';
to << (Line->B.Y) << 'n';
to << 'n';
Item = (TTriangle*)FirstItem;
while (Item)
{
to << (Item->A.A.X) << 'n';
to << (Item->A.A.Y) << 'n';
to << (Item->B.A.X) << 'n';
to << (Item->B.A.Y) << 'n';
to << (Item->C.A.X) << 'n';
to << (Item->C.A.Y) << 'n';
if (Item->Next)
to << 'n';
Item = (TTriangle*)Item->Next;
};
f.close ();
SaveCrossedTria («Tria.dat»);
};
void TTriangleLst: SaveCrossedTria (char* FileName)
{
TTriangle* Item;
remove (FileName);
filebuf f;
if (f.open (FileName, ios: out) == 0)
printf («Не могу открыть выходной файл %s», FileName);
ostream to (&f);
Item = (TTriangle*)FirstItem;
while (Item)
{
if (Item->Crossed)
{
to << (Item->A.A.X) << 'n';
to << (Item->A.A.Y) << 'n';
to << (Item->B.A.X) << 'n';
to << (Item->B.A.Y) << 'n';
to << (Item->C.A.X) << 'n';
to << (Item->C.A.Y) << 'n';
if (Item->Next)
to << 'n';
};
Item = (TTriangle*)Item->Next;
};
f.close ();
};
void TTriangleLst: SetBiggSmall ()
{
TTriangle* Item;
Smaller = (TShape*)FirstItem;
Item = (TTriangle*)FirstItem->Next;
while (Item)
{
if (Item->Area < ((TTriangle*)Smaller)->Area)
Smaller = Item;
Item = (TTriangle*)Item->Next;
};
((TTriangle*)Smaller)->Smaller = True;
};
Boolean TTriangleLst: Cross (TLine* Item, TLine* SubItem)
((x22<=x)&&(x<=x21))&&((y22<=y)&&(y<=y21))))
Result = True;
return (Result);
;
void TTriangleLst: Filter ()
{
TTriangle* Item;
Boolean Accept;
Item = (TTriangle*)FirstItem;
while (Item)
{
Accept = False;
if ((Cross (&(Item->A), Line)) ||
(Cross (&(Item->B), Line)) ||
(Cross (&(Item->C), Line)))
Accept = True;
if (Accept)
{
Item->Crossed = True;
};
Item = (TTriangle*)Item->Next;
};
};
void TTriangleLst: Repaint ()
{
TShapeLst:Repaint ();
Line->Draw ();
};
class TProgaMenu: public TControlLst
{
public:
void Repaint ();
};
class TProga: public TApplication
{
public:
TProgaMenu Menu;
int Tag;
TTriangleLst Lines;
void MainMenu ();
PAppButtonClick onNew;
PAppButtonClick onLoad;
PAppButtonClick onSave;
PAppButtonClick onRun;
PAppButtonClick onExit;
void doNew (void* Sender);
void doLoad (void* Sender);
void doSave (void* Sender);
void doExit (void* Sender);
void doRun (void* Sender);
void BkRepaint ();
TProga ();
};
//*******************************************************
// RealiZation
//*******************************************************
//*** TControl methods
TControl:TControl (Byte AX, Byte AY, TCaption ACaption, Byte ACol, Byte ABkCol, Byte AActiveCol, int ATag)
{
ExitFlag = efNext;
X = AX;
Y = AY;
strcpy (Caption, ACaption);
Color = ACol;
BkCol = ABkCol;
ActiveCol = AActiveCol;
Active = False;
Tag = ATag;
};
void TControl: SetClr (Byte AItem, Byte ACol)
{
switch (AItem)
{
case 0: Color = ACol;break;
case 1: ActiveCol = ACol;break;
case 2: BkCol = ACol;
};
};
void TControl: Enter ()
{
Active = True;
Draw ();
};
void TControl: Exit ()
{
Active = False;
Draw ();
};
//*** TButtons methods
TButton:TButton (TApplication* AOwner, Byte AX, Byte AY, TCaption ACaption, int ATag, PAppButtonClick AClick):
TControl (AX, AY, ACaption, BLUE, LIGHTGRAY, RED, ATag)
{
Owner = AOwner;
onClick = AClick;
Draw ();
};
void TButton: Draw ()
{
struct text_info ti;
gettextinfo (&ti);
gotoxy (X, Y);
if (Active)
textbackground (ActiveCol);
else
textbackground (BkCol);
textcolor (Color);
for (int I = 0;I < strlen (Caption);I++)
putch (Caption[I]);
textcolor (ti.attribute);
};
void TButton: Enter ()
{
TControl:Enter ();
Run ();
};
void TButton: Run ()
{
char Key;
Boolean CtrlKey;
Boolean Quit;
Quit = False;
do
{
ReadKey (&Key,&CtrlKey);
switch (Key)
{
case VK_UP:if (CtrlKey)
{
Quit = True;
ExitFlag = efPrev;
};break;
case VK_ENTER:
{
Quit = True;
ExitFlag = efNext;
((Owner)->*onClick)(this);
};break;
case VK_DOWN:if (CtrlKey)
{
Quit = True;
ExitFlag = efNext;
};break;
case VK_ESC:
{
Quit = True;
ExitFlag = efExit;
};break;
};
Draw ();
} while (!Quit);
Exit ();
};
//*** TControlList methods
TControlLst:TControlLst ():TList ()
{
//must be
};
void TControlLst: Repaint ()
{
TControl* Item = (TControl*)FirstItem;
while (Item)
{
Item->Draw ();
Item = (TControl*)(Item)->Next;
};
};
void TControlLst: Run ()
{
//*** CurrItem тут — синоним ActiveControl
CurrItem = FirstItem;
do
{
((TControl*)CurrItem)->Enter ();
switch (((TControl*)CurrItem)->ExitFlag)
{
case efNext: if (CurrItem->Next)
CurrItem = CurrItem->Next;break;
case efPrev: if (CurrItem->Prev)
CurrItem = CurrItem->Prev;break;
};
Repaint ();
} while (!((TControl*)CurrItem)->ExitFlag == efExit);
};
//*** TProgaMenu methods
void TProgaMenu: Repaint ()
{
TControlLst:Repaint ();
};
void ReadKey (char* Key, Boolean* CtrlKey)
{
*Key = getch ();
if (*Key == 0)
{
*Key = getch ();
*CtrlKey = True;
}
else
*CtrlKey = False;
};
char* DltChr (char* S, int Pos)
{
//*** S — строка, Pos — номер удаляемого символа (начиная с 1)
char* Begin = S;
int I = 1;
while (*S)
{
if (I >= Pos)
*S = *(S+1);
S++;
I++;
};
return (Begin);
};
char* InsChr (char* S, int Pos, char Ch)
{
//*** S — строка, Pos — номер вставляемого символа Ch
char* Begin = S;
char Chr;
int I = 1;
while (*S)
{
if (I >= Pos)
{
Chr = *S;
*S = Ch;
Ch = Chr;
};
S++;
I++;
};
*S = Ch;
return (Begin);
};
//*** TProga methods
TProga:TProga ():TApplication ()
{
onNew = (PAppButtonClick)&TProga:doNew;
onLoad = (PAppButtonClick)&TProga:doLoad;
onSave = (PAppButtonClick)&TProga:doSave;
onRun = (PAppButtonClick)&TProga:doRun;
onExit = (PAppButtonClick)&TProga:doExit;
};
void TProga: MainMenu ()
{
TButton* Btn;
Btn = new TButton (this, 2,2," Новий «, 1, onNew);
Menu.Add (Btn);
Btn = new TButton (this, 2,3," Зчитати «, 2, onLoad/*&doLoad*/);
Menu.Add (Btn);
Btn = new TButton (this, 2,4," Записати «, 3, onSave);
Menu.Add (Btn);
Btn = new TButton (this, 2,5," Запуск «, 4, onRun);
Menu.Add (Btn);
Btn = new TButton (this, 2,6," Вихiд «, 4, onExit);
Menu.Add (Btn);
BkRepaint ();
Menu.Repaint ();
Menu.Run ();
};
void TProga: doNew (void* Sender)
{
Lines.Clear ();
randomize ();
Lines.Generate (26);
doRun (0);
};
void TProga: doLoad (void* Sender)
{
Lines.Clear ();
Lines.LoadFromFile («Test.dat»);
doRun (0);
};
void TProga: doSave (void* Sender)
{
Lines.SaveToFile («test.dat»);
};
void TProga: doExit (void* Sender)
{
((TControl*)(Menu.CurrItem))->ExitFlag = efExit;
};
void TProga: doRun (void* Sender)
{
int I;
float BLen, SLen, Len;
char* S;
int grDriver, grMode, errorcode;
grDriver = DETECT;
initgraph (&grDriver, &grMode," .\BGI");
Lines.Filter ();
Lines.SetBiggSmall ();
//*** Инфа
printf («%d треугольниковn», Lines. ItemCount);
printf («Синий — наименьшийn»);
printf («Желтым — те, что пересекаются с линиейn»);
printf («Белым — линияn»);
Lines.Repaint ();
getch ();
closegraph ();
BkRepaint ();
};
void TProga: BkRepaint ()
{
textbackground (0);
textcolor (7);
clrscr ();
for (int I = 1;I <= 25;I++)
for (int J = 1;J <= 80;J++)
putch ('-');
for (I = 20;I < 70;I++)
{
gotoxy (I, 4);
putch ('=');
};
for (I = 20;I < 70;I++)
{
gotoxy (I, 8);
putch ('=');
};
gotoxy (20,5);
printf («%-50s» ," Курсова робота з програмування");
gotoxy (20,6);
printf («%50s» ," Перевiряючий:");
gotoxy (20,7);
printf («%50s» ," Черняк О. I.");
for (I = 53;I < 70;I++)
{
gotoxy (I, 21);
putch ('=');
};
for (I = 53;I < 70;I++)
{
gotoxy (I, 23);
putch ('=');
};
gotoxy (53,22);
printf («%s» ," ВДТУ, ФIТКI, 2001″);
};
//*** Main
int main ()
{
TProga Proga;
Proga.MainMenu ();
return (0);
}