Идентификация связей между классами и объектами 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Идентификация связей между классами и объектами



Класс TPoint. При взаимодействии объектов, характеризуемых местоположением, возникает необходимость вычисления расстояния между некоторыми двумя точками графического пространства. Эта операция будет приписана классу TPoint.

Класс TFigure. В процессе выполнения моделирования всех отображаемых объектов для определения фактов столкновения необходимо знать, на каком расстоянии находятся друг от друга объекты класса TFigure. Поэтому определяем операцию GetDistance получения расстояния от произвольной точки экрана до центра фигуры.

Класс TWall. Для данного класса переопределяются методы GetDistance и Show. Для обеспечения доступа к атрибуту theAngle при имитации взаимодействия шаров со стенкой вводится метод GetAngle.

Класс THole. Для данного класса переопределяются методы GetDistance и Show.

Класс TBall. Объекты подклассов данного класса взаимодействуют между собой, со стенками и лузами. При взаимодействии изменяются атрибуты, поэтому вводим операции доступа и изменения атрибутов theEnergy и theDirection, соответственно, GetEnergy, GetDirection, SetEnergy, SetDirection.

Классы TWhiteBall, TBlackBall. Поведение белых и черных шаров различается при взаимодействии с лузой, поэтому следует ввести замещающий метод HitOnHole для этих двух классов.

Реализация классов и объектов

Все разработанные классы и выявленные объекты должны быть включены в проект. Уточненные диаграммы классов и объектов показаны на рис. 13, 14. Для диаграммы объектов составлена диаграмма взаимодействия (рис. 15), иллюстрирующая порядок взаимодействия шара с другими объектами. На рис. 16 представлена диаграмма переходов для объекта класса TBlackBall.

Относительно универсальные классы TPoint и TFigure, могут быть использованы в любой графической программной системе. Они составят модуль Figures (рис. 17). Оставшиеся классы относятся к изучаемой предметной области и будут входить в модуль Billiard. Кроме того, для графического изображения простейших фигур необходимо использовать стандартный модуль графики Graphics. Головная программа main в данном случае является единственной и содержит инициализацию, выполнение и уничтожение единственного объекта класса TReality. Вся программная система реализуется одним процессом, поэтому нет необходимости составлять диаграмму процессов.

 

Программирование

Программирование выполняется на языке С++, что определено общими требованиями к курсовой работе, но в реальном проекте выбор языка программирования должен быть обоснован. Основу для программирования составляют диаграммы и спецификации этапа проектирования. Подробнее останавливаться на данном этапе не будем, считая, что он не должен вызвать затруднений. Необходимые детали разъясняются комментариями в тексте программы в приложении 1.

Тестирование

Тестирование программного модуля (подпрограммы) рассмотрим на примере метода HitOnBall класса TBall. При восходящем тестировании сначала тестируются модули нижнего уровня. Модули последующих уровней тестируются в предположении, что используемые модули абсолютно надежны. В рассматриваемом случае программными модулями нижнего уровня являются методы GetDistance, GetCenter, GetDirection, SetDirection, GetEnergy, SetEnergy класса TBall. При тестировании метода класса следует иметь в виду, что кроме явно объявляемых параметров соответствующей процедуре передается указатель на объект, и поэтому поля объекта являются одновременно входными и выходными данными.

Спецификация тестируемого метода:

· Имя: HitOnBall;

· Назначение: изменить параметры движения двух шаров при их столкновении;

· Аргумент: TBall *aBall (указатель на пассивный шар);

· Квалификация: управление;

· Расширение: добавление;

· Действия: Если один из шаров находится в лузе, то выходные данные остаются без изменения. Если шары находятся на близком расстоянии, то каждый из сталкивающихся шаров изменяет направление таким образом, как будто он столкнулся со стенкой, расположенной посередине между направлениями их движения, при этом суммарная энергия двух шаров перераспределяется между шарами поровну.

Тесты допустимых границ входных данных (тесты 1¸4) и функциональных границ (тесты 5¸7) сведем в таблицу.

 

 

