2026-05-21 16:27:53 +00:00
|
|
|
|
#include <fstream>
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
|
2026-05-19 22:17:12 +00:00
|
|
|
|
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:
|
2026-05-21 16:27:53 +00:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-05-19 22:17:12 +00:00
|
|
|
|
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];
|
2026-05-21 16:27:53 +00:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-19 22:17:12 +00:00
|
|
|
|
|
|
|
|
|
|
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];
|
|
|
|
|
|
}
|
2026-05-21 16:27:53 +00:00
|
|
|
|
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];
|
|
|
|
|
|
}
|
2026-05-19 22:17:12 +00:00
|
|
|
|
|
|
|
|
|
|
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;}
|
2026-05-21 16:27:53 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int main(){
|
|
|
|
|
|
|
|
|
|
|
|
}
|