Игра 'Марио'
Санкт-Петербургский
государственный
электротехнический
университет «ЛЭТИ» им. В.И. Ульянова (Ленина)
Кафедра МО
ЭВМ
ПОЯСНИТЕЛЬНАЯ
ЗАПИСКА
К КУРСОВОЙ
РАБОТЕ
«Игра
“Марио”»
по
дисциплине «Программирование»
Выполнил:
Малинин М.В.
Группа:
5304
Факультет:
КТИ
Преподаватель:
Голубков А.М.
Санкт-Петербург
Содержание
1. Цель работы
. Постановка задачи
. Анализ и выполнение задачи
.1 Общий анализ
.2 Алгоритм решения
.3 Отрисовка
. Тестирование
. Вывод
Приложение 1. Код программы
Приложение 2. Блок-схемы
1.
Цель работы
В ходе написания программы:
· освоить синтаксис языка
программирования С++;
· изучить и реализовать на практике
сложные алгоритмы;
· повторить знания о применении
различных типов данных;
· применить на практике знания,
полученные за семестр.
2. Постановка
задачи
Написать программу, в которой происходит
управление пользователем игровым персонажем (вид сбоку), с целью набрать
наибольшее число очков.
Программа включает в себя:
· генерацию персонажа, земли, деревьев
(заднего фона) и бонусных блоков;
· создание панели меню, для получения
информации о программе, сохранения результата и выхода из программы;
· возможность передвижения персонажем
по карте вперед, вверх, вниз и назад;
· визуализация предметов в игровом
поле.
. Анализ и выполнение задачи
.1 Общий анализ
Для создания проекта использовалась программа
Microsoft Visual C++ 2013. Проект создавался методом проб и ошибок, с
постоянными изменениями и улучшениями, как в плане производительности, так и в
плане удобства для пользователя. Исходя из того, что нет предела совершенству,
можно сказать, что программа не окончена и требует дополнений.
Программа состоит из файла исходного кода и двух
текстовых документов.
Программа имеет возможность считывать карту из
текстового документа и самостоятельно дополнять ее по мере прохождения. Конец
игры зависит только от желания игрока (пользователя) продолжать игру и в любой
момент имеет выход.
В игре существуют следующие объекты:
Таблица 1. Игровые объекты
Тип
объекта
|
Условное
обозначение в консоли
|
Персонаж
|
7
(цвет - серый)
|
Малое
дерево
|
2
(цвет - зелёный) 2 6 (цвет - коричневый)
|
Среднее
дерево
|
10
(цвет - светло-зелёный) 10 10 10 6 (цвет - коричневый)
|
Бонусный
блок
|
4
(цвет - красный)
|
Земля
|
1
(цвет - синий)
|
Воздух
|
0
(цвет - черный)
|
.2 Алгоритм решения
Объявляю два двумерных массива А(массив,
отвечающий за фон будущей карты) и В(массив, отвечающий за блоки, на которые
можно воздействовать). А так же перечисление, отвечающее за цвет объектов.
Точка входа программы находится в файле Mario_1.cpp.
В первую очередь, программа осуществляет вызов
текстового документа, с которого считывает значения и присваивает их каждому
элементу массива А. Массив В заполняется нулевыми значениями.
С помощью функций «void
LTree(int
j)», «void
MTree(int
j)» создаются
деревья для красоты программы с вероятностью 1:10 и 13:100 соответственно и
вводятся в массив А, при чем они создаются на «поверхности», то есть над первым
значением «1» в этом массиве в столбце j.
Учитывается вероятность того, что верхушки деревьев могут выходить за верх
карты, поэтому они обрезаются сверху.
Функция «void
Coins(int
j)» создает бонусные
блоки с вероятностью 6:100, которые «лежат» на «земле», или 1:10, которые
«зависают» над «землей» на высоте одного блока в массиве В в столбце j.
На этом первичная генерация карты окончена,
можно переходить к «основным действиям».
Создаю персонажа, который появляется в этом мире
на втором столбце, стоящий на земле.
Далее идет цикл типа do…while,
который определяет движение персонажа по нажатию игроком клавиш. При каждом
действии происходит отрисовка карты с помощью функции «void mass(int N, int
M)».
«W»
- прыжок. Персонаж подпрыгивает на один блок вверх и ждет следующей команды.
Есть возможность прыгнуть вверх, вперед и назад. Учитывается, что при прыжке
персонаж может подобрать бонусный блок. В таком случае, прибавляется одно очко.
«D»
- движение вперед. Происходит движение вперед, если после этого действия
персонаж находится не на земле, то он падает. Учитывается, что при движении
персонаж может подобрать бонусный блок. В таком случае, прибавляется одно очко.
Если персонаж подходит близко к краю карты (за 15 блоков до конца), то к ней
прибавляется новый столбец с помощью функции «int
main1(int
N, int
M)».
«A»
- движение назад. Происходит движение назад, если после этого действия персонаж
находится не на земле, то он падает. Учитывается, что при движении персонаж
может подобрать бонусный блок. В таком случае, прибавляется одно очко. Если
перед этим происходило создание нового столбца, то карта сдвигается назад.
В программе существует возможность обратиться к
Меню игры. На данный момент там можно сохранить свой результат в файл на ПК,
посмотреть информацию об игре, или выйти из нее. В будущем планируется создать
рейтинговую таблицу, в которой будет происходить сравнение предыдущих
результатов и выводить первые десять мест и имена чемпионов по количеству
очков.
«Q»
- вызов меню. Управление выбранным пунктом меню производится клавишами «W»
и «S». Для выбора
пункта необходимо нажать клавишу «D».
Сохранение производится автоматически при выборе пункта меню «Score».
«P»
- конец цикла. Происходит выход из основной части программы. После чего
происходит освобождение памяти массивов А и В и завершение программы.
.3 Отрисовка
Как уже было сказано, цвет был добавлен для
удобства игрока и зрелищности программы. Изменение цвета фона и шрифта
происходит с помощью функции «void SetColor(int text, int background)»
4.
Тестирование
В ходе бесчисленных запусков игры, проверки всех
условий, которые я мог придумать, и отладчика было выявлено:
- программа написана верно, явных
ошибок обнаружено не было;
- возможны утечки памяти в программе,
но ими можно пренебречь.
. Вывод
В ходе выполнения курсовой работы были освоены
навыки работы с файлами, двумерными и одномерными динамическими массивами,
функциями, строками и циклами. Отработаны собственные алгоритмы и методы
выполнения работы. Создана рабочая программа игрового формата, имеющая много
возможностей улучшения и оптимизации.
Приложение 1
язык программирование файл массив
Код программы
#include "stdafx.h"
#include
<conio.h>
#include
<iostream>
#include
<cstdlib>
#include
<fstream>
#include
<string>
#include
<Windows.h>namespace std; **A; // Массив
"заднего" фона
int **B; // Массив "переднего" фона
enum ConsoleColor
{= 0,= 1,= 2,= 3,=
4,= 5,= 6,= 7,= 8,= 9,= 10,= 11,= 12,= 13,= 14,= 15
};SetColor(int
text, int background)
{hStdOut =
GetStdHandle(STD_OUTPUT_HANDLE);(hStdOut, (WORD)((background << 4) |
text));
}menu(int c, int v,
int score)
{<<
"\t\t\t***MENU***\n";(c == 1){ SetColor(13, 0); }<<
"\tINFO\n"; SetColor(15, 0);
if (v == 1 && c == 1){
cout << "\tЭто информацияV1.1\n"; }// информация о программе(c
== 2){ SetColor(13, 0); }<< "\tStart\n"; SetColor(15, 0); //
переходит к разделу игры(v == 1 && c == 2){}(c == 3){ SetColor(13, 0);
} // выдает 10 лучших результатов
cout <<
"\tScore\n"; SetColor(15, 0);(v == 1 && c == 3){<<
"\tSaved\n";in("C://Users//Maskit//Desktop//php3.txt");<<
"Ваш счет:
" << score;.close();
} //Закрываем файл(c == 4){
SetColor(13, 0); } // выход из программы
cout <<
"\tEXIT"; SetColor(15, 0);(v == 1 && c == 4){exit(0);}
}LTree(int j){i,
r;= 1;= 1 + rand() % 100;(A[i][j] != 1)
{
++i;
}(r < 10){(i
> 1){ A[i - 1][j] = 6; }(i > 2){ A[i - 2][j] = 10; A[i - 2][j - 1] = 10;
A[i - 2][j + 1] = 10; }(i > 3){ A[i - 3][j] = 10; }
}
}MTree(int j){i,
r;= 1;= 1 + rand() % 100;(A[i][j] != 1)
{
++i;
}(r < 13){(i
> 1){ A[i - 1][j] = 6; }(i > 2){ A[i - 2][j] = 2; }(i > 3){ A[i -
3][j] = 2; }
}
}Coins(int j){i,
r;= 1;= 1 + rand() % 100;(A[i][j] != 1)
{
++i;
}(r < 6){if (i
> 1){ B[i - 1][j] = 4; }}(r >= 6 && r<14){ if (i > 2){ B[i
- 2][j] = 4; } }
}mass(int N, int
M){i, j;("cls");(i = 0; i < M-1; ++i){<< "\n\t";(j
= N - 46; j < N; ++j){(i<1 || j<N-45 || i>M-2 || j>N-2){
SetColor(0,2); cout<<"2 "; SetColor(15,0);}{(B[i][j] == 0){(0,
A[i][j]);<< A[i][j];(A[i][j] < 10)cout << " ";
}
{(0, B[i][j]); cout
<< B[i][j]; if (B[i][j] < 10) cout << " ";
}(15, 0);
}
}
}
}main1(int N, int
M)// создание нового столбца и заполнение
{i, e, r;= 0;= (0 +
rand() % 3);(A[e][N - 1] != 1)
{
++e;
}(e < M - 2
&& r == 0){ ++e; }(e > 2 && r == 1){ --e; }**temp = new
int*[M];(int i = 0; i < M; i++){[i] = new int[N];//Выделяю память
для временного массива
for (int j = 0; j
< N; j++ ){
temp[i][j] = A[i][j];
//Записываю туда данные
}
}[](*A); //вот так освобождаю
массив, принятый функцией
for (int i = 0; i
< M; i++){
A[i] = new int[N + 1];
//Выделяю для массива, принятой функцией новую память
}(int i = 0; i <
M; i++){(int j = 0; j < N; j++){
A[i][j] = temp[i][j];
//Записываю туда данные
}
}**temp2 = new
int*[M];(int i = 0; i < M; i++)
temp2[i] = new int[N];
//Выделяю новую память для временного массива
for (int i = 0; i
< M; i++){(int j = 0; j < N; j++){
}
}[](*B); //вот так освобождаю
массив, принятый функцией
for (int i = 0; i
< M; i++){
B[i] = new int[N + 1];
//Выделяю для массива, принятой функцией новую память
}(int i = 0; i <
M; i++){(int j = 0; j < N; j++){
B[i][j] = temp2[i][j];
//Записываю туда данные
}
}(i = 0; i < M;
i++)
{(e <= i){
A[i][N] = 1; }{ A[i][N] = 0; }[i][N] = 0;
}[]temp; //освобождаю память от
временного массива[]temp2; //освобождаю память от временного массива
MTree(N); LTree(N
- 1); Coins(N);
++N;N;
}main()
{i, j;a, b;=
*"";(LC_ALL, "Russian"); N = 0, M = 0; //Число колонок=N, Число строк= M
/*Чтение из файла текста*/
ifstream in("C://Users//Maskit//Desktop//php.txt");// получение файла с картой
int t;=
0;(!in.eof())
{(in, a); // Считываем строчку
в переменную а
b = b + ' ' + a;(N
< a.size()){ N = a.size(); }(i = 0; a[i] != *""; i++){ if (i >
a.size()){ break; } }
++M;
}.close(); //Закрываем файл
/*Создание динамического
двумерного массива*/
//A = new int*[M];=
(int**)malloc(sizeof(int*) * M);= (int**)malloc(sizeof(int*) * M);(i = 0; i
<= M; i++)
{
// A[i] = new
int[N];[i] = (int*)malloc(sizeof(int) * N);[i] = (int*)malloc(sizeof(int) *
N);(j = 0; j <= N; j++)
{= b.substr(t + 2,
1);
++t;[i][j] =
atoi(a.c_str());[i][j] = 0;(a == " "){(j < N)
{[i][j] = 0;[i][j]
= 0;++;
}
}(t == b.size() -
2){ break; }
}(t == b.size() -
2){ break; }// зарисовка предметов
}<<
"\n\n";(j = 1; j < N - 1; ++j){ LTree(j); MTree(j); Coins(j); }= M
- 2;= 2;(A[i][j] == 1)
{= i - 1;
}[i][j] = 7;// создание персонажа
char vvod;K = N, c
= 0, score = 0, v = 0;{= _getche();(vvod == 'w' && i > 0 &&
A[i - 1][j] != 1){ if (B[i - 1][j] == 4){ ++score; }B[i][j] = 0; --i; B[i][j] =
7; mass(N, M); vvod = _getche(); }(vvod == 'a' && j > 0 &&
A[i][j - 1] != 1){ if (B[i][j - 1] == 4){ ++score; }B[i][j] = 0; --j; B[i][j] =
7; if (N > 45){ --N; } mass(N, M); }(vvod == 'd' && j <
N - 2 && A[i][j + 1] != 1){ if (j >= K - 15){/**/ if (N < K){
++N; } else { K = main1(K, M); ++N;/**/ } } if (B[i][j + 1] == 4){ ++score;
}B[i][j] = 0; ++j; B[i][j] = 7; mass(N, M); }(A[i + 1][j] !=
1){ if (B[i + 1][j] == 4){ score++; }if (B[i + 1][j] == 4){ ++score; } B[i][j]
= 0; ++i; B[i][j] = 7; mass(N, M); }(vvod == 'q'){// Меню=
1;
{("cls");(c,
v, score);= _getche();(vvod == 'w'){ if (c > 1) { --c; } }(vvod == 'a'){ v =
0; }(vvod == 's'){ if (c < 5){ ++c; } }(vvod == 'd'){ v = 1; }
//if (c == 1){}
} while (vvod !=
'q');
}
} while (vvod != 'p');
/*Очистка памяти от созданного
двумерного массива*/
for (int i = 0; i
< N; i++) { delete[]A[i]; delete[]B[i]; }[]A; delete[]B;= NULL; B = NULL;
system("pause");
}
Приложение 2
Блок-схемы