#include #include #include #include class cell{ private: int x, y; bool isWall; bool isExit; bool isStart; public: cell(){x=0; y=0; isWall=false; isExit=false; isStart = false;} cell(int x, int y, bool isWall, bool isExit, bool isStart) { this->x = x; this->y = y; this->isWall = isWall; this->isExit = isExit; this->isStart = isStart; } bool isPassable() {return !isWall;} void setStart(bool value) {isStart = value;} void setExit(bool value) {isExit = value;} void setX(int x) {this->x = x;} void setY(int y) {this->y = y;} void setIsWall(bool isWall) {this->isWall = isWall;} int getX() {return x;} int getY() {return y;} bool getIsWall() {return isWall;} bool getIsExit() {return isExit;} bool getIsStart() {return isStart;} }; class maze{ private: int width; int height; cell** matrix; cell* start; cell* exit; public: maze(int width, int height) { this->width = width; this->height = height; this->start = nullptr; this->exit = nullptr; matrix = new cell*[width]; for (int x = 0; x < width; ++x) { matrix[x] = new cell[height]; for (int y = 0; y < height; ++y) matrix[x][y] = cell(x, y, false, false, false); } } maze(int width, int height, int startX, int startY, int exitX, int exitY) { this->width = width; this->height = height; this->start = nullptr; this->exit = nullptr; matrix = new cell*[width]; for (int x = 0; x < width; ++x) { matrix[x] = new cell[height]; for (int y = 0; y < height; ++y) { matrix[x][y] = cell(x, y, false, false, false); } } matrix[startX][startY].setStart(true); matrix[exitX][exitY].setExit(true); start = &matrix[startX][startY]; exit = &matrix[exitX][exitY]; } ~maze() { for (int i = 0; i < width; ++i) delete[] matrix[i]; delete[] matrix; } cell* getCell(int x, int y) { if (x < 0 || x >= width || y < 0 || y >= height) return nullptr; return &matrix[x][y]; } void setCell(int x, int y, cell newCell) { if (x < 0 || x >= width || y < 0 || y >= height) return; matrix[x][y] = newCell; if (matrix[x][y].getIsStart()) start = &matrix[x][y]; if (matrix[x][y].getIsExit()) exit = &matrix[x][y]; } cell** getNeighbors(cell* current) { /*ДЕЛАТЬ delete[] neighbors; !!!!!!!!!!!!!!!*/ cell** neighbors = new cell*[5]; int count = 0; int x = current->getX(); int y = current->getY(); cell* up = getCell(x, y - 1); cell* down = getCell(x, y + 1); cell* left = getCell(x - 1, y); cell* right = getCell(x + 1, y); if (up != nullptr && up->isPassable()) { neighbors[count] = up; count++;} if (down != nullptr && down->isPassable()) { neighbors[count] = down; count++;} if (left != nullptr && left->isPassable()) { neighbors[count] = left; count++;} if (right != nullptr && right->isPassable()) { neighbors[count] = right; count++;} neighbors[count] = nullptr; return neighbors; } cell* getStart() {return start;} cell* getExit() {return exit;} int getWidth() {return width;} int getHeight() {return height;} }; class MazeBuilder { public: virtual maze* buildFromFile(const std::string& filename) = 0; virtual ~MazeBuilder() {} }; class TextFileMazeBuilder : public MazeBuilder { public: maze* buildFromFile(const std::string& filename) override { std::ifstream file(filename); if (!file.is_open()) throw std::runtime_error("Ошибка: Не удалось открыть файл!"); std::string line; int width = 0; int height = 0; // ДОБАВИЛ: первый проход по файлу. // Здесь узнаём ширину и высоту лабиринта. while (std::getline(file, line)) { if (height == 0) { width = line.length(); } else { if (line.length() != width) throw std::runtime_error("Ошибка: строки лабиринта разной длины!"); } height++; } if (width == 0 || height == 0) { throw std::runtime_error("Ошибка: файл пустой!"); } file.clear(); file.seekg(0); maze* labirint = new maze(width, height); bool hasStart = false; bool hasExit = false; int y = 0; while (std::getline(file, line)) { for (int x = 0; x < width; x++) { char ch = line[x]; bool isWall = false; bool isStart = false; bool isExit = false; switch(ch){ case '#': isWall = true; break; case ' ': isWall = false; break; case 'S': isStart = true; if (hasStart) throw std::runtime_error("Ошибка: в лабиринте больше одного старта!"); hasStart = true; break; case 'E': isExit = true; if (hasExit) throw std::runtime_error("Ошибка: в лабиринте больше одного выхода!"); hasExit = true; break; default: throw std::runtime_error("Ошибка: неизвестный символ в файле!"); break; } cell current(x, y, isWall, isExit, isStart); labirint->setCell(x, y, current); } y++; } file.close(); if (!hasStart) throw std::runtime_error("Ошибка: в лабиринте нет старта!"); if (!hasExit) throw std::runtime_error("Ошибка: в лабиринте нет выхода!"); return labirint; } // прочитать символы // создать клетки // вернуть готовый Maze } }; class PathFindingStrategy { public: virtual cell** findPath(maze* m, cell* start, cell* exit) = 0; virtual ~PathFindingStrategy() {} }; class PathBuilder { public: static cell** buildPath(cell* start, cell* exit, cell*** parent) { int length = 0; cell* current = exit; while (current != nullptr) { length++; if (current == start) break; current = parent[current->getX()][current->getY()]; } cell** path = new cell*[length + 1]; current = exit; for (int i = length - 1; i >= 0; i--) { path[i] = current; if (current == start) break; current = parent[current->getX()][current->getY()]; } path[length] = nullptr; return path; } }; class BFSStrategy : public PathFindingStrategy { public: cell** findPath(maze* m, cell* start, cell* exit) override { int width = m->getWidth(); int height = m->getHeight(); bool** visited = new bool*[width]; cell*** parent = new cell**[width]; for (int x = 0; x < width; x++) { visited[x] = new bool[height]; parent[x] = new cell*[height]; for (int y = 0; y < height; y++) { visited[x][y] = false; parent[x][y] = nullptr; } } cell** deque = new cell*[width * height]; int head = 0; int tail = 0; deque[tail] = start; tail++; visited[start->getX()][start->getY()] = true; bool found = false; while (head < tail) { cell* current = deque[head]; head++; if (current == exit) { //сравниваются указатели found = true; break; } cell** neighbors = m->getNeighbors(current); for (int i = 0; neighbors[i] != nullptr; i++) { cell* next = neighbors[i]; int nx = next->getX(); int ny = next->getY(); if (!visited[nx][ny]) { visited[nx][ny] = true; parent[nx][ny] = current; deque[tail] = next; tail++; } } delete[] neighbors; } cell** path; if (found) { path = PathBuilder::buildPath(start, exit, parent); } else { path = new cell*[1]; path[0] = nullptr; } delete[] deque; for (int x = 0; x < width; x++) { delete[] visited[x]; delete[] parent[x]; } delete[] visited; delete[] parent; return path; } }; class DFSStrategy : public PathFindingStrategy { public: cell** findPath(maze* m, cell* start, cell* exit) override { int width = m->getWidth(); int height = m->getHeight(); bool** visited = new bool*[width]; cell*** parent = new cell**[width]; cell** stack = new cell*[width * height]; int top = 0; for (int x = 0; x < width; x++) { visited[x] = new bool[height]; parent[x] = new cell*[height]; for (int y = 0; y < height; y++) { visited[x][y] = false; parent[x][y] = nullptr; } } stack[top] = start; top++; visited[start->getX()][start->getY()] = true; bool found = false; while (top > 0) { top--; cell* current = stack[top]; if (current == exit) { //сравниваются указатели found = true; break; } cell** neighbors = m->getNeighbors(current); for (int i = 0; neighbors[i] != nullptr; i++) { cell* next = neighbors[i]; int nx = next->getX(); int ny = next->getY(); if (!visited[nx][ny]) { visited[nx][ny] = true; parent[nx][ny] = current; stack[top] = next; top++; } } delete[] neighbors; } cell** path; if (found) { path = PathBuilder::buildPath(start, exit, parent); } else { path = new cell*[1]; path[0] = nullptr; } delete[] stack; for (int x = 0; x < width; x++) { delete[] visited[x]; delete[] parent[x]; } delete[] visited; delete[] parent; return path; } }; class AStarStrategy : public PathFindingStrategy { public: cell** findPath(maze* m, cell* start, cell* exit) override { // здесь будет алгоритм A* } }; int main(){ }