KillFont() – освобождение ресурсов занимаемых bitmap шрифтом.
glPrint(const char *fmt, ...) – Метод вывода текстовой надписи.
CreateGLWindow(WNDPROC, LPCWSTR, int) – метод создания окна windows приложения.
KillGLWindow() – метод корректного разрушения окна приложения.
3.3. Класс Statistic – сбор и хранение данных о играх.
Класс Statistic содержит список структур - записей о прошедших играх. Внешний вид статистики изображен на рисунке 4.
В запись входят: Дата игры, параметры поля и количество мин, время, затраченное на игру и результат игры – выигрыш/проигрыш.
Единица записи представлена следующей структурой:
struct StatRec
{
// Дата и время записи
char recDate[80];
// Параметры поля
int Width, Height, BombCount;
// Затраченное время на игру
long gameTime;
// Тип завершения игры: выигрыш, проигрыш
bool WinGame;
};
Statistic содержит следующие методы:
AddRecord(StatRec) – добавление новой записи о завершенной игре к общему списку записей.
Clear() – уничтожение всех записей статистики.
SaveStat() – сохранение в файл данных о завершенных играх.
LoadStat() – загрузка данных из файла.
Refresh() – обновление статистических данных о играх.
ToString() – сбор статистики в строку.
GetRecords()– получить доступ к списку записей.

Рисунок 4 – Внешний вид окна статистики
3.4. Класс Game – контроль процесса игры
Класс Game обеспечивает игровой процесс: настройка и запуск, а также остановка игры, запуск и остановка игрового таймера. Класс Game содержит в качестве полей указатели на объекты модели, отображения и статистики.
Game содержит следующие методы:
InitGame(int, int) – инициализация игры: создание модели заданного размера, присоединение модели к объекту отображения.
GameStart() – запуск игры: запускается игровой таймер, маркер отвечающий за запуск игры выставляется в true.
EndGame() – остановка игры: останавливается игровой таймер, маркер запуска игры выставляется в false, отсоединяется модель от объекта отображения.
IsStart() – метод проверки запущена игра или нет.
GameProcess(x, y) – проверка ячейки с заданными координатами. Возвращаемое значение – процесс игры: "Игра окончена, победил компьютер", "Игра окончена, победил игрок", "Игра продолжается".
TimerStart() – запуск игрового таймера.
TimerStop() – остановка игрового таймера.
UpdateTimer() – обновить отображение текущего времени игры используя объект отображения класса View.
GetModel() – получить доступ к объекту модели.
GetView() – получить доступ к объекту отображения.
SetView(View*) – задать объект отображения.
GetStat() – доступ к объекту статистики.
Внешний вид игрового меню можно наблюдать на рис.5, рис. 6. Изображение игрового поля рис. 7, рис. 8.

Рисунок 5 – Внешний вид игрового меню

