На прикладі консольної гри розглянемо, як можна розділити програму на кілька файлів, а також використаємо наші нові знання про константи, функції та масиви.

Визначення для гри

Перш за все, у грі ми будемо використовувати набір констант, для яких варто створити окремий заголовний файл.

// Файл 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