#include "MazeGenerator.h" MazeGenerator::MazeGenerator(uint32_t height, uint32_t width) : m_areaHeight(height), m_areaWidth(width) { if ((!m_areaHeight % 2u) || (!(m_areaWidth % 2u))) { throw std::invalid_argument("The Heigh and Width must be odd numbers"); } m_area = new char* [m_areaHeight]; for (int y = 0; y < m_areaHeight; y++) { m_area[y] = new char[m_areaWidth]; for (int x = 0; x < m_areaWidth; x++) { m_area[y][x] = Maze_Char_Wall; } } InitializeMapDetails(); } MazeGenerator::~MazeGenerator() { for (int y = 0; y < m_areaHeight; y++) { delete[] m_area[y]; } delete[] m_area; } void MazeGenerator::SetCell(uint32_t y, uint32_t x, uint32_t value) { if ((m_areaHeight <= y) || m_areaWidth <= x) { throw std::invalid_argument("Out of boundry"); } else if ((Maze_Char_Space != 32) && (Maze_Char_Exit != 69) && (Maze_Char_Start != 83) && (Maze_Char_Wall != 88) && (Maze_Char_Path != 111)) { throw std::invalid_argument("The input can only contain allowed ASCII character"); } else { m_area[y][x] = value; } } void MazeGenerator::SetMaze(char** maze, uint32_t mazeHeight, uint32_t mazeWidth) { if ((m_areaHeight != mazeHeight) || (m_areaWidth != mazeWidth)) { throw std::invalid_argument("Maze height and width is not the same"); } else { for (int y = 0; y < mazeHeight; y++) { for (int x = 0; x < mazeWidth; x++) { if ((Maze_Char_Space != 32) && (Maze_Char_Exit != 69) && (Maze_Char_Start != 83) && (Maze_Char_Wall != 88) && (Maze_Char_Path != 111)) { throw std::invalid_argument("The input can only contain allowed ASCII character"); } else { m_area[y][x] = maze[y][x]; } } } } } void MazeGenerator::GenerateWalls() { for (int y = 0; y < m_areaHeight; y++) { for (int x = 0; x < m_areaWidth; x++) { m_area[y][x] = Maze_Char_Wall; } } } void MazeGenerator::GenerateCentreSpace(uint32_t exitEntrance) { Maze_Height_Half = m_areaHeight / 2; Maze_Width_Half = m_areaWidth / 2; for (int i = Maze_Centre_Top; i < Maze_Centre_Bottom; i++) { for (int j = (Maze_Centre_Left); j < Maze_Centre_Right; j++) { m_area[i][j] = Maze_Char_Space; } } m_area[Maze_Height_Half][Maze_Width_Half] = exitEntrance; } void MazeGenerator::GenerateRandomExit(int n, int* exitsLocation, int* playerLocation, uint32_t exitEntrance) { int constexpr min = 0; int maxH = m_areaHeight - 1; int maxW = m_areaWidth - 1; int exitsLocationCount = 0; int playersLocationCount = 0; srand(time(0)); for (int i = 0; i < n; i++) { int randNum = rand() % (maxH - min + 1) + min; if ((randNum == 0) || (randNum == maxH)) { int randNum2 = rand() % (maxW - min + 1) + min; if (m_area[randNum][randNum2] != Maze_Char_Exit) { m_area[randNum][randNum2] = Maze_Char_Exit; exitsLocation[exitsLocationCount] = randNum; exitsLocationCount++; exitsLocation[exitsLocationCount] = randNum2; exitsLocationCount++; if (((randNum == min) || (randNum == maxH)) && ((randNum2 == min || randNum2 == maxW))) {} else { if (randNum == 0) { m_area[randNum + 1][randNum2] = exitEntrance; m_area[randNum + 2][randNum2] = Maze_Char_Space; if (playerLocation) { playerLocation[playersLocationCount] = randNum + 1; playersLocationCount++; playerLocation[playersLocationCount] = randNum2; playersLocationCount++; } } else { m_area[randNum - 1][randNum2] = exitEntrance; m_area[randNum - 2][randNum2] = Maze_Char_Space; if (playerLocation) { playerLocation[playersLocationCount] = randNum - 1; playersLocationCount++; playerLocation[playersLocationCount] = randNum2; playersLocationCount++; } } } } else { i--; } } else { int randomBit = rand() & 1; int randomBit2 = (randomBit == 1) ? maxW : 0; if (m_area[randNum][randomBit2] != Maze_Char_Exit) { m_area[randNum][randomBit2] = Maze_Char_Exit; exitsLocation[exitsLocationCount] = randNum; exitsLocationCount++; exitsLocation[exitsLocationCount] = randomBit2; exitsLocationCount++; if (randomBit2 == 0) { m_area[randNum][randomBit2 + 1] = exitEntrance; m_area[randNum][randomBit2 + 2] = Maze_Char_Space; if (playerLocation) { playerLocation[playersLocationCount] = randNum; playersLocationCount++; playerLocation[playersLocationCount] = randomBit2 + 1; playersLocationCount++; } } else { m_area[randNum][randomBit2 - 1] = exitEntrance; m_area[randNum][randomBit2 - 2] = Maze_Char_Space; if (playerLocation) { playerLocation[playersLocationCount] = randNum; playersLocationCount++; playerLocation[playersLocationCount] = randomBit2 - 1; playersLocationCount++; } } } else { i--; } } } } void MazeGenerator::PrintMaze() { for (int y = 0; y < m_areaHeight; y++) { for (int x = 0; x < m_areaWidth; x++) { std::cout << m_area[y][x]; std::cout << ((x == (m_areaWidth - 1)) ? "\n" : ""); } } } void MazeGenerator::InitializeMapDetails() { Maze_Height_Half = m_areaHeight / 2; Maze_Width_Half = m_areaWidth / 2; Maze_Exits = (2 * (Maze_Height_Half - 1)) + (2 * (Maze_Width_Half - 1)); Maze_Max_Exits = (2 * (m_areaHeight - 2)) + (2 * (m_areaWidth - 2)); Maze_Centre_Top = Maze_Height_Half - 3; Maze_Centre_Bottom = Maze_Height_Half + 4; Maze_Centre_Left = Maze_Width_Half - 3; Maze_Centre_Right = Maze_Width_Half + 4; Maze_Centre_Size = (Maze_Centre_Bottom - Maze_Centre_Top) * (Maze_Centre_Right - Maze_Centre_Left); Maze_All_Nodes = m_areaHeight * m_areaWidth; Maze_Available_Nodes = Maze_All_Nodes - (Maze_Exits + Maze_Centre_Size); Maze_Nodes_To_Clear = (int)Maze_All_Nodes * 0.35; }