Игра "Lines"

 

1. Анализ задания и постановка задачи


В нашем случае предметной областью является мини-игра «LINES». Игра существует уже давно, поэтому ничего нового изобретать нам не придётся, нужно лишь реализовать приложение.

Правила игры предельно просты. Имеется игровое поле - 9х9 ячеек в которых лежат шарики. Необходимо переставлять шарики одного цвета в линии из 5 и более по горизонтали или вертикали. В начале шариков мало, но в течение игры их количество увеличивается.

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

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

Шар не всегда может попасть туда куда вы бы его хотели поставить. После каждого перемещения появляются ещё три шара.

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

Чтобы не загромождать игровое поле, очков и игрового времени вынесен на специальную строку состояния, которая будет располагаться за пределами игрового поля, вверху окна.

Следовательно, можно сделать вывод, что в нашей программе мы будем реализовывать:

1.Игровое поле 9*9 со случайной генерацией чисел.

.Перемещение шаров по полю.

.Уничтожение шаров.

.Анимация.

.Звуковое сопровождение.

.Подсчет игрового времени.

.Запись текущего состояния в файл.

.Загрузка сохраненной игры из файла.


2. Теоретическая часть


В данной части пояснительной записки хочется рассказать о стандартных процедурах и функциях, которые использовались в моей программе.

) MyRegisterClass - функция регистрации класса окна. Является одной из основных функций. В ней мы задаём стили, иконки, стиль курсора, цвет фона и многое другое… В нашей программе полностью оформленная эта функция выглядит так:

MyRegisterClass (HINSTANCE hInstance)

{wcex;.cbSize = sizeof(WNDCLASSEX);.style= CS_HREDRAW | CS_VREDRAW;.lpfnWndProc= (WNDPROC) WndProc;.cbClsExtra= 0;.cbWndExtra= 0;.hInstance= hInstance;.hIcon= LoadIcon (hInstance, (LPCTSTR) IDI_mymenu);.hCursor= LoadCursor (NULL, IDC_ARROW);.hbrBackground= (HBRUSH) (COLOR_WINDOW+1);.lpszMenuName= (LPCSTR) IDC_mymenu;.lpszClassName= szWindowClass;.hIconSm= LoadIcon (wcex.hInstance, (LPCTSTR) IDI_SMALL);RegisterClassEx(&wcex);

}


) CreateWindow - функция создания окна. В ней мы указываем заголовок окна, его стили, размеры и др. Без использования этой функции наша программа в принципе невозможна. В нашем проекте эта функция выглядит следующим образом:

= CreateWindow (szWindowClass, szTitle, WS_CAPTION | WS_POPUPWINDOW | WS_OVERLAPPED, 512, 240, 305, 368, NULL, NULL, hInstance, NULL);


где hWnd - указатель на дескриптор создаваемого нами окна.

Ещё некоторые функции окна:- функция, которая в зависимости от переданых ей параметров либо показывает, либо скрывает окно.- функция обновления окна.

) PlaySound (MY_SOUND1, NULL, SND_FILENAME | SND_ASYNC) - функция для воспроизведения звуковых файлов в формате WAVE.