N Входные данные Выходные данные
  Шары имеют нулевую энергию: this‑>theRadius==5; this‑>theCenter=={11,25}; this‑>theState==stOnField; this‑>theEnergy==0; this‑>theDirection==3*Pi/4; aBall‑>theRadius==5; aBall‑>theCenter=={15,25}; aBall‑>theState==stOnField; aBall‑>theEnergy==0; aBall‑>theDirection==-3*Pi/4. Направление и энергия не изменяются: this‑>theEnergy==0; this‑>theDirection==3*Pi/4; aBall‑>theEnergy==0; aBall‑>theDirection==-3*Pi/4.
  Шары имеют максимальную энергию: this‑>theRadius==5; this‑>theCenter=={11,25}; this‑>theState==stOnField; this‑>theEnergy==cMaxEnergy; this‑>theDirection==3*Pi/4; aBall‑>theRadius==5; aBall‑>theCenter=={15,25}; aBall‑>theState==stOnField; aBall‑>theEnergy==cMaxEnergy; aBall‑>theDirection==-3*Pi/4. Направление и энергия изменяются: this‑>theEnergy==cMaxEnergy; this‑>theDirection==Pi/4; aBall‑>theEnergy==cMaxEnergy; aBall‑>theDirection==-Pi/4.

 


 

    Продолжение
  Первый шар находится в лузе: this‑>theRadius==5; this‑>theCenter==cLongWallCenter1; this‑>theState==stOnHole; this‑>theEnergy==cMaxEnergy/3; this‑>theDirection==3*Pi/4; aBall‑>theRadius==5; aBall‑>theCenter=={cLongWallCenter1.X, cLongWallCenter1.Y-4}; aBall‑>theState==stOnField; aBall‑>theEnergy==cMaxEnergy/5; aBall‑>theDirection==-3*Pi/4. Направление и энергия не изменяются: this‑>theEnergy==cMaxEnergy/3; this‑>theDirection==3*Pi/4; aBall‑>theEnergy==cMaxEnergy/5; aBall‑>theDirection==-3*Pi/4.
  Второй шар находится в лузе: this‑>theRadius==5; this‑>theCenter=={cLongWallCenter1.X, cLongWallCenter1.Y-4}; this‑>theState==stOnField; this‑>theEnergy==cMaxEnergy/5; this‑>theDirection==-3*Pi/4; aBall‑>theRadius==5; aBall‑>theCenter==cLongWallCenter1; aBall‑>theState==stOnHole; aBall‑>theEnergy==cMaxEnergy/3; aBall ‑>theDirection==3*Pi/4. Направление и энергия не изменяются: this‑>theEnergy==cMaxEnergy/5; this‑>theDirection==-3*Pi/4; aBall‑>theEnergy==cMaxEnergy/3; aBall‑>theDirection==3*Pi/4.
  Оба шара находятся в поле и движутся навстречу: this‑>theRadius==5; this‑>theCenter=={5,10}; this‑>theState==stOnField; this‑>theEnergy==0.1*cMaxEnergy; this‑>theDirection==Pi/4+Pi/2; aBall‑>theRadius==5; aBall‑>theCenter=={10,10}; aBall‑>theState==stOnField; aBall‑>theEnergy==0.3*cMaxEnergy; aBall‑>theDirection==Pi/4. Направление и энергия изменяются в соответствии со спецификацией: this‑>theEnergy==0.2*cMaxEnergy; this‑>theDirection==Pi/4; aBall‑>theEnergy==0.2*cMaxEnergy; aBall‑>theDirection==Pi/4+Pi/2.
  Оба шара находятся в поле и движутся в разные стороны: this‑>theRadius==5; this‑>theCenter=={5,10}; this‑>theState==stOnField; this‑>theEnergy==0.7*cMaxEnergy; this‑>theDirection==Pi/4; Направление не изменяется: this‑>theDirection==Pi/4; this‑>theEnergy==0.5*cMaxEnergy; aBall‑>theDirection==Pi/4+Pi/2; aBall‑>theEnergy==0.5*cMaxEnergy.
    Окончание
  aBall‑>theRadius==5; aBall‑>theCenter=={10,10}; aBall‑>theState==stOnField; aBall‑>theEnergy==0.3*cMaxEnergy; aBall‑>theDirection==Pi/4+Pi/2.  

 

Введем обозначения для ветвлений:

A: (theState==stOnField);

B: (aBall->GetDistance(GetCenter()) <= theRadius + cSmallSpace);

C: (aBall->theState==stOnField).

Построим диаграмму управления (рис.18) и, руководствуясь ею, составим матрицу учета ветвей.

 

  Условия              
A (theState==stOnField) T X X   X X X
    F     X      
B (aBall->GetDistance(GetCenter()) <= T X X   X X X
  TheRadius+ cSmallSpace) F            
C (aBall->theState==stOnField) T X X     X X
    F       X    

 

Из матрицы учета ветвей видно, что предусмотренные тесты не охватывают ситуацию B=F, поэтому дополнительно вводим еще тест:

 

  Оба шара находятся в поле и движутся в разные стороны: this‑>theRadius==5; this‑>theCenter=={5,10}; this‑>theState==stOnField; this‑>theEnergy==cMaxEnergy/2; this‑>theDirection==Pi/4+Pi/2; aBall‑>theRadius==5; aBall‑>theCenter=={100,20}; aBall‑>theState==stOnField; aBall‑>theEnergy==cMaxEnergy/3; aBall‑>theDirection==Pi/4. Направление и энергия не изменяются: this‑>theEnergy==cMaxEnergy/2; this‑>theDirection==Pi/4+Pi/2; aBall‑>theEnergy==cMaxEnergy/3; aBall‑>theDirection==Pi/4.

 

Циклы и сложные логические условия в тестируемой процедуре отсутствуют, поэтому нет необходимости составлять соответствующие тесты. Драйвер для выполнения тестов с номерами 5, 6, 7 и результаты тестирования приводятся в приложениях 2 и 3. Отметим, что в тесте 5 несоответствие результата и ожидаемого значения обусловлено ошибкой округления. Тест 6 выявляет ошибку, вызванную тем, что в тестируемой подпрограмме направление шаров изменяется, если они расходятся. Исправление ошибки требует возврата к этапу проектирования. Аналогичная ошибка выявляется при тестировании TBall::HitOnWall.

 

ПОРЯДОК ВЫПОЛНЕНИЯ РАБОТЫ