Рисунок 6 – Выбор размеров игрового поля
Рисунок 7 – Построение игрового поля
Рисунок 8 – Игровой процесс
Заключение
В ходе курсовой работы были разобраны принципы, по которым работает компьютерная игра «Сапер» от компании Microsoft. Они были использованы для написания собственной игры. При программировании использовалась библиотека OpenGL, языком создания программы был С++.
Логика игры «Сапер» была в большей части воспроизведена в курсовой работе, за исключением элементов, дополняющие геймплей игры. Воссозданная игра может быть использоваться наравне с оригинальной версией.
Библиографический список
1. Т. Кормен, Ч. Лейзер – Алгоритмы. Построение и анализ / http://www. /books/thalg/kormen_leiser_algorith. html
2. Начальный курс OpenGl. М., В. / http://www. /file/308896/
3. Технология программирования на C++. Win32 API-приложения.
Н. А. Литвиненко, Издательство: БХВ-Петербург / http:///2011/05/15/tehnologiya-programmirovaniya-na-c-win32-api-prilozheniya. html
Приложение А
=============================Модель========================
#pragma once
#include "Model. h"
// Конструктор
Model::Model() {}
// Конструктор с параметрами
Model::Model(int width = 10, int height = 10)
{
timer = 0;
// Задаем размер поля
Width = width;
Height = height;
// Генерируем некоторое количество бомб
BombCount = (int)sqrt(width * height);
BombCount += rand() % BombCount;
// Флагов пока нет
FlagCount = 0;
// Создаем поле в виде вектора
field = new Cell[width * height];
// Расставляем мины
SetMines();
domainMatrix = new int*[height];
for(int i = 0; i < height; i++)
domainMatrix[i] = new int[width];
for(int y = 0; y < height; y++)
{
for(int x = 0; x < width; x++)
{
int minesAround = 0;
for (int yy = y - 1; yy <= y + 1; ++yy)
{
for (int xx = x - 1; xx <= x + 1; ++xx)
{
if ((xx == x && yy == y) ||
xx < 0 || xx >= width ||
yy < 0 || yy >= height)
continue;
if (GetCell(xx, yy).hasMine)
++minesAround;
}
}
if(GetCell(x, y).state == CellState::CLOSED &&
GetCell(x, y).hasMine == false &&
minesAround == 0)
{
domainMatrix[y][x] = 1;
}
else
{
domainMatrix[y][x] = 0;
}
}
}
for(int y = 0; y < height; y++)
{
for(int x = 0; x < width; x++)
{
if(domainMatrix[y][x] == 1)
{
if(x + 1 < width)
{
// Справа прямо
if(domainMatrix[y][x + 1] != 1 && domainMatrix[y][x + 1] == 0)
domainMatrix[y][x + 1] = 2;
// Справа сверху
if(y + 1 < height)
if(domainMatrix[y + 1][x + 1] != 1 && domainMatrix[y + 1][x + 1] == 0)
domainMatrix[y + 1][x + 1] = 2;
// Справа снизу
if(y - 1 >= 0)
if(domainMatrix[y - 1][x + 1] != 1 && domainMatrix[y - 1][x + 1] == 0)
domainMatrix[y - 1][x + 1] = 2;
}
if(x - 1 >= 0)
{
// Слева прямо
if(domainMatrix[y][x - 1] != 1 && domainMatrix[y][x - 1] == 0)
domainMatrix[y][x - 1] = 2;
// Слева сверху
if(y + 1 < height)
if(domainMatrix[y + 1][x - 1] != 1 && domainMatrix[y + 1][x - 1] == 0)
domainMatrix[y + 1][x - 1] = 2;
// Слева снизу
if(y - 1 >= 0)
if(domainMatrix[y - 1][x - 1] != 1 && domainMatrix[y - 1][x - 1] == 0)
domainMatrix[y - 1][x - 1] = 2;
}
if(y + 1 < height)
if(domainMatrix[y + 1][x] != 1 && domainMatrix[y + 1][x] == 0)
domainMatrix[y + 1][x] = 2;
if(y - 1 >= 0)
if(domainMatrix[y - 1][x] != 1 && domainMatrix[y - 1][x] == 0)
domainMatrix[y - 1][x] = 2;
}
}
}
// Получаем домены
for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
{
// Нашли стартовую точку домена
if(domainMatrix[i][j] == 1)
{
// Создаем новый домен
Domain d(pair<int, int>(i, j), height, width);
// Получаем все координаты домена
domainMatrix = d. add_neighbors(domainMatrix, height, width);
// Добавляем в список доменов
domains. push_back(d);
}
}
}
}
// Копирования конструктор
Model::Model(const Model &href)
{
timer = href. timer;
field = new Cell[href. Width * href. Height];
Width = href. Width;
Height = href. Height;
BombCount = href. BombCount;
FlagCount = href. FlagCount;
// Копируем параметры ячеек
for (int x = 0; x < Width; x++)
for (int y = 0; y < Height; y++)
{
// Копируем наличие бомбы
field[y * Width + x].hasMine = href. field[y * Width + x].hasMine;
// Копируем состояние ячейки
field[y * Width + x].state = href. field[y * Width + x].state;
}
// Копируем список доменов
domains. assign(href. domains. begin(), href. domains. end());
}
// Деструктор
Model::~Model()
{
delete []field;
for(int i = 0; i < Height; i++)
delete []domainMatrix[i];
delete []domainMatrix;
}
// Расстановка мин
void Model::SetMines()
{
srand((unsigned)time(NULL));
// Заполняем параметры ячеек на поле
for (int y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
{
// Изначально ячейка закрыта
field[y * Width + x].state = CellState::CLOSED;
// Бомб нет
field[y * Width + x].hasMine = false;
}
// Расставляем мины
int count = 0;
while(count < BombCount)
{
// Координаты мины
int x, y;
do
{
// Генерируем х координату на поле
x = rand() % Width;
// Генерируем y координату
y = rand() % Height;
}
// Повторяем пока по текущим координатам попадаем на занятое поле
while (GetCell(x, y).hasMine);
// Выставляем мину в ячейку
GetCell(x, y).hasMine = true;
count++;
}
}
// Изменение ячейки
void Model::SetCell(int x, int y, CellState state)
{
// Меняем свойство яйечки
field[y * Width + x].state = state;
}
// Получить доступ к ячейке по индексу
Cell &Model::GetCell(int x, int y)
{
return field[y * Width + x];
}
// Открыть ячейку
void Model::Open(int x, int y)
{
// Если ячейка помечена флагом или открыта - выходим
if(GetCell(x, y).state!= CellState::CLOSED)
return;
int domainID = -1;
// Проверяем попадает ли точка в какой либо домен свободных клеток
for(size_t i = 0; i < domains. size() && domainID == -1; i++)
{
// Проверяем точки домена
for(size_t j = 0; j < domains. at(i).points. size() && domainID == -1; j++)
// Если найдено вхождение
if(domains. at(i).points. at(j).first == y && domains. at(i).points. at(j).second == x)
// Запоминаем индекс домена
domainID = i;
}
// Если точка входит в какой либо домен
if(domainID!= -1)
{
// Открываем все клетки из этого домена
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 |
Основные порталы (построено редакторами)