Первый параметр функции задает либо имя файла на диске, либо строку имени звукового ресурса. Если при вызове PlaySound первый параметр равен NULL, это вызывает прекращение воспроизведения любого «играемого» файла. Второй параметр используется только при воспроизведении звука из звукового ресурса. Если же функция вызвана для воспроизведения звука из файла, то второй параметр устанавливается в NULL. Третий параметр управляет загрузкой и воспроизведением звука.

) SetTimer - функция присоединения стандартного таймера Windows. Первый параметр, hWnd, содержит дескриптор окна, ассоциированного с данным таймером. Второй параметр, nIDEvent, позволяет указывать идентификатор таймера, которым может быть произвольное целое число (но не нуль). Третий параметр, uElapse, задает интервал, который может находиться в пределах (теоретически) от 1 до 4 294 967 295 мс, что составляет около 50 дней. Это значение определяет темп, с которым Windows будет посылать программе сообщения WM_TIMER. Сообщения WM_TIMER направляются либо оконной процедуре для окна hWnd, если параметр IpTimeProc равен NULL, либо функции обратного вызова с адресом IpTimeProc - в противном случае.

) ImageList_Add - функция добавления изображений в список. Первый аргумент этой функции: хэндл списка изображений. Второй аргумент представляет собой хэндл добавляемого в список изображения. Третий аргумент - хэндл монохромного bitmapa, который содержит маски._Draw - функция прорисовки изображения хранящегося в списке. Первый аргумент хэндл списка изображений, второй - индекс изображения, третий - хэндл контекста, на которых будет копироваться изображение, четвёртый и пятый - координаты в этом контексте, начиная с которых будет скопировано изображение, и, наконец, шестой - именно флаги прорисовки.

) GetObject - функция получающая размеры изображения. Первый параметр дескриптор графического объекта. Второй параметр размер буфера для информации об объекте. Третий параметр адрес буфера для информации об объекте. Функция является универсальной, поэтому в параметре hgdiobj может быть указан дескриптор одного из таких объектов, как перо, кисть, шрифт, палитра или растр типа Н BITMAP.

) BitBlt - Функция BitBlt передает прямоугольный блок пикселов с поверхности устройства-источника hdcSrc на поверхность устройства-приемника hdcDest. Исходный прямоугольник определяется параметрами nXSrc, nYSrc, nWidth, nHeight в логической системе координат контекста устройства-источника. Приемный прямоугольник определяется параметрами nXDest, nYDest, nWidth, nHeight в логической системе координат контекста устройства-приемника. Оба контекста устройства должны поддерживать растровые операции RC_BITBLT.

) DestroyWindow - функция разрушения окна. Вызывается нами единствееный раз при активации пункта меню «Выход». Полностю разрушает окно, дескриптор которг передан ей в параметре.

) rand() - функция для рандомного (случайного) заполнения. В нашем проекте используется для случайного заполнения поля фишками. Для того, чтобы это заполнение было каждый раз новое, нужно использовать следующую конструкцию:((unsigned) time(NULL));

) DrawImage - функция рисования изображения. Используется для рисования наших игровых фишек.

):CreateFile - используется для создания и / или открытия файла. Файл нам необходим для хранение таблицы рекордов.

:ReadFile - функция чтения файла.


3. Проектирование программы


.1 Пользовательские функции


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

При проектировании игры использовались следующие функции: void Paint (HDC hdc, HDC hdcMem);

Функция вывода на экран всей графики. POINT * len (int StartX, int StartY, int &length);

Функция подсчёта шаров в одной линии. Осуществляет поиск ряда по вертикали и горизонтали от текущей позиции, задаваемой параметрами StartX и StartY. Результат возвращается в переменную length. void EndPathfinder (void);

Функция очистки динамического массива, содержащего координаты точек проходимого пути для шарика. int FindPath (int startX, int startY, int targetX, int targetY).

Функция поиска пути по алгоритму A-star. В начале работы просматриваются узлы, смежные с начальной; выбирается тот из них, который имеет минимальное значение f(x), после чего этот узел раскрывается. На каждом этапе алгоритм оперирует с множеством путей из начальной точки до всех ещё не раскрытых (листовых) вершин графа («множеством частных решений»), которое размещается в очереди с приоритетом. Приоритет пути определяется по значению f(x) = g(x) + h(x). Алгоритм продолжает свою работу до тех пор, пока значение f(x) целевой вершины не окажется меньшим, чем любое значение в очереди (либо пока всё дерево не будет просмотрено). Из множественных решений выбирается решение с наименьшей стоимостью.dest_len (POINT * PatchDestroy);