Преподавателем выдаются задания на курсовую работу и указываются конкретные даты выполнения этапов. Примерный график выполнения курсовой работы:

· 1-я неделя. Получение задания.

· 2-я - 3-я недели. Системный анализ.

· 4-я - 7-я недели. Проектирование программной системы.

· 8-я - 10-я недели. Программирование.

· 11-я - 12-я недели. Тестирование.

· 13-я - 14-я недели. Отладка.

· 15-я - 16-я недели. Оформление пояснительной записки.

· 17-я неделя. Защита курсовой работы.

Отчет о выполнении курсовой работы оформляется на листах писчей бумаги формата 11 (A4). Текст следует размещать на листах, оставляя свободное поле сверху и снизу 20 мм, слева - 25 мм, справа - 15 мм. Разделы, подразделы, таблицы, рисунки и страницы отчета нумеруются. Заголовки разделов пишутся прописными буквами (симметрично тексту), заголовки подразделов - строчными, кроме первой прописной (с абзаца).

Состав пояснительной записки по курсовой работе:

- титульный лист;

- аннотация, включающая в себя сведения об объеме курсовой работы, количество рисунков, таблиц, краткое описание задачи, оценку результатов и т.д.;

- лист задания;

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

- основная часть записки (введение, разделы, заключение);

- список литературы;

- приложения.

Основная часть записки должна включать следующие обязательные разделы: системный анализ, проектирование программной системы, программирование, тестирование. Тексты программ вынести в приложение. Пояснительная записка должна содержать необходимый и достаточный набор диаграмм и спецификаций. В заключение указать пути возможного усовершенствования разработанной программной системы.

Защита курсовой работы проводится перед комиссией, состав которой утвержден кафедрой, и в присутствии студентов данной группы. При защите курсовой работы студент должен сделать краткое сообщение, в котором обоснованно изложить:

- назначение и технические возможности программной системы;

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

- особенности реализации и пути совершенствования программы. Курсовая работа оценивается с учетом полноты выполнения всех стадий разработки, качества оформления отчета, качества защиты, степени самостоятельности работы студента и соблюдения им графика выполнения курсовой работы.

ПРИЛОЖЕНИЕ 1.
Тексты программы учебного примера “Бильярд”

 

// figures.h - Интерфейс модуля графических фигур

#ifndef figures_h

#define figures_h­

#include<math.h>

// Класс точка на экране

class TPoint

{ public:

float X,Y;

float DistanceTo(TPoint& aPoint)

{float X2 = X-aPoint.X;

float Y2 = Y-aPoint.Y;

return (sqrt(X2*X2+Y2*Y2));

};

};

// Базовый класс фигура

class TFigure

{

TPoint theCenter; // геометрический центр фигуры

public:

TFigure(TPoint& aPoint); // инициализировать новыми

//координатами

virtual void Show()=0; // отобразить

void Hide(); // спрятать

virtual float GetDistance(TPoint aPoint)=0; // расстояние

// до фигуры

TPoint GetCenter(); // дать координаты центра

void SetCenter(TPoint aPoint); // установить
//новые коорд.центра

};

#endif

 

// figures.cpp - Реализация модуля графических фигур

#include"figures.h"

#include<graphics.h>

TFigure::TFigure(TPoint& aPoint)

// инициализировать новыми координатами

{ theCenter = aPoint; };

void TFigure::Hide()

{int prev_col = getcolor(); // запомнить предыд.цвет

//рисования

setcolor(BLACK); // установить цвет фона

Show(); // отобразить в "черном цвете"

setcolor(prev_col); // восстановить цвет

};

TPoint TFigure::GetCenter() // дать координаты центра

{return theCenter;};

void TFigure::SetCenter(TPoint aPoint)

// установить новые координаты центра

{theCenter = aPoint;};

 

// billiard.h - Заголовок модуля элементов бильярда

#ifndef billiard_h

#define billiard_h

#include "figures.h"

// Константы предметной области

float const Pi=3.14159265359;

const cWallsNumber=4; // Количество стенок

//у бильярдного стола

const cHolesNumber=4; // Количество луз стола

const cBallsNumber=11; // Количество шаров

//на бильярдном столе

const cBallRadius=5; // Радиус шара

const cHoleRadius=6; // Радиус лузы

const cLongWallLength=290; // Длина длиной стенки стола

const cShortWallLength=190; // Длина короткой стенки стола

float const cMaxEnergy=200.0; // максимальная энергия шара

float const cDeltaEnergy=0.05;

// уменьшение энергии в единицу времени

float const cThresholdEnergy=0.5;

// предел энергии подвижности

float const cVelocity=2.0; // скорость перемещения шара

// Константы проектирования

TPoint const cLongWallCenter1={155,10};

// Положение центра длинной стенки

TPoint const cLongWallCenter2={155,200};

// Положение центра длинной стенки

float const cLongWallAngle = 0.0; // Наклон длинной стенки

TPoint const cShortWallCenter1={10,105};

// Положение центра короткой стенки

TPoint const cShortWallCenter2={300,105};

// Положение центра короткой стенки

float const cShortWallAngle=Pi/2.0;

// Наклон короткой стенки

int const cTimerInterval = 2;

// период генерации событий времени

float const cSmallDistance = 1.0;

