2026-rff_mp/SolovevDS/docs/data/data_for_task2/task2.cpp
2026-05-22 00:51:21 +03:00

454 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <fstream>
#include <iostream>
#include <string>
#include <stdexcept>
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(){
}