Рис. 8. Победа одного из игроков
Заметим, что в этом случае корабли невозможно перетащить, они показаны только для визуализации. Надпись начинает вновь мерцать, но в данном случае она ссылается на функцию меню «Новая игра».
Программа состоит из четырех модулей:
1. «TFlashingLabel.cpp», в котором содержится класс «TFlashingLabel», потомок класса «TLabel», носит вспомогательную роль для мерцания текста.
Содержит следующие переменные:
bool FFlashEnabled; //Включение мерцания
int FFlashRate; //Скорость мерцания
TTimer *Timer; //Таймер
Атакжеследующиефункции:
void SetFlashEnabled (bool AFlashEnabled);
Включение мерцания, параметр регулирует его включение
voidSetFlashRate (intAFlashRate);
Установление скорости; параметр содержит число, соответствующее скорости мерцания
void OnTimer (TObject *Sender);
Событиетаймера.
2. «AboutProgFrm.cpp», в нем содержится следующий класс «TAboutProg», а также форма, на которой расположена информация о программе.
Содержитфункцию:
void OKClick(TObject *Sender);
Предназначена для исключения из области видимости формы данного модуля.
3. «ResultsFrm.cpp» состоит из класса «TResultsForm» и формы для размещения текстовой информации в метках Label, загружаемой из файла.
Содержитследующиефункции:
void __fastcall OKClick(TObject *Sender);
Предназначена для исключения из области видимости формы данного модуля.
void LoadRes ();
Функция загружает данные из файла «SeaButResults.txt» и размещает их на форме.
4. «SeaButFrm.cpp» - главный модуль приложения, посредством которого осуществляются все основные функции игры. В том числе визуализация на форме данного модуля.
Содержит следующие переменные (все переменные в разделе private):
TDrawGrid **Ships1; //Корабли на 1-ом поле
TDrawGrid **Ships2; //Корабли на 2-ом поле
int **field1; //Массив 1-го поля
int **field2; //Массив 2-го поля
intlinex; //Координата x графической линии
intliney; //Координата y графической линии
ShootCpu; //Переменная для хранения информации стрельбы компьютера, является переменной типа Shoot, определенного следующей структурой:
struct Shoot //Структура для хранения данных выстрелов компьютера
{
int Choice; //Выбор
bool Target; //Попадание
bool TarDir; //Правильно ли выбрана горизонталь
bool TarDirect; //Правильно ли выбрано направление
bool TarDestr; //Корабльубит
int Direction; //Направление
int RowNum[100]; //Неопознанные точки поля
int RowDir[4]; //Неопознанные направления
};
intChoice; //Выбор при попадании компьютера
intShips1Destr[10]; //Подбитые корабли 1-го поля
intShips2Destr[10]; //Подбитые корабли 2-го поля
intCount1Destr; //Кол-во подбитых кораблей 1-го поля
intCount2Destr; //Кол-во подбитых кораблей 2-го поля
Graphics::TBitmap *Bitmap1; //Для хранения изображения канвы
Graphics::TBitmap *Bitmap2;
TFlashingLabel *FIGHT; //Динамическая мерцающая метка
А также содержит следующие функции:
1. Связанные с формой приложения и являющиеся методами компонентов
void __fastcall ExitClick(TObject *Sender);
Выходизприложения.
void __fastcall GridField1DragOver(TObject *Sender, TObject *Source, int X,
int Y, TDragState State, bool &Accept);
Перетаскиваниеобъектанадполем.
void __fastcall ShipsDragOver(TObject *Sender, TObject *Source, int X,
int Y, TDragState State, bool &Accept);
Функция для обеспечения возможности перетаскивания корабля.
void __fastcall ShipsMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y);
Необходима для поворота корабля на 90 градусов.
void __fastcall AboutClick(TObject *Sender);
Вызовокна «опрограмме».
void __fastcall CompClick(TObject *Sender);
Переход в режим игры с компьютером.
void __fastcall HumanClick(TObject *Sender);
Счеловеком.
void __fastcall FightClick(TObject *Sender);
Начатьбой.
void __fastcall NewGameClick(TObject *Sender);
Новаяигра.
void __fastcall Ready1Click(TObject *Sender);
Готовность 1-гоигрока.
void __fastcall Ready2Click(TObject *Sender);
Готовность 2-гоигрока.
void __fastcall GridField1MouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y);
Выстрел.
void __fastcall Timer1Timer(TObject *Sender);
Работа таймера 1, необходим для прорисовки линий и стрельбы компьютера.
void __fastcall Timer2Timer(TObject *Sender);
Работа таймера 1, необходим для замедления выстрелов компьютера.
void __fastcall Timer3Timer(TObject *Sender);
Работа таймера 1, необходим для показа победы игрока.
void __fastcall FormDestroy(TObject *Sender);
При уничтожении формы, очистка памяти.
void __fastcall FormPaint(TObject *Sender);
Прорисовка формы, в случае перекрывания другими окнами.
void __fastcall ResultsClick(TObject *Sender);
Показатьрезультаты.
void __fastcall FormDragOver(TObject *Sender, TObject *Source, int X, int Y,
TDragState State, bool &Accept);
Для запрета перемещения кораблей вне поля.
2. Созданные программистом (все в разделе private)
void SaveRes (int);
Сохранение результатов игры в файл, параметр определяет победителя.
void SaveBM (int);
Сохранение изображения поля, на которое был произведен выстрел. Параметр определяет это поле и соответствующий ему указатель на изображение.
void DelBM (int);
Удаление изображения, параметр вводится для соответствия указателю на изображение, необходимого для удаления.
void SetWindow (bool);
Установки свойств окна. При ложном значении параметра установить изначальные свойства окна, в обратном случае свойства, предотвращающие перекрывание изображений на форме.
void SeaDraw (int, int, int, bool);
Рисование на канве, номер которой указан первым параметром. Ее координаты указываются следующими двумя параметрами типа int, ложное значение последнего параметра указывает на промах игрока, правдивое – на попадание.
void NullCpu ();
ОбнулениеCpu.
void NewShips (int);
Создание объектов – кораблей, задание им необходимых свойств. Объекты располагаются на панели под номером, указанным параметром.
voidNewfield (int);
Создание динамического массива для поля боя игрока под номером, указанным параметром.
voidDelShips (int);
Удаление кораблей на панели под номером параметра типа int.
void Delfield (int);
Удаление массивов.
bool CheckShips (int);
Проверка правильной расстановки кораблей, проверяются корабли указанные параметром.
void CheckDestr ();
Проверка на непригодные клетки для стрельбы, функция предназначена для стрельбы компьютера, она отмечает неподходящие клетки специальной меткой, стрельба по ним производиться не будет.
void CreateShips ();
Случайная расстановка кораблей компьютером.
void CompShot ();
Выстрел компьютера. Выполняется алгоритм случайного выбора клетки на поле, при попадании по кораблю, случайным образом выбирается возможное направление пораженного корабля, стрельба производится до тех пор, пока корабль не будет убит. Запоминание информации о стрельбе производится с помощью переменной Cpu.
voidChangeCur (char *, int);
Смена курсоров производится в соответствии с указанным файлом в первом параметре. Курсор запоминается с помощью константы, имя которой указано во втором параметре.
В процессе создания программы возникали различные проблемы, как со сложностью реализации некоторых участков программы, так и с ошибками в программном коде.
Первые сложности возникли при создании функции автоматического расположения кораблей. Для проверки правильности необходимо было провести большое количество тестов с графическим изображением результатов, для этого стало необходимым создание временных переменных. Результаты были не сразу правильными. В начале положение кораблей стало заходить за рамки поля, для устранения проблемы понадобились новые переменные для хранения информации о границах. Затем корабли стали накладываться друг на друга, ошибка была в неправильной работе циклов, для отладки их работы использовалась печать в контрольных точках, слежение за значениями переменных. Дальнейшие тесты были удовлетворительными, по настоящий момент ошибки в этой функции не замечены.
Также возникла проблема при создании функции отслеживания клеток, в которые уже не нужно производить выстрелы компьютеру. На начальном этапе эта функция была рекурсивной, но многочисленные тесты показали, что компьютер продолжает производить выстрелы в эти клетки, а иногда даже программа зависала в результате зацикливания. В дальнейшем был придуман новый алгоритм, который стал более объемным, но зато он качественно и точно работает, что подтверждают тесты. Он проверяет поля не рекурсивно, а сразу для всех неубитых кораблей. Тестирование проводилось с помощью слежения за значениями переменных и их изменения в ходе работы программы.
Огромной проблемой стала отладка точной работы программы и ее интерфейса, так как при вызове одной из функций необходимо активировать и деактивировать, сделать видимыми и убрать из видимости другие компоненты и функции. Для примера, если во время выполнения выстрела, производилась попытка свернуть приложение или перекрыть его другим окном, то нарушалось изображение на полях боя. Для устранения пришлось изменять свойства окна, была создана специальная функция.
Для тестирования функций, вызываемых в концовке боя, использовалось изменение значений некоторых параметров для ускорения процесса.
В любом программном продукте есть свои достоинства и недостатки. Рассмотрим достоинства и недостатки «Логической игры «Морской бой»».
Достоинства:
· Удобный и простой интерфейс;
· Возможность соревноваться с предыдущими результатами игр;
· Минимальная загруженность оперативной памяти;
· Возможность игры с человеком, что редко встречается в компьютерных реализациях этой игры;
· Богатое графическое оформление игры.
Недостатки:
· Отсутствие справки к программе;
· Довольно примитивный интеллект компьютера;
· Отсутствие дополнительных функций игры, увеличивающих интерес к ней;
· Возможность испортить графику игры перекрыванием другими приложениями или меню Пуск.
Для развития логической игры «Морской бой» необходимо изучить пожелания пользователя данного программного продукта и в связи с этим внести необходимые изменения в данный продукт. На данном этапе необходимо улучшить дизайн, разработать более интересные варианты логики компьютера. Также можно добавить уровни сложности игры, возможность выбора размеров игрового поля и даже игру по сети.