// зазор между шарами при расстановке

// константы событий

enum TEvConstant {EvNothing, EvStart, EvInitiate, EvQuit, EvTick};

// Интерфейсы классов

class TEvent

{

// Класс Событие

public:

TEvConstant What;

};

class TTimer

{

private:

int theCounter; // счетчик обращений

int theInterval; // период генерации события

public:

TTimer(int anInterval){theInterval = anInterval; theCounter = 0;};

void HandleEvent(TEvent* anEvent)

{if(theCounter<theInterval){theCounter++;}

// нет события

else{theCounter=0; anEvent->What=EvTick;};

// есть событие

};

~Ttimer(){;}; // Деструктор

};

class TWall: public TFigure

{

// Стенка

float theLength;

float theAngle;

public:

TWall(TPoint aCenter, int aLength, float anAngle);

// параметры

virtual float GetDistance(TPoint aPoint);

// расстояние до точки

float GetAngle(); // угол наклона

virtual void Show();

};

class THole: public TFigure

{

// Луза

int theRadius;

public:

THole(TPoint aCenter, int aRadius);

virtual float GetDistance(TPoint aPoint);

// расстояние до точки

virtual void Show();

};

class TBall: public TFigure

{

// Просто шар

protected:

int theRadius; // радиус

enum TState {stOnField, stOnHole} theState;

// состояние (в поле; в лузе)

float theEnergy; // энергия

float theDirection; // направление движения

public:

TBall(TPoint& aCenter, int aRadius);

void HitOnWall(TWall* aWall);

virtual void HitOnHole(THole* aHole)=0;

void HitOnBall(TBall* aBall);

void SetOnTable(TPoint& aCenter);

virtual void Move();

virtual float GetDistance(TPoint aPoint);

float GetEnergy();

float GetDirection();

void SetEnergy(float anEnergy);

void SetDirection(float aDirection);

};

class TBlackBall: public TBall

{

// Черный шар

public:

TBlackBall(TPoint& aCenter, int aRadius);

virtual void HitOnHole(THole* aHole);

virtual void Show();

};

class TWhiteBall: public TBall

{

// Белый шар

public:

TWhiteBall(TPoint& aCenter, int aRadius);

virtual void HitOnHole(THole* aHole);

virtual void Show();

};

class TTable

{

// Бильярдный стол

TWall* PWalls[cWallsNumber];

//массив указателей на элементы стола

THole* PHoles[cHolesNumber];

TBall* PBalls[cBallsNumber];

TWhiteBall* PTheWhiteBall; // указатель на белый шар

public:

TTable();

void HandleEvent(TEvent* anEvent); // обработка событий

void Initiate(); // Первоначальная расстановка

void Start(); // Удар кием

void Update(); // Изменить состояние

~TTable();

};

class TReality

{

// Моделируемая действительность

TTable* PTheTable; // указатель на стол

TTimer* PTheTimer; // указатель на таймер

public:

TReality();

void Run();

~TReality();

};

#endif

 

// billiard.cpp - Реализация модуля элементов бильярда

#include"figures.h"

#include"billiard.h"

#include<graphics.h>

#include<conio.h>

#include<stdlib.h>

#include <string.h>

// Реализация класса Стенка

TWall::TWall(TPoint aCenter, int aLength, float anAngle)

: TFigure(aCenter)

{ theLength = aLength; theAngle = anAngle;};

float TWall::GetDistance(TPoint aPoint)

// расстояние до точки

{

// Площадь треугольника - по формуле Герона

TPoint A,B; // концы стенки

float L1, L2; //длины боковых сторон

float S, D;

// Определить координаты концов стенки

A.X = theLength*cos(theAngle)/2.0+GetCenter().X;

A.Y = theLength*sin(theAngle)/2.0+GetCenter().Y;

B.X = 2*GetCenter().X-A.X;

B.Y = 2*GetCenter().Y-A.Y;

// Найти длины сторон треугольника между точкой

// и концами стенки

L1 = aPoint.DistanceTo(A);

L2 = aPoint.DistanceTo(B);

// Полупериметр треугольника

S = (L1+L2+theLength)/2.0;

// Искомое расстояние

D = 2.0*sqrt(S*(S-theLength)*(S-L1)*(S-L2))/theLength;

return(D);

};

float TWall::GetAngle() // угол наклона

{ return(theAngle); };

void TWall::Show()

{

// Найти координаты концов стенки

TPoint A,B; // концы стенки

// Определить координаты концов стенки

A.X = theLength*cos(theAngle)/2.0+GetCenter().X;

A.Y = theLength*sin(theAngle)/2.0+GetCenter().Y;

B.X = 2.0*GetCenter().X-A.X;

B.Y = 2.0*GetCenter().Y-A.Y;

line(A.X, A.Y, B.X, B.Y); // и нарисовать ее

};

// Реализация класса Луза

THole::THole(TPoint aCenter, int aRadius): TFigure(aCenter)

{ theRadius = aRadius;};

float THole::GetDistance(TPoint aPoint)

// расстояние до точки

{

// Исключить из расстояния радиус лузы

TPoint A;

A = GetCenter();

return(aPoint.DistanceTo(A)-theRadius);

};

void THole::Show()

{ circle(GetCenter().X, GetCenter().Y, theRadius);};