Функция очистки массива из координат точек шаров расположенных в одной линии.create_bubbles (HWND hWnd);

Функция добавления шариков в массив. Осуществляет случайное заполненение поля шариками, также осужествляет проверку на завершение игры (игра завершается когда заполняется всё поле). На каждом ходе функция добавляет три шарика, в случае попадания шарика в занятую ячейку осуществляется поиск свободной.


3.2 Хранение данных


Данные хранятся в статическом массиве типа int размером 9х9. Младшее слово используется для хранения номера шарика, а старший для хранения текущего состояния (используется для анимации активации, уничтожения, и появления шарика).

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


3.3 Воспроизведение анимации


Для воспроизведения анимации используется стандартный таймер Windows, который через заданный промежуток времени посылает сообщение WM_TIMER и через этот промежуток времени осуществляется загрузка другого bitmap'а из Image_List и так повторятся циклически. В моём случае период срабатывания таймера равен 100ms.


3.4 Подсчёт проведённого в игре времени


Для подсчёта времени используется функция GetTickCount(), которая возвращается количество миллисекунд с момента запуска системы. Для расчёта времени работы при создании окна записывается в переменную T1 время запуска программы. Проведённое время в игре рассчитывается как T1-T2, где T2 текущее количество миллисекунд с момента запуска системы.


3.5 Начисление очков


Начисление очков производится за каждый уничтоженный шарик по единице.


Полный листинг всех процедур и функций представлен в приложении «Листинг программы».


4. Реализация программы


4.1 Реализация главного окна игры


Рис. 1. «Главное окно программы»


4.2 Реализация перемещения шариков


Совершим произвольное количество ходов и увидим, что все шарики перемещаются совершенно правильно.


Рис. 2. «Реализация перемещения шаров»

4.3 Реализация новой игры


На вкладке меню «Игра» выберем пункт «Новая игра» и увидим следующее сообщение:


Рис. 3 «Новая игра»


4.4 Составление шаров в линию


Рис. 4. Реализация уничтожения шаров

4.5 Реализация сохранения и загрузки игры





Рис. 5. Сохранение и загрузка


4.6 Реализация меню «О программе»


Рис. 6 «Меню - «О программе»»


5. Методика и результаты тестирования

lines шарик игра программа

Тест 1. Корректный и стабильный запуск программы

При каждом запуске приложение готово выполнять поставленную задачу. Никаких ошибок не происходит. Тест пройден.

Тест 2. Перемещение шарика

При клике на шарик с последующим кликом на свободную клетку шарик перемещается при наличии свободного пути. Тест пройден.

Тест 3. Попытка переместить шарик в закрытую область

При попытке переместить шарик через непроходимую область ничего не происходит. Тест пройден.

Тест 4. Новая игра

После запуска новой игры поле обновилось таймер и очки аннулированы, можно начинать играть. Тест пройден.

Тест 5. Выход

После выбора в меню выхода или по нажатию на крестик игра закрывается. Тест пройден.

Тест 6. Сохранение с последующей загрузкой

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

Тест 6. Составление в ряд шаров

После составления в ряд по вертикали или горизонтали пяти и более шаров одного цвета происходит их уничтожение с последующим увеличением очков.

Можно сделать вывод, что программа прошла тестирование. Ее использование не вызвало проблем, все действия она выполняла стабильно и верно.


Заключение


В рамках данной курсовой работы была решена поставленная задача. Задача представляет собой windows-приложение, эмулирующее игру «Lines». Приложение имеет интуитивно-понятный интерфейс. В ходе тестирования приложение показало себя стабильным и устойчивым к некорректным действиям пользователя.

Для разработки приложения использовался язык высокого уровня C++. Средой разработки была выбрана среда Microsoft Visual Studio 2008.


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


1.Win32 API Щупак

2.Win32API Основы программирования

.Саймон Р. Windows 2000 API.1085 стр.


Приложение


Файл h

#pragma once

#include «resource.h»

