Объектно-ориентированное программирование методичка
МЕТОДИЧЕСКИЕ УКАЗАНИЯ
ПО ВЫПОЛНЕНИЮ КУРСОВОЙ РАБОТЫ
ПО ДИСЦИПЛИНЕ
«ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ»
1. ОБЩАЯ ЧАСТЬ
Курсовая работа студента – заключительный этап изучения определенной дисциплины. Цель работы – систематизация и закрепление теоретических знаний, полученных за время обучения, а также приобретение и закрепление навыков самостоятельной работы. Работа, как правило, основывается на обобщении изученного студентом теоретического материала и дальнейшего его практического осмысления и подготавливается к защите в завершающий период теоретического обучения.
В этой работе студент на основе изучения теоретической части курса «Объектно-ориентированное программирование» использует знания по вопросам проектирования и реализации программ с объектно-ориентированным подходом.
Курсовая работа должна быть подготовлена к защите в срок. К защите курсовой работы представляется:
– пояснительная записка;
– электронная реализация в виде программы и данных.
Пояснительная записка содержит основной текст, графические материалы (иллюстрации) и, при необходимости, приложения – разработанную программу с исходным текстом на бумажном и дисковом носителе, исходные данные и результаты.
Пояснительная записка включает следующие компоненты:
— титульный лист;
— задание на курсовую работу;
— оглавление, включающее наименование всех разделов и пунктов с указанием номеров страниц;
— введение, в котором обосновывается актуальность темы, указываются цель и задачи работы;
— теоретическую часть, освещающую теоретические аспекты темы (один из вопросов);
— практическую часть, в которой разработка программы и ее результаты (одна из задач);
— заключение с краткими выводами по результатам работы;
— список литературы.
Последовательность выполнения курсовой работы включает следующие этапы:
— уточнение задания;
— анализ теоретических источников;
— выбор методов, структур и их обоснование;
— определение наборов исходных данных и алгоритмов их обработки;
— решение поставленной задачи на компьютере и получение результатов;
— анализ полученных результатов;
— оформление пояснительной записки.
2. ТРЕБОВАНИЯ К СОДЕРЖАНИЮ СТРУКТУРНЫХ ЭЛЕМЕНТОВ ТЕКСТОВОЙ ЧАСТИ КУРСОВОЙ РАБОТЫ
2.1 Титульный лист
Титульный лист является первым листом курсовой работы. Переносы слов в надписях титульного листа не допускаются. Образец титульного листа представлен в приложении А.
2.2 Задание
Задание на курсовую работу составляется на кафедре.
2.3 Содержание
Структурный элемент «Содержание» включает введение, порядковые номера и заголовки разделов, при необходимости подразделов, заключение, список использованных источников, приложения с указанием их обозначений и заголовков. После заголовка каждого из указанных структурных элементов ставят отточие, а затем приводят номер страницы, на которой начинается данный структурный элемент.
Элемент «Содержание» размещают после аннотации, начиная с нового листа. Слово «Содержание» записывают в верхней части листа, посередине, с прописной буквы.
2.4 Введение
В элементе «Введение» указывают цель работы, область применения разрабатываемой предметной области, ее практическое значение.
Элемент «Введение» размещают на отдельном листе после содержания. Слово «Введение» записывают в верхней части листа, посередине, с прописной буквы.
2.5 Основная часть
Содержание основной части работы должно быть представлено в виде двух разделов: теоретической части и практической. Теоретическая часть раскрывает основные понятия темы курсовой работы. Практическая часть должна отвечать заданию и требованиям, изложенным в методических указаниях.
Основная часть состоит из разделов и подразделов. При оформлении основной части используют словосочетания «Теоретическая часть» и «Практическая часть». Теоретическая часть является первым разделом, практическая – вторым. Элемент «Теоретическая часть» и «Практическая часть» располагают на отдельных листах. Указания к выполнению практической части приведены в приложении Б.
2.7 Заключение
Заключение должно содержать краткие выводы по результатам выполненной работы, оценку полноты решения поставленных задач, рекомендации по конкретному использованию результатов работы.
Элемент «Заключение» размещают на отдельном листе после практической части. Слово «Заключение» записывают в верхней части листа, посередине, с прописной буквы.
2.8 Список использованных источников
В список включают все источники, на которые имеются ссылки в тексте работы. Сведения об источниках следует располагать в порядке появления ссылок в тексте, нумеровать арабскими цифрами без точки и печатать с абзацного отступа. Ссылки в тексте приводят в квадратных скобках.
Пример – [5], [7, 8, 9], [8-13, 44-56].
Допускается располагать сведения об источниках в списке:
— в алфавитном порядке;
— по разделам;
— по видам источников.
При составлении списка в алфавитном порядке и наличии в нем источников на разных языках образуются дополнительные алфавитные ряды, которые приводят в следующей последовательности: на русском языке, на языках с кириллическим алфавитом, на языках с латинским алфавитом, на языках с оригинальной графикой. Нумерация источников в списке сохраняется сквозная. Структурный элемент «Список использованных источников» размещают после заключения. Словосочетание «Список использованных источников» приводят в верхней части листа, посередине, с прописной буквы.
2.9 Приложения
Материал, дополняющий основную часть работы, оформляют в виде приложений. В приложениях целесообразно приводить графический материал большого объема и/или формата, таблицы большого формата.
Приложения следует оформлять как продолжение работы на листах, следующих за списком использованных источников. Приложения выполняют на листах формата А4.
Приложения обозначают прописными буквами русского алфавита, начиная с А (за исключением букв Ё, З, Й, О, Ч, Ь, Ы, Ъ), которые приводят после слова «Приложение». В случае полного использования букв русского алфавита приложения обозначают арабскими цифрами. При наличии в работе одного приложения оно обозначается «Приложение А».
3. ОФОРМЛЕНИЕ КУРСОВОЙ РАБОТЫ
Текст выполняется на листах формата А4 (210х297 мм) по ГОСТ 2.301 с применением печатающих устройств вывода ЭВМ (ГОСТ 2.004). На компьютере текст должен быть оформлен в текстовом редакторе.
Тип шрифта: Times New Roman.
Шрифт основного текста – обычный, размер 14 пт.
Шрифт заголовков подразделов – полужирный, размер 14 пт.
Межсимвольный интервал – обычный.
Межстрочный интервал – одинарный. Выравнивание текста по ширине.
Абзацный отступ должен быть одинаковым по всему тексту и равен 15 мм.
Текст работы выполняется на листах формата А4, без рамки, с соблюдением следующих размеров полей:
а) левое – не менее 30 мм;
б) правое – не менее 10 мм;
в) верхнее и нижнее – не менее 20 мм.
Страницы следует нумеровать арабскими цифрами, соблюдая сквозную нумерацию по всему тексту.
Номер страницы проставляют в центре нижней части листа без точки.
Опечатки, описки и графические неточности, обнаруженные в процессе выполнения, допускается исправлять подчисткой или закрашиванием белой краской и нанесением на том же месте исправленного текста. Помарки и следы не полностью удаленного прежнего текста не допускаются.
Объем работы должен составлять не менее 25 страниц основной части. Изложение должно быть последовательным, логичным, конкретным.
4. ПРИМЕРНЫЕ ТЕМЫ КУРСОВЫХ РАБОТ
— Динамическое распределение памяти и его значимость в реализации ООП парадигмы.
— Шаблоны проектирования.
— Перегружаемые методы. Способы реализации и назначение.
— Обзор технологий OLE и COM.
— История возникновения объектно-ориентированного подхода.
— Наследование. Преимущества повторного использования кода
— Понятие класса. Основное назначение. Принципы создания классов.
— Визуальное программирование.
— Обзор созданных библиотек для упрощенного создания оконных приложений.
— Интегрированные сред разработки ПО и ООП.
5. ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ
Библиотека визуальных компонентов VCL и ее базовые классы
Все классы библиотеки визуальных компонентов произошли от группы базовых классов, которые лежат в основе иерархии VCL. Самый общий предок компонентов — это класс TObject, инкапсулирующий простейший объект. Как известно, каждый объект наследует свойства и методы родительского класса. К объекту можно добавить новые свойства и методы, но нельзя удалить унаследованные. Объект-наследник в свою очередь может стать родительским для нового класса, который унаследует возможности всех своих предков.
Поэтому иерархия базовых классов VCL продумана чрезвычайно тщательно — ведь на их основе создано все множество компонентов, используемых в Delphi. Особое место среди базовых классов, помимо TObject, занимают TComponent (от него происходят все компоненты) и TControl (от него происходят все элементы управления).
Класс TObject
Класс TObject является родоначальником всей иерархии классов VCL. Он реализует функции, которые обязательно будет выполнять любой объект, который может быть создан в среде разработки. Из-за большого разнообразия его потомков, круг общих для всех классов операций весьма невелик.
В первую очередь — это создание экземпляра объекта и его уничтожение. Любой объект выполняет эти две операции в обязательном порядке.
Процесс создания объекта включает выделение области адресного пространства, установку указателя на экземпляр объекта, задание начальных значений свойств и выполнение установочных действий, связанных с назначением объекта. В общем случае две последние операции могут не выполняться.
Указатель на экземпляр объекта передается в переменную объектного типа, которая в дальнейшем будет идентифицировать объект в программном коде приложения. В приведенном выше фрагменте кода переменная объектного типа SomeList объявлена как экземпляр типа TStrings. При создании экземпляра этого типа конструктор Create возвращает в переменную SomeList указатель на выделенную для нового объекта область памяти. Для этого применяется метод Newinstance, который вызывается в конструкторе автоматически:
class function Newinstance: TObject; virtual;
Объект класса TObject обеспечивает выполнение этого процесса для любого порожденного от него объекта. А уже внутри конструктора, который унаследован от класса TObject, можно предусмотреть инициализацию переменных и выполнение дополнительных операций.
Объявление конструктора выглядит следующим образом:
constructor Create;
В конструкторах потомков это объявление может перекрываться, но при необходимости вызвать конструктор предка используется оператор inherited:
constructor TSomeObject. Create;
begin
inherited Create;
end;
Для уничтожения экземпляра объекта в классе TObject предназначены методы Destroy и Free:
Абстрактный класс TОbjeсt является базовым классом, от которого произошли все остальные классы.
Разработчикам компонентов вовсе не обязательно создавать свои компоненты как непосредственные потомки класса TОbjeсt. Библиотека VCL предоставляет широкий выбор классов потомков класса TОbjeсt, и создаваемые компоненты могут быть производными от них. Эти уже существующие классы обеспечивают большинство функциональных возможностей, которые могут понадобиться новым компонентам. Лишь при создании классов, не являющихся компонентами, имеет смысл делать их потомками класса TОbjeсt.
Методы Create() и Destroy() класса TОbjeсt предназначены для выделения и освобождения памяти для экземпляра объекта. Конструктор TОbjeсt. Create() возвращает указатель на созданный объект. Класс TОbjeсt содержит несколько полезных функций, позволяющих получить информацию об объекте.
Библиотека VCL использует в основном внутренние вызовы методов класса TОbjeсt, что позволяет получить необходимую информацию о типе класса, его имени, базовых классах (предках) для экземпляра любого класса, поскольку все они являются потомками TОbjeсt.
Класс TControl
Класс TControl определяет свойства, методы и события, общие для большинства визуальных компонентов. Например, класс TControl позволяет визуальным компонентам отображаться на экране. Класс TControl содержит такие позиционные свой ства, как Top и Left, свойства размеров Width и Height, значения которых определяют размеры элемента по горизонтали и вертикали. Имеются и некоторые другие свойства: ClientRect, ClientWidth и ClientHeight.
Класс TControl содержит свойства, отвечающие за внешний вид и доступ к ком поненту: Visible, Enabled и Color. В свойстве Font даже можно задать шрифт, используемый для текста, помещаемого в компонент TControl. Этот текст выводится с помощью свойств Text и Caption.
В классе TControl впервые появляются некоторые стандартные события: события мыши — OnClick, OnDblClick, OnMouseDown, OnMouseMove и OnMouseUp, а также со бытия перетаскивания с помощью мыши — OnDragOver, OnDragDrop и OnEndDrag.
Сам по себе класс TControl не очень полезен на своем уровне иерархии. Прямые потомки этого класса никогда не создаются. Компонент TControl может иметь родительский компонент. Он обязательно должен принадлежать классу TWinControl (в VCL) или TWidgetControl (в CLX). Родительские элементы управления должны быть оконными (windowed) элементами управления. Для этого в класс TControl введено свойство Parent.
Таблица 1.
Некоторые события класса TForm:
Событие |
Описание |
OnActivate |
Cобытие наступает, когда форма становится активной, т. е. получает фокус, например при щелчке на ней. |
OnClose |
Событие наступает при закрытии формы после события OnCloseQuery. |
OnCloseQuery |
Первое событие при закрытии формы. В его обработчике можно прервать закрытие. |
OnCreate |
Первое событие при создании формы. В его обработчике можно настроить форму и ее компоненты. |
OnDiactivate |
Событие наступает когда форма перестает быть активной. |
OnDestroy |
Последнее событие при закрывании формы и удалении ее из памяти. |
OnHelp |
Событие наступает при запросе пользователем помощи. |
OnHide |
Событие наступает перед тем, как форма становится невидимой. |
OnPaint |
Событие наступает перед прорисовкой формы. |
OnShortCut |
Событие наступает при нажатии клавиши пользователем |
OnShow |
Наступает перед тем, как форма становится видимой. |
onKeyDown |
когда при нажатии на кнопку на клавиатуре она оказалась в нижнем положении |
onKeyUp |
когда при отпускании клавиатурной кнопки она оказалась в верхнем положении |
onKeyPress |
возникает при нажатии на клавиатурную кнопку. От событий onKeyDown и onKeyUp — оно отличается типом используемого параметра Key |
onMouseDown |
когда при нажатии кнопки мышки она оказалась в нижнем положении |
onMouseUp |
когда при отпускании кнопки мышки она оказалась в верхнем положении |
onMouseMove |
возникает при перемещении указателя мышки над компонентом |
Художник в своей работе использует карандаши и кисти. Методы, обеспечивающие вычерчивание на поверхности холста графических примитивов, тоже используют карандаш и кисть. Карандаш применяется для вычерчивания линий и контуров, а кисть — для закрашивания областей, ограниченных контурами.
Карандашу и кисти, используемым для вывода графики на холсте, соответствуют свойства Реn (карандаш) и Brush (кисть), которые представляют собой объекты типа ТРеn и TBrush, соответственно. Значения свойств этих объектов определяют вид выводимых графических элементов.
Карандаш
Карандаш используется для вычерчивания точек, линий, контуров геометрических фигур: прямоугольников, окружностей, эллипсов, дуг и др. Вид линии, которую оставляет карандаш на поверхности холста, определяют свойства объекта треп, которые перечислены в табл. 2.
Таблица 2.
Свойства объекта ТРеn (карандаш)
Свойство |
Определяет |
Color |
Цвет линии |
Width |
Толщину линии |
Style |
Вид линии |
Mode |
Режим отображения |
Свойство Color задает цвет линии, вычерчиваемой карандашом. В табл. 3 перечислены именованные константы (тип TColor), которые можно использовать в качестве значения свойства Color.
Таблица 3.
Значение свойства Color определяет цвет линии
Константа |
Цвет |
Константа |
Цвет |
clBlack |
Черный |
clSilver |
Серебристый |
clMaroon |
Каштановый |
clRed |
Красный |
clGreen |
Зеленый |
clLime |
Салатный |
clOlive |
Оливковый |
clBlue |
Синий |
clNavy |
Темно-синий |
clFuchsia |
Ярко-розовый |
clPurple |
Розовый |
clAqua |
Бирюзовый |
clTeal |
Зелено-голубой |
clWhite |
Белый |
clGray |
Серый |
Свойство width задает толщину линии (в пикселах). Например, инструкция canvas. Pen. width: =2 устанавливает толщину линии в 2 пиксела.
Свойство style определяет вид (стиль) линии, которая может быть непрерывной или прерывистой, состоящей из штрихов различной длины. В табл. 4 перечислены именованные константы, позволяющие задать стиль линии. Толщина пунктирной линии не может быть больше 1. Если значение свойства Pen. width больше единицы, то пунктирная линия будет выведена как сплошная.
Таблица 4.
Значение свойства Реn. Туре определяет вид линии
Константа |
Вид линии |
psSolid |
Сплошная линия |
psDash |
Пунктирная линия, длинные штрихи |
psDot |
Пунктирная линия, короткие штрихи |
psDashDot |
Пунктирная линия, чередование длинного и короткого штрихов |
psDashDotDot |
Пунктирная линия, чередование одного длинного и двух коротких штрихов |
psClear |
Линия не отображается (используется, если не надо изображать границу области, например, прямоугольника) |
Кисть
Кисть (canvas. Brush) используется методами, обеспечивающими вычерчивание замкнутых областей, например геометрических фигур, для заливки (закрашивания) этих областей. Кисть, как объект, обладает двумя свойствами, перечисленными в табл. 5.
Таблица 5.
Свойства объекта TBrush (кисть)
Свойство |
Определяет |
Color |
Цвет закрашивания замкнутой области |
Style |
Стиль (тип) заполнения области |
Область внутри контура может быть закрашена или заштрихована. В первом случае область полностью перекрывает фон, а во втором — сквозь незаштрихованные участки области будет виден фон.
В качестве значения свойства Color можно использовать любую из констант типа TColor (см. список констант для свойства Pen. Color в табл. 4).
Константы, позволяющие задать стиль заполнения области, приведены в табл. 6.
Таблица 6.
Значения свойства Brush, style определяют тип закрашивания
Константа |
Тип заполнения (заливки) области |
bsSolid |
Сплошная заливка |
bsClear |
Область не закрашивается |
bsHorizontal |
Горизонтальная штриховка |
bsVertical |
Вертикальная штриховка |
bsFDiagonal |
Диагональная штриховка с наклоном линий вперед |
bsBDiagonal |
Диагональная штриховка с наклоном линий назад |
bsCross |
Горизонтально-вертикальная штриховка, в клетку |
bsDiagCross |
Диагональная штриховка, в клетку |
Функции для создания геометрических объектов
procedure Ellipse(X1, Y1, X2, Y2: Integer);
Метод Ellipse рисует окружность или эллипс с помощью текущих параметров пера Pen. Фигура заполняется текущим значением Brush. Точки (X1, Y1) и (X2, Y2) определяют прямоугольник, описывающий эллипс.
procedure Rectangle(X1, Y1, X2, Y2: Integer);
Рисует на канве текущим пером Pen прямоугольник верхний левый угол, которого имеет координаты (X1, Y1), а нижний правый — (X2, Y2). Прямоугольник закрашивается текущей кистью Brush.
Приложение А
Министерство образования и науки РФ
ФГБОУ ВПО «Волгоградский государственный
архитектурно-строительный университет»
Себряковский филиал
Кафедра математических и естественно-научных дисциплин
Пояснительная записка к курсовой работе
по дисциплине
«Объектно-ориентированное программирование»
Тема работы:
« Динамическое распределение памяти и его значимость в
реализации ООП парадигмы»
Выполнил студент гр. <группа>
Иванов И. И.
Проверил <должность >:
Иванов И. И.
Михайловка 2013
Приложение Б
Создаем новый проект:
1.Проект → Создать проект
2.Выбираем тип проекта приложение:
3. Добавляем в проект обработчик события нажатия кнопок мыши : OnMouseDown
4. Добавим в модуль реализации
Form1.Canvas. Ellipse(X+sizeObj, Y+sizeObj, X-sizeObj, Y-sizeObj);
где sizeObj — глобальную константу определяющую размер фигуры: const sizeObj=20;
5. Запускаем созданный нами проект (F9) и тестируем, что у нас получилось.
Вне зависимости от того какой кнопкой мыши мы щелкаем, происходит добавление нового круга на экран.
Но как только вы пробуйте изменить размеры окна. Ваша форма перерисовывается заново и изменения не сохраняются.
Закомментируем код рисования эллипса.
6. Создадим объекты, которые будут оставаться в программе в течение всего времени жизни главного окна. Добавляем в проект обработчик события рисования окна : OnPaint.
Создадим прямоугольники, которые будут располагаться в верхней части окна. Так как размеры окна могут меняться, то пусть количество нарисованных прямоугольников меняется в зависимости от ширины окна (Form1.Width).
procedure TForm1.FormPaint(Sender: TObject);
var i:integer;
begin
for i:=0 to Round(Form1.Width/sizeObj) do
Form1.canvas. Rectangle(sizeObj*i, 0, sizeObj*(i+1), sizeObj);
end;
7. Теперь у нас есть проблема. Так как окно может быль любых размеров, то нарисованные прямоугольники помещаются в окне не целое количество раз. Сделаем так, чтобы размеры окна были только кратными переменной sizeObj. Для этого добавляем в проект обработчик события изменения размера окна : OnResize
Добавим в модуль реализации :
Form1.Width :=sizeObj*round(Form1.Width/sizeObj);
8. Создайте такую же границу из прямоугольников с обоих боков окна.
Результат:
Обратите особое внимание, что для боковых границ последнее значение счетчика цикла рассчитывается с помощью значения высоты окна(Form1. Height/sizeObj).
Теперь процедура FormPaint выглядит так:
procedure TForm1.FormPaint(Sender: TObject);
var i:integer;
begin
for i:=0 to Round(Form1.Width/sizeObj) do {create Top Windows}
Form1.canvas. Rectangle(sizeObj*i, 0, sizeObj*(i+1), sizeObj);
for i:=0 to Round(Form1. Height/sizeObj) do {create Left Windows}
Form1.canvas. Rectangle(0,sizeObj*i, sizeObj, sizeObj*(i+1));
for i:=0 to Round(Form1. Height/sizeObj) do {create Right Windows}
Form1.canvas. Rectangle(Form1.Width, sizeObj*i,
Form1.Width — sizeObj, sizeObj*(i+1));
end;
9. Сделайте такое же, как в пункте 7 ограничение, но еще для высоты окна (Form1. Height)
10. Создадим три прямоугольника, которые будут управляться с помощью клавиатуры. Для обработки событий клавиатуры добавляем в проект обработчик события нажатия клавиши: OnKeyDown:
Для управления будут использоваться стрелки.
Обратим внимание, что в нашу процедуру передается параметр Key типа Word. Это некоторое цифровое значение клавиш, чтобы узнать его можно воспользоваться какой-нибудь справочной литературой. Но если таковой под рукой нет, поступим следующим образом: Напишем в этой процедуре код:
ShowMessage(IntToStr(Key)) ;
И теперь запустим нашу программу и нажимая необходимую нам клавишу увидим сообщение с ее кодом. Так определяем «←» = 37, «→» =39. Если же вам нужна какая-то английская буква то можно воспользоваться функцией Ord (‘S’).
При нажатии на клавишу объект должен перемешаться, т. е. должны изменяться его координаты. Для этого необходимо чтобы значение координат где-то хранилось. Создадим глобальную переменную coorXObj хранящую значение по Х. Тип этой переменной будет Integer, при этом присвоим значение по умолчанию coorXObj:integer=sizeObj;
11. Продолжаем работу в обработчике события нажатие клавиши.
При Key=37 значение coorXObj уменьшаем, а при Key=39 значение coorXObj увеличиваем.
if Key=37 then coorXObj:=coorXObj-sizeObj ;
if Key=39 then coorXObj:=coorXObj+sizeObj ;
12. Для того чтобы наш объект изображался, необходимо его рисовать в процедуре FormPaint :
Form1.canvas. Rectangle(coorXObj, Form1.Height — sizeObj,
coorXObj+sizeObj, Form1.Height);
13. Запустим проект на тестирование. Обнаружим, что наш объект не реагирует на нажатия клавиш. Это связано с тем, что при нажатии клавиш не происходит перерисовка окна. Значит, в процедуре FormKeyDown наверное необходимо вызывать процедуру рисования окна.
FormPaint(Sender);
14. Запустим проект на тестирование. Наблюдаем ошибку, предыдущее положение объекта не стирается с окна. Поэтому необходимо вызывать не процедуру рисования, а процедуру перерисовки окна
Form1.Repaint
15. Однако некоторые аномалии поведения еще остались. Например если объект вывести за приделы экрана, то обратно он возвращается не сразу. Поэтому на значение этой переменной coorXObj должны быть наложены ограничения.
sizeObj <=coorXObj and coorXObj <= (Form1.Width – 2*sizeObj).
Выразим это следующим способом
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState );
begin
if (Key=37) and not (sizeObj =coorXObj) then coorXObj:=coorXObj-sizeObj ;
if (Key=39) and not (coorXObj = (Form1.Width — 2*sizeObj)) then
coorXObj:=coorXObj+sizeObj ;
Form1.Repaint;
end;
16. Преобразуйте этот объект в три последовательных прямоугольника, и исправьте ограничения переменной coorXObj для этого случая.
17. Необходимо реализовать следующее
1. Перемещение шарика по окну программы через определенные промежутки времени.
2. Отражение шарика от стенок.
3. В случае попадания в нижнюю часть окна он должен либо отразиться от передвигаемой пользователем стенки либо упасть, и во втором случае работа программы должна завершаться.
18. Теперь создадим объект — шарик, который будет перемешаться самостоятельно. Для этого нам необходим специальный системный компонент таймер располагающийся на выкладке System
Добавим его в наш проект.
Для этого добавляем в проект обработчик события времени OnTimer
19. У самостоятельного объекта пусть будет две меняющиеся координаты, два коэффициента, для определения направления движения. Для этого создадим сначала класс, а потом переменную этого типа.
type TBall=class
X, Y, dx, dy:integer;
procedure SetDefault;
end;
procedure TBall. SetDefault;
begin
X:=sizeObj;
Y:=sizeObj;
dx:=1;
dy:=2;
end;
var
Ball:TBall;
Для того чтобы событие перемещения, не начинались сразу после создания формы, выключим таймер в его свойствах.
Для того чтобы запустить игру опишем в обработчике событий нажатия клавиши следующее действие:
If key = 116 then { код клавиши — F5}
StartNewGame;
где StartNewGame – процедура, которую мы добавим в класс TForm1.
И реализуем процедуру:
procedure TForm1.StartNewGame;
begin
Ball:= TBall. Create; {создаем экземпляр класса}
Ball. SetDefault;
Timer1.Enabled:=True; {запускаем таймер}
end;
20. Добавим в модуль реализации обработчика событий времени Timer1Timer алгоритм изменения координат нового объекта — Шарика.
Ball. X:= Ball. X+ Ball. dx;
Ball. Y:= Ball. Y+ Ball. dy;
И сразу же изменим интервал времени через который будет происходит запуск этой процедуры Поставим 100.
21. Для более удобного обозначения размеров рабочей области введем переменные и создадим функцию её вычисляющую.
Переменная будет особого типа record
Который опишем
Type TMinMax=record
min, max:integer;
End;
Type TField=record
X, Y: TMinMax;
End;
Var
WorkField: TField;
22. Добавим метод procedure CalculationWorkField; в класс TForm1;.
Его реализация будет:
procedure TForm1.CalculationWorkField;
begin
WorkField. X.min:=sizeObj;
WorkField. Y.min:=sizeObj;
WorkField. X.max:=Form1.Width-sizeObj;
WorkField. Y.max:=Form1.Height-sizeObj;
end;
23. Будем вызывать процедуру CalculationWorkField при каждом изменении размеров окна т. е. в процедуре FormResize.
24. Благодаря только что созданной процедуре есть возможность улучшить читабельность нашей программы в уже написанном коде. Если вспомните что у нас написано в процедуре FormKeyDown. Именно там мы использовали плохо читаемые прямые указания ограничений.
if (Key=37) and not (coorXObj= sizeObj) then coorXObj:=coorXObj-sizeObj ;
if (Key=39) and not (coorXObj = (Form1.Width — 4*sizeObj)) then
coorXObj:=coorXObj+sizeObj ;
Так что теперь напишем:
if (Key=37) and not (coorXObj = WorkField. X.min) then coorXObj:=coorXObj-sizeObj ;
if (Key=39) and not (coorXObj = (WorkField. X. max — 3*sizeObj)) then
coorXObj:=coorXObj+sizeObj ;
Дело в том, что мы храним координату самой левой точки объекта, поэтому вычитаем 3* sizeObj – теперь это стало хорошо видно ( с четверкой было не понятно).
Смотрим дальше в процедуре FormPaint мы тоже использовали прямые значения от края окна, поэтому перепишем:
старое |
По-новому |
Form1.Width/sizeObj |
WorkField. X.max/sizeObj |
Form1.Height/sizeObj |
WorkField. Y.max/sizeObj |
Вместо:
for i:=0 to Round(Form1.Height/sizeObj) do {create Right Windows}
Form1.canvas. Rectangle(Form1.Width, sizeObj*i,
Form1.Width — sizeObj, sizeObj*(i+1));
for i:=0 to 2 do
Form1.canvas. Rectangle(coorXObj+sizeObj*i, Form1.Height — sizeObj,
coorXObj+sizeObj*(i+1), Form1.Height);
Получилось:
for i:=0 to Round(WorkField. Y.max/sizeObj) do {create Right Windows}
Form1.canvas. Rectangle(WorkField. X.max, sizeObj*i,
WorkField. X.max+ sizeObj, sizeObj*(i+1));
for i:=0 to 2 do
Form1.canvas. Rectangle(coorXObj+sizeObj*i, WorkField. Y.max,
coorXObj+sizeObj*(i+1), WorkField. Y.max+ sizeObj);
25.Добавим возможность отражения от стенок шарика реализуем в процедуре Timer1Timer.
If (Ball. X= WorkField. X.min) or (Ball. X= WorkField. X.max — sizeObj) then
Ball. dx:= -1*Ball. dx;
Аналогично можно написать для координаты Y, но необходимо проверять наличие стенки перемещаемой пользователем, на пути движения шарика.
If (Ball. Y= WorkField. Y.min) then Ball. dy:= -1*Ball. dy; {отражение от верхней границы}
If (Ball. Y= WorkField. Y.max — sizeObj) then begin {с пользовательской стенкой}
if ((coorXObj<= Ball. X) and (coorXObj+3* sizeObj >= Ball. X)) then
Ball. dy:= -1*Ball. dy
Else begin
ShowMessage(‘Game over’);
Timer1.Enabled:=false; { останавливаем таймер}
GameIsStart:=false;
Ball. Free;{уничтожить шарик}
end;
end;
Дело в том, что мы храним координату самой левой точки объекта, поэтому от максимального вычитаем sizeObj
26. Теперь всю реализацию, связанную с шариком в процедуре Timer1Timer, спрячем в метод класса (TBall) function Move():Boolean; возвращающий значение по которому можно определить вышел ли наш шарик за приделы рабочей области или нет. Для удобства чтения создадим глобальную константу: BallInOutWorkField=true; {- шарик вышел за приделы}
function TBall. Move():Boolean;
begin
result:=not BallInOutWorkField;
X:= X+ dx;
Y:= Y+ dy;
If (X= WorkField. X.min) or (X= WorkField. X.max — sizeObj) then
dx:= -1*dx;
If (Y= WorkField. Y.min) then dy:= -1*dy;
If (Y= WorkField. Y.max — sizeObj) then begin {с пользовательской стенкой}
if ((coorXObj<= X) and
(coorXObj+3* sizeObj >= X)) then
dy:= -1*dy
Else result:=BallInOutWorkField;
end;
end;
27. Делаем соответствующие исправления в процедуре Timer1Timer.
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if Ball. Move()=BallInOutWorkField then begin
ShowMessage(‘Game over’);
Timer1.Enabled:=false; { останавливаемтаймер}
GameIsStart:=false;
Ball. Free;
end;
Form1.Repaint;
end;
28. Теперь необходимо рисовать объект –шарик. Создадим специальный метод Draw()
procedure TBall. Draw();
begin
Form1.canvas. Ellipse(X, Y, X+sizeObj, Y+sizeObj);
end;
Будем вызывать её в процедуре FormPaint.
Ball. Draw();
29. Запускаем и видим ошибку. Дело в том, что мы еще не запускали процедуру StartNewGame, а значит, у нас еще нет объекта Ball.. Нужно как то ограничить запуск строчки Ball. Draw(), поэтому создадим глобальную переменную (GameIsStart) несущую значение началась наша игра или нет.
Var GameIsStart: Boolean=false;
и в процедуре StartNewGame добавляем GameIsStart:=true; {игра началась}
Исправляем процедуре FormPaint
If GameIsStart then TBall. Draw();
30. При тестировании программы обнаруживаются недочеты. Это происходит, потому что левая координата шарика не находится в приделах нашей стенки и соответственно отражение не происходит. Поэтому для более корректного условия стоит выбрать проверять координату середины шарика:
if ((coorXObj<= X+sizeObj/2 ) and
(coorXObj+3* sizeObj >= X+sizeObj/2)) then …
31. В работе программы есть аномалия. При уменьшении размеров окна пользовательская стенка остается на своем месте и поэтому выходит за приделы рабочей области. Необходимо исправить эту ошибку.
32. Добавить возможность подсчета очков заработанных пользователем в зависимости от :
а. количества столкновений
б. места столкновения с вашей стенкой (средний или крайний квадраты)
в. размеров рабочей области.
и выведение этого значения во время игры.
33. Реализовать все функциональные возможности, указанные в индивидуальном задании на курсовую работу.