// Реализация класса Шар

TBall::TBall(TPoint& aCenter, int aRadius): TFigure(aCenter)

{

theRadius = aRadius; // Константа

theState = stOnField; // в поле

theEnergy = 0.0;

theDirection = 0.0;

};

void TBall::HitOnWall(TWall* aWall)

{

if(theState==stOnField) // действия - если в поле

{

// Отражение - если близко

if(aWall->GetDistance(GetCenter()) <= theRadius)

{

// Зеркальное отражение

if(theState==stOnField)

theDirection = 2.0*aWall->GetAngle() - theDirection;

}; // -если близко

}; // -если в поле

};

void TBall::HitOnBall(TBall* aBall)

{

float MidAngle, MidEnergy;

// Все действия, если в поле

if(theState==stOnField)

{

// Столкновение, если близко

if(aBall->GetDistance(GetCenter()) <= theRadius)

{

if(aBall->theState==stOnField)

// если ударяемый шар в поле

{

// Вычиcлить средний угол между направлениями шаров

MidAngle = (theDirection + aBall->GetDirection())/2.0;

// Вычислить новые углы для активного и пассивного шаров

theDirection = 2.0*MidAngle - theDirection;

aBall->SetDirection(2.0*MidAngle - aBall->GetDirection());

// Найти половину суммарной энергии

MidEnergy = (theEnergy + aBall->GetEnergy())/2.0;

aBall->SetEnergy(MidEnergy);

theEnergy = MidEnergy;

}; // -если другой шар в поле

}; // -если близко

}; // -если в поле

};

void TBall::SetOnTable(TPoint& aCenter)

{

theState = stOnField;// в любом случае состояние - в поле

Hide(); // убрать изображение

SetCenter(aCenter); // указать новые координаты

Show(); // отобразить

};

void TBall::Move()

{

TPoint TargetPoint; // Целевая точка перемещения

if(theState==stOnField) // изменения - если в поле

{

// Перемещение, если не достигнут предел подвижности

if(theEnergy > cThresholdEnergy)

{

Hide(); // спрятать

// Переместить центр в направлении движения

TargetPoint.X = GetCenter().X+cVelocity*1.0*cos(theDirection);

TargetPoint.Y = GetCenter().Y+cVelocity*1.0*sin(theDirection);

SetCenter(TargetPoint);

// Уменьшить энергию

SetEnergy(GetEnergy()-cDeltaEnergy);

Show(); // опять отобразить

}; // -если подвижный

}; // -если в поле

};

float TBall::GetDistance(TPoint aPoint)

{

return(GetCenter().DistanceTo(aPoint)-theRadius);

};

float TBall::GetEnergy()

{ return(theEnergy);};

float TBall::GetDirection()

{ return(theDirection);};

void TBall::SetEnergy(float anEnergy)

{ theEnergy = anEnergy;};

void TBall::SetDirection(float aDirection)

{ theDirection = aDirection;};

// Реализация класса Черный шар

TBlackBall::TBlackBall(TPoint& aCenter, int aRadius)

:TBall(aCenter, aRadius) {;};

void TBlackBall::HitOnHole(THole* aHole)

{

// В соответствии с диаграммой преходов

if(theState==stOnField)

{

// Если близко с лузой

if(aHole->GetDistance(GetCenter()) <= theRadius)

{

Hide(); // спрятать изображение

SetCenter(aHole->GetCenter()); // переместить в лузу

theEnergy = 0.0; // лишить энергии

theState = stOnHole; // изменить состояние

}; // -если близко

}; // -если в поле

};

// Реализация класса Белый шар

TWhiteBall::TWhiteBall(TPoint& aCenter, int aRadius)

:TBall(aCenter, aRadius) {;};

void TWhiteBall::HitOnHole(THole* aHole)

{;}; // Белый шар игнорирует столкновение с лузой

void TWhiteBall::Show()

{

// Нарисовать закрашенный круг

if(theState==stOnField)

{

char pattern[8];

getfillpattern(pattern);

setfillpattern(pattern, getcolor());

pieslice(GetCenter().X, GetCenter().Y, 0, 360, theRadius);

};

};

void TBlackBall::Show()

{

// Нарисовать закрашенный круг

if(theState==stOnField) circle(GetCenter().X, GetCenter().Y, theRadius);

};

// Реализация класса Бильярдный стол

TTable::TTable()

{

int i; // Индекс для массивов

TPoint StartPoint;

// Создать стенки

PWalls[0] =

new TWall(cLongWallCenter1, cLongWallLength, cLongWallAngle);

PWalls[1] =

new TWall(cLongWallCenter2, cLongWallLength, cLongWallAngle);

PWalls[2] =

new TWall(cShortWallCenter1, cShortWallLength, cShortWallAngle);

PWalls[3] =

new TWall(cShortWallCenter2, cShortWallLength, cShortWallAngle);

// Создать лузы

PHoles[0] = new THole(cLongWallCenter1, cHoleRadius);

PHoles[1] = new THole(cLongWallCenter2, cHoleRadius);

PHoles[2] = new THole(cShortWallCenter1, cHoleRadius);

PHoles[3] = new THole(cShortWallCenter2, cHoleRadius);

// Создать шары (черные и один белый) между стенками

StartPoint.X = (cLongWallCenter1.X+cLongWallCenter2.X)/2;

StartPoint.Y = (cLongWallCenter1.Y+cLongWallCenter2.Y)/2;

PTheWhiteBall = new TWhiteBall(StartPoint, cBallRadius);

PBalls[0] = PTheWhiteBall;

// запомнить указатель на белый шар

for(i=1; i<cBallsNumber;i++) PBalls[i] =

new TBlackBall(StartPoint, cBallRadius);

Initiate();

// установить первоначальную расстановку шаров

};

