На прикладі консольної гри розглянемо, як можна розділити програму на кілька файлів, а також використаємо наші нові знання про константи, функції та масиви.
Визначення для гри
Перш за все, у грі ми будемо використовувати набір констант, для яких варто створити окремий заголовний файл.
// Файл game-defs.h
#ifndef GAME_DEFS_H
#define GAME_DEFS_H
const int mazeColumns = 20;
const int mazeRows = 20;
const char emptySymbol = ' ';
const char wallSymbol = 'X';
const char characterSymbol = '@';
const char exitSymbol = '#';
const char keySymbol = '&';
const char scoreSymbol1 = '1';
const char scoreSymbol2 = '2';
const char scoreSymbol3 = '3';
#endif //GAME_DEFS_H
- Для розміру ігрового поля та значень клітинок ігрового поля ми використали окремі константи. Це дасть нам змогу змінити будь-яке з цих значень у будь-який момент. Більше того, це необхідно буде зробити лише у цьому заголовному файлі і перекомпілювати програму заново. Це значно спростить зміни у майбутньому.
- Константи для цих значень зроблять програму більш зрозумілою, оскільки кожне значення має зрозуміле ім’я.
Функції для роботи з ігровою картою
Файл, який містить функції для роботи з ігровою картою виглядає так:
// Файл game-map-utils.cpp
#include "game-map-utils.h"
#include <iostream>
#include "random-utils.h"
// Draws maze onto screen
// Parameters:
// maze - maze field to draw
void drawMaze(const std::array<std::array<char, mazeColumns>, mazeRows> &maze)
{
for (int row = 0; row < mazeRows; row++)
{
for (int column = 0; column < mazeColumns; column++)
{
char ch = maze[row][column];
std::cout << ch;
}
std::cout << std::endl;
}
}
// Searches given char on the given maze field,
// returns if found and filling row and column with coordinates
// Parameters:
// maze - maze field where character will be serched
// charToFind - char that should be found on maze field
// rCharRow - reference to row variable for which will be assigned row position
// rCharColumn - reference to column variable for which will be assigned column position
// Returns true if found; false otherwise.
bool scanForChar(const std::array<std::array<char, mazeColumns>, mazeRows> &maze,
const char charToFind,
int &rCharRow,
int &rCharColumn)
{
for (int row = 0; row < mazeRows; row++)
{
for (int column = 0; column < mazeColumns; column++)
{
if (maze[row][column] == charToFind)
{
rCharRow = row;
rCharColumn = column;
return true;
}
}
}
return false;
}
// Places given char on the game field in random way,
// omiting replacing existing characters
// Parameters:
// maze - maze field where character will be serched
// charToPlace - char that should be placed on maze field
// charCount - number of chars to place
void placeCharRandomly(std::array<std::array<char, mazeColumns>, mazeRows> &rMaze,
char charToPlace,
int charCount)
{
for(int i = 0; i < charCount; i++)
{
int randomRow = 0;
int randomColumn = 0;
do
{
randomRow = generateRandomNumber(0, mazeRows - 1);
randomColumn = generateRandomNumber(0, mazeColumns - 1);
}
while (rMaze[randomRow][randomColumn] != emptySymbol);
rMaze[randomRow][randomColumn] = charToPlace;
}
}
А відповідний для нього заголовний файл:
#ifndef GAME_MAP_UTILS_H
#define GAME_MAP_UTILS_H
#include <array>
#include "game-defs.h"
void drawMaze(const std::array<std::array<char, mazeColumns>, mazeRows> &maze);
bool scanForChar(const std::array<std::array<char, mazeColumns>, mazeRows> &maze, const char charToFind,
int &prCharRow, int &prCharColumn);
void placeCharRandomly(std::array<std::array<char, mazeColumns>, mazeRows> &rMaze,
char charToPlace,int charCount);
#endif // GAME_MAP_UTILS_H
Звичайно, для того щоб ці файли компілювались, необхідно також додати файл,який містить функції для генерації випадкових чисел, які ми розглядали у попередньому розділі:
// Файл random-utils.cpp
#include "random-utils.h"
#include <random>
#include <vector>
int generateRandomNumber(int min, int max)
{
static std::random_device randomDevice;
static std::mt19937 engine{randomDevice()};
std::uniform_int_distribution<int> distribution(min, max);
return distribution(engine);
}
std::vector<int> generateRandomSequence(int min, int max, int count)
{
std::vector<int> rRandomSequence;
for (int i = 0; i < count; ++i)
{
rRandomSequence.push_back(generateRandomNumber(min, max));
}
return rRandomSequence;
}
А також відповідний для нього заголовний файл:
// Файл random-utils.h
#ifndef RANDOM_UTILS_H
#define RANDOM_UTILS_H
#include <vector>
int generateRandomNumber(int min, int max);
std::vector<int> generateRandomSequence(int min, int max, int count);
#endif // RANDOM_UTILS_H