#define FILE_PATH _T («data.dat»)hBitmapNum0=(HBITMAP) LoadImage (NULL, _T («data //BKG.BMP»), IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);hBitmapNum1=(HBITMAP) LoadImage (NULL, _T («data //BALLS1.BMP»), IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);hBitmapNum2=(HBITMAP) LoadImage (NULL, _T («data //BALLS2.BMP»), IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);hBitmapNum3=(HBITMAP) LoadImage (NULL, _T («data //BALLS3.BMP»), IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);hBitmapNum4=(HBITMAP) LoadImage (NULL, _T («data //BALLS4.BMP»), IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);hBitmapNum5=(HBITMAP) LoadImage (NULL, _T («data //BALLS5.BMP»), IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);hBitmapNum6=(HBITMAP) LoadImage (NULL, _T («data //BALLS6.BMP»), IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);hBitmapNum7=(HBITMAP) LoadImage (NULL, _T («data //BALLS7.BMP»), IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);hBitmapNum8=(HBITMAP) LoadImage (NULL, _T («data //TIME.BMP»), IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);hBitmapNum9=(HBITMAP) LoadImage (NULL, _T («data //NEXT.BMP»), IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);hBitmapNum10=(HBITMAP) LoadImage (NULL, _T («data //DIGITS.BMP»), IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);hBitmapNum11=(HBITMAP) LoadImage (NULL, _T («data //DIGTR.BMP»), IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);hBitmapNum12=(HBITMAP) LoadImage (NULL, _T («data //TIMTR.BMP»), IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);hBitmapNum13=(HBITMAP) LoadImage (NULL, _T («data //NEXTTR.BMP»), IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);