void TTable::HandleEvent(TEvent* anEvent)

{

switch (anEvent->What)

{

case EvStart: Start(); anEvent->What = EvNothing; break;

case EvInitiate: Initiate(); anEvent->What = EvNothing; break;

case EvTick: Update(); anEvent->What = EvNothing; break;

};

};

void TTable::Initiate()

{

TPoint aPoint, CenterPoint;

int i, NInRow, iBall;

// Отобразить стенки и лузы

for(i=0; i<cWallsNumber;i++) PWalls[i]->Show();

for(i=0; i<cHolesNumber;i++) PHoles[i]->Show();

// Установить белый шар в исходную позицию

// и лишить энергии

CenterPoint.X = (cLongWallCenter1.X+cLongWallCenter2.X)/2 - 4*cBallRadius;

CenterPoint.Y = (cLongWallCenter1.Y+cLongWallCenter2.Y)/2;

PTheWhiteBall->SetOnTable(CenterPoint);

// Установить черные шары треугольником

// Начальная точка в четырех диаметрах от белого шара

CenterPoint.X = CenterPoint.X+4*2*cBallRadius;

NInRow = 1;

iBall = 1;

while(iBall<cBallsNumber)

{

// Установить шары текущего ряда

aPoint.X = CenterPoint.X;

aPoint.Y = CenterPoint.Y + (cBallRadius+cSmallDistance)

*(NInRow-1);

for(i=1; (i<=NInRow)&&(iBall<cBallsNumber); i++)

{

PBalls[iBall]->SetOnTable(aPoint);

iBall = iBall+1;

aPoint.Y = aPoint.Y-2*(cBallRadius+cSmallDistance);

}; // -текущий ряд

NInRow = NInRow + 1;

// в следующем ряду на один шар больше

// Переместить центр

CenterPoint.X = CenterPoint.X+2*(cBallRadius+cSmallDistance);

}; // -while

// Обнулить энергию у всех шаров

// и придать случайное направление

for(iBall=0; iBall<cBallsNumber; iBall++)

{

PBalls[iBall]->SetEnergy(0.0);

PBalls[iBall]->SetDirection(2*Pi*rand()/RAND_MAX);

};

};

void TTable::Start()

{

// Белому шару - случайное направление

// и максимальную энергию

PTheWhiteBall->SetDirection(rand()*2.0*Pi/RAND_MAX);

PTheWhiteBall->SetEnergy(cMaxEnergy);

};

void TTable::Update()

{

int i,j;

// Для каждого шара анализировать взаимодействия

for(i=0;i<cBallsNumber;i++)

{

// Проверить на столкновение с лузами

for(j=0; j<cHolesNumber;j++) PBalls[i]->HitOnHole(PHoles[j]);

// Проверить на столкновение со стенками

for(j=0; j<cWallsNumber;j++) PBalls[i]->HitOnWall(PWalls[j]);

// Проверить на столкновение шаров между собой

for(j=i+1; j<cBallsNumber;j++) PBalls[i]->HitOnBall(PBalls[j]);

};

// Переместить шары

for(i=0;i<cBallsNumber;i++)

{

PBalls[i]->Move();

};

// Перерисовать стенки и лузы

for(i=0; i<cWallsNumber;i++) PWalls[i]->Show();

for(i=0; i<cHolesNumber;i++) PHoles[i]->Show();

};

TTable::~TTable()

{

int i;

// Удалить все динамические массивы

for(i=0; i<cWallsNumber; i++)

{PWalls[i]->Hide(); delete PWalls[i];};

for(i=0; i<cHolesNumber; i++)

{PHoles[i]->Hide(); delete PHoles[i];};

for(i=0; i<cBallsNumber; i++)

{PBalls[i]->Hide(); delete PBalls[i];};

};

TReality::TReality()

{

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

int gdriver = DETECT, gmode, errorcode;

initgraph(&gdriver, &gmode,"\\bc\\bin");

// Создать экземпляр Бильярдного стола

PTheTimer = new TTimer(cTimerInterval);

PTheTable = new TTable;

}

void TReality::Run()

{

TEvent theEvent; // создать экземпляр объекта Событие

theEvent.What = EvNothing; // еще ничего не произошло

// Цикл получения и генерации событий

do{

// Событие от таймера

PTheTimer->HandleEvent(&theEvent);

// Событие от клавиатуры

if (kbhit())

{ char ch = getch(); strupr(&ch);

switch(ch)

{

case 'I': theEvent.What = EvInitiate; break;

case 'S': theEvent.What = EvStart; break;

case 'Q': theEvent.What = EvQuit; break;

}; // -case ch

}; // -if

// Переслать сообщение о событии возможному получателю

// и, может быть, получить от него

PTheTable->HandleEvent(&theEvent);

} while(theEvent.What!= EvQuit);

}; // -TReality::Run()

TReality::~TReality()

{

delete PTheTable; // убрать стол

delete PTheTimer; // убрать таймер

closegraph(); // отменить графический режим для дисплея

};

 

// main.cpp - Головная программа системы Бильярд

#include"billiard.h"

int main()

{ TReality theReality; // Инициализация всего

theReality.Run(); // Имитация процесса

return(0);

};

ПРИЛОЖЕНИЕ 2.
Текст программы-драйвера

 

// Проект "Бильярд". Драйвер для тестирование подпрограммы

// void TBall::HitOnBall(TBall* aBall)

#include<iostream.h>

#include<graphics.h>

#include"billiard.h"

// Подпрограмма сравнения результатов

// с ожидаемыми значениями

void OutputResults

(TBall *ActiveBall, TBall *PassiveBall,

/*активный и пассивный шары*/

float ExDirection1, float ExEnergy1,

/*Ожидаемые направление и энергия активного шара*/

float ExDirection2, float ExEnergy2)

/*Ожидаемые направление и энергия пассивного шара*/

{

cout << "Результаты теста:" << endl;

cout << " Активный шар" << endl;

cout << " атрибут theDirection: ";

if(ActiveBall->GetDirection()!= ExDirection1)

cout << "ОШИБКА!";

cout << " факт " << ActiveBall->GetDirection()

<< "; ожидается " << ExDirection1 << endl;

cout << " атрибут theEnergy: ";

if(ActiveBall->GetEnergy()!= ExEnergy1)

cout << "ОШИБКА!";

cout << " факт " << ActiveBall->GetEnergy()

<< "; ожидается " << ExEnergy1 << endl;

cout << " Пассивный шар" << endl;

cout << " атрибут theDirection: ";

if(PassiveBall->GetDirection()!= ExDirection2)

cout << "ОШИБКА!";

cout << " факт " << PassiveBall->GetDirection()

<< "; ожидается " << ExDirection2 << endl;

cout << " атрибут theEnergy: ";

if(PassiveBall->GetEnergy()!= ExEnergy2)

cout << "ОШИБКА!";

cout << " факт " << PassiveBall->GetEnergy()

<< "; ожидается " << ExEnergy2 << endl;

};

// Подпрограмма исполнения отдельного теста

void Testing

(int NTest,/*номер теста*/ float aRadius,

/*радиус шаров*/ TPoint aCenter1, float aDirection1,

float anEnergy1, /*Заданные центр, направление и энергия активного шара*/

TPoint aCenter2, float aDirection2, float anEnergy2,

/*Заданные направление и энергия пассивного шара*/

float ExDirection1, float ExEnergy1,

/*Ожидаемые направление и энергия активного шара*/

float ExDirection2, float ExEnergy2

/*Ожидаемые направление и энергия пассивного шара*/

)

{

TBall *theBall1, *theBall2;

// указатели на активный и пассивный шары

// Инициализация входных данных (объектов)

theBall1 = new TBlackBall(aCenter1, aRadius);

theBall2 = new TBlackBall(aCenter2, aRadius);

theBall1->SetDirection(aDirection1);

theBall1->SetEnergy(anEnergy1);

theBall2->SetDirection(aDirection2);

theBall2->SetEnergy(anEnergy2);

// Вывод входных данных в листинг

cout << endl << "---------Тест N " << NTest << endl;

cout << "Входные данные:" << endl;

cout << " Активный шар" << endl;

cout << " theCenter "

<< theBall1->GetCenter().X << ","

<< theBall1->GetCenter().X

<< "; theRadius " << aRadius << endl;

cout << " theDirection " << theBall1->GetDirection()

<< "; theEnergy " << theBall1->GetEnergy() << endl;

cout << " Пассивный шар" << endl;

cout << " theCenter "

<< theBall2->GetCenter().X << ","

<< theBall2->GetCenter().X

<< "; theRadius " << aRadius << endl;

cout << " theDirection " << theBall2->GetDirection()

<< "; theEnergy " << theBall2->GetEnergy() << endl;

// Выполнение тестируемой подпрограммы

theBall1->HitOnBall(theBall2);

// Анализ результатов теста

OutputResults(theBall1, theBall2, ExDirection1, ExEnergy1,

ExDirection2, ExEnergy2);

delete theBall1;

delete theBall2;

};

// Головная программа драйвера

int main()

{

// Заголовок

cout << "Тестирование подпрограммы" << endl;

cout << "void TBall::HitOnBall(TBall* aBall)"

<< endl << endl;

// Подготовка входных данных

const int cBallRadius = 5;

const float cMaxEnergy = 200;

TPoint thePoint1 = {5,10};

TPoint thePoint2 = {10,10};

TPoint thePoint3 = {100,20};

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

int gdriver = DETECT, gmode, errorcode;

initgraph(&gdriver, &gmode,"\\bc\\bin");

// Реализация тестов

Testing(5, cBallRadius, thePoint1, Pi/4+Pi/2, 0.1*cMaxEnergy,

thePoint2, Pi/4, 0.3*cMaxEnergy,

Pi/4, 0.2*cMaxEnergy, Pi/4+Pi/2, 0.2*cMaxEnergy);

Testing(6, cBallRadius, thePoint1, Pi/4, 0.7*cMaxEnergy,

thePoint2, Pi/4+Pi/2, 0.3*cMaxEnergy,

Pi/4, 0.5*cMaxEnergy, Pi/4+Pi/2, 0.5*cMaxEnergy);

Testing(7, cBallRadius, thePoint1, Pi/4+Pi/2, cMaxEnergy/2,

thePoint3, Pi/4, cMaxEnergy/3,

Pi/4+Pi/2, cMaxEnergy/2, Pi/4, cMaxEnergy/3);

closegraph(); // отменить графический режим для дисплея

// Сравнение полученных данных с ожидаемым результатом

return 0;

}