TCHAR MY_SOUND0 []=_T («data //move.wav»);

TCHAR MY_SOUND1 []=_T («data //destroy.wav»);MY_SOUND2 []=_T («data //fetus.wav»);MY_SOUND3 []=_T («data //cantmove.wav»);struct

{hour, min, sec;

} TIME;int walkability_fetus=1376256;int zero=0x0000ffff;int mapWidth = 9, mapHeight = 9;onClosedList = 10;int notfinished = 0, notStarted = 0;int found = 1, nonexistent = 2;int walkable = 0;walkability [mapWidth] [mapHeight];openList [mapWidth*mapHeight+2];whichList [mapWidth+1] [mapHeight+1];openX [mapWidth*mapHeight+2];openY [mapWidth*mapHeight+2];parentX [mapWidth+1] [mapHeight+1];parentY [mapWidth+1] [mapHeight+1];Fcost [mapWidth+1] [mapHeight+1];pathLength;*pathBank;int path=0;xPath;yPath;

// -

// Реализация алгоритма A*(A-star)

// -FindPath (int startX, int startY, int targetX, int targetY)

{onOpenList=0, parentXval=0, parentYval=0,=0, b=0, m=0, u=0, v=0, temp=0, numberOfOpenListItems=0,= 0, x=0, y=0,, pathX, pathY, cellPosition,=0;

if (startX == targetX && startY == targetY)

return found;= 1;[1] = 1;[1] = startX;[1] = startY;

{(numberOfOpenListItems!= 0)

{[parentXval] [parentYval] = onClosedList;-;[1] = openList [numberOfOpenListItems+1];= 1;

{(2*u+1 <= numberOfOpenListItems)

{(Fcost [openX[openList[u]]] [openY [openList[u]]]>=[openX[openList [2*u]]] [openY [openList[2*u]]])= 2*u;

if (Fcost [openX[openList[v]]] [openY [openList[v]]]>=

Fcost [openX[openList [2*u+1]]] [openY [openList[2*u+1]]])

if (2*u <= numberOfOpenListItems)(u!= v)

{= openList[u];[u] = openList[v];[v] = temp

};

}

for (a = parentXval-1; a <= parentXval+1; a++) {

for (b = parentYval-1+abs (parentXval-a); b <= parentYval+1-abs (parentXval-a); b++) {(a!= -1 && b!= -1 && a!= mapWidth && b!= mapHeight) {

if (whichList[a] [b]!= onClosedList) {(walkability [a] [b] == walkable || HIWORD (walkability [a] [b])==HIWORD (walkability_fetus)) {(whichList[a] [b]!= onOpenList)

{++;= numberOfOpenListItems+1;[m] = newOpenListItemID;[newOpenListItemID] = a;[newOpenListItemID] = b;

Fcost[a] [b] = 10*(abs (a - targetX) + abs (b - targetY));

parentX[a] [b] = parentXval;

parentY[a] [b] = parentYval;(m!= 1)

{(Fcost [openX[openList[m]]] [openY [openList[m]]] <=[openX[openList [m/2]]] [openY [openList[m/2]]])

{= openList [m/2];[m/2] = openList[m];[m] = temp;= m/2;

};

}++;[a] [b] = onOpenList;

}

{(Fcost[parentXval] [parentYval] < Fcost[a] [b])

{[a] [b] = parentXval;[a] [b] = parentYval;(int x = 1; x <= numberOfOpenListItems; x++)

{(openX [openList[x]] == a && openY [openList[x]] == b)

{= x;(m!= 1)

{(Fcost [openX[openList[m]]] [openY [openList[m]]] <[openX[openList [m/2]]] [openY [openList[m/2]]])

{= openList [m/2];[m/2] = openList[m];[m] = temp;= m/2;

};

};

}

{= nonexistent; break;

}(whichList[targetX] [targetY] == onOpenList)

{= found; break;

}

}(1);(path == found)

{= targetX; pathY = targetY;

{= parentX[pathX] [pathY];= parentY[pathX] [pathY];= tempx;= pathLength + 1;

}(pathX!= startX || pathY!= startY);

pathBank = (POINT*) realloc (pathBank,= targetX; pathY = targetY;

cellPosition = pathLength;

{-;[cellPosition].x = pathX;[cellPosition].y = pathY;= parentX[pathX] [pathY];= parentY[pathX] [pathY];= tempx;(pathX!= startX || pathY!= startY);

}path;:= startX;= startY;nonexistent;

}EndPathfinder (void)

{(pathBank)

{(pathBank);=NULL;

}

}

POINT * len (int StartX, int StartY, int &length)

{north=1, south=1, west=1, east=1, width=0, height=0;*PatchDestroy=NULL;=0;++;

while (StartY+south!=mapHeight && walkability[StartX] [StartY]==walkability[StartX] [StartY+south])

south++;

while (StartX-west!=-1 && walkability[StartX] [StartY]==walkability [StartX-west] [StartY])

west++;

while (StartX+east!=mapWidth && walkability[StartX] [StartY]==walkability [StartX+east] [StartY])

east++;=north+south-1;=west+east-1;

if (height>=5 && width>=5 && height>=width || height>=5)

{=height;=(POINT*) malloc (sizeof(POINT)*height);=north-1;(int i=0; i<height; i++)

{[i].x=StartX;[i].y=StartY+i;

}

}(width>=5)

{=width;=(POINT*) malloc (sizeof(POINT)*width);=west-1;(int i=0; i<width; i++)

{[i].x=StartX+i;[i].y=StartY;

}

}PatchDestroy;

}

void dest_len (POINT * PatchDestroy)

{(PatchDestroy)

{(PatchDestroy);=NULL;

}

}



1. Анализ задания и постановка задачи В нашем случае предметной областью является мини-игра «LINES». Игра существует уже давно, поэтому ничего

Больше работ по теме:

КОНТАКТНЫЙ EMAIL: [email protected]

Скачать реферат © 2017 | Пользовательское соглашение

Скачать      Реферат

ПРОФЕССИОНАЛЬНАЯ ПОМОЩЬ СТУДЕНТАМ