ПРИЛОЖЕНИЕ 3.
Листинг тестирования

Тестирование подпрограммы

void TBall::HitOnBall(TBall* aBall)

---------Тест N 5

Входные данные:

Активный шар

theCenter 5,5; theRadius 5

theDirection 2.356194; theEnergy 20

Пассивный шар

theCenter 10,10; theRadius 5

theDirection 0.785398; theEnergy 60

Результаты теста:

Активный шар

атрибут theDirection: ОШИБКА! факт 0.785398; ожидается 0.785398

атрибут theEnergy: факт 40; ожидается 40

Пассивный шар

атрибут theDirection: факт 2.356194; ожидается 2.356194

атрибут theEnergy: факт 40; ожидается 40

---------Тест N 6

Входные данные:

Активный шар

theCenter 5,5; theRadius 5

theDirection 0.785398; theEnergy 140

Пассивный шар

theCenter 10,10; theRadius 5

theDirection 2.356194; theEnergy 60

Результаты теста:

Активный шар

атрибут theDirection: ОШИБКА! факт 2.356194; ожидается 0.785398

атрибут theEnergy: факт 100; ожидается 100

Пассивный шар

атрибут theDirection: ОШИБКА! факт 0.785398; ожидается 2.356194

атрибут theEnergy: факт 100; ожидается 100

---------Тест N 7

Входные данные:

Активный шар

theCenter 5,5; theRadius 5

theDirection 2.356194; theEnergy 100

Пассивный шар

theCenter 100,100; theRadius 5

theDirection 0.785398; theEnergy 66.666664

Результаты теста:

Активный шар

атрибут theDirection: факт 2.356194; ожидается 2.356194

атрибут theEnergy: факт 100; ожидается 100

Пассивный шар

атрибут theDirection: факт 0.785398; ожидается 0.785398

атрибут theEnergy: факт 66.666664; ожидается 66.666664

Список рекомендуемой литературы

1. Липаев В.В. Проектирование программных средств. М.: Высш.шк., 1990. - 303 с.

2. Буч Г. Объектно-ориентированное проектирование / Пер. с англ. - Конкорд, 1992. - 519 с.

3. Бадд Т. Объектно-ориентированное программирование в действии / Пер. с англ. - СПб: Питер, 1997. - 464 с.

4. Майерс Г. Надежность программного обеспечения. М.: Мир, 1980. - 360 с.

5. Липаев В.В. Отладка сложных программ: Методы, средства, технология. - М.: Энергоатомиздат, 1993. - 384 с.

6. Калянов Г.Н. CASE структурный системный анализ (автоматизация и применение). - М.: "ЛОРИ", 1996. - 242 с.


ОГЛАВЛЕНИЕ

 

1. Общие методические указания................................................................

1.1. Цель и тематика курсовой работы....................................................

1.2. Системный анализ..............................................................................

1.3. Проектирование.................................................................................

1.4. Программирование..........................................................................

1.5. Тестирование....................................................................................

2. Пример разработки программной системы.........................................

2.1. Формулировка задачи.....................................................................

2.2. Системный анализ............................................................................

2.3. Проектирование...............................................................................

2.4. Программирование..........................................................................

2.5. Тестирование....................................................................................

3. Порядок выполнения работы...............................................................

Приложение 1. Тексты программы учебного примера “Бильярд”........

Приложение 2. Текст программы-драйвера...........................................

Приложение 3. Листинг тестирования.....................................................

Список рекомендуемой литературы.........................................................

 

ТЕХНОЛОГИЯ ПРОГРАММИРОВАНИЯ

Методические указания к курсовой работе

 

Составители: ДУБОВ Илья Ройдович,

БАРКОВ Валерий Андреевич,

ДОЛИНИН Александр Геннадиевич

 

Ответственный за выпуск - зав.кафедрой профессор А.В.Костров

 

Редактор Е.П.Викулова

 

Лицензия N 020275 от 13.11.96 г.

Подписано в печать 12.03.99. Формат 60x84/16. Бумага для множит. техники.
Гарнитура Times. Печать офсетная. Усл.печ.л.. Уч.-изд.л. 2,98.
Тираж 100 экз. С - Зак.

Владимирский государственный университет.

Подразделение оперативной полиграфии Владимирского государственного
университета.

Адрес университета и подразделения оперативной полиграфии:
600026, Владимир, ул. Горького, 87.

 



Поделиться:


Последнее изменение этой страницы: 2016-12-17; просмотров: 190; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 13.58.137.218 (0.716 с.)