diff --git a/SolovevDS/docs/data/data_for_task2/task2.cpp b/SolovevDS/docs/data/data_for_task2/task2.cpp index 8423440..2ad321f 100644 --- a/SolovevDS/docs/data/data_for_task2/task2.cpp +++ b/SolovevDS/docs/data/data_for_task2/task2.cpp @@ -2,6 +2,7 @@ #include #include #include +#include class cell{ private: @@ -373,9 +374,6 @@ class DFSStrategy : public PathFindingStrategy { 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]; @@ -386,6 +384,8 @@ class DFSStrategy : public PathFindingStrategy { } } + cell** stack = new cell*[width * height]; + int top = 0; stack[top] = start; top++; visited[start->getX()][start->getY()] = true; @@ -442,9 +442,143 @@ class DFSStrategy : public PathFindingStrategy { }; class AStarStrategy : public PathFindingStrategy { + private: + int heuristic(cell* current, cell* exit) {return std::abs(current->getX() - exit->getX()) + std::abs(current->getY() - exit->getY());} + public: cell** findPath(maze* m, cell* start, cell* exit) override { - // здесь будет алгоритм A* + int width = m->getWidth(); + int height = m->getHeight(); + + bool** closed = new bool*[width]; /*клетка [x][y] посещена (да/нет)*/ + bool** inOpen = new bool*[width]; /*клетка [x][y] имеет потенциал к посещению (да/нет)*/ + int** gScore = new int*[width]; /* до клетка [x][y] от старта gSchore[x][y] шагов*/ + int** fScore = new int*[width]; /*f = h + g, где g - эвристика клетки[x][y]*/ + + cell*** parent = new cell**[width]; + + + for (int x = 0; x < width; x++) { + closed[x] = new bool[height]; + inOpen[x] = new bool[height]; + gScore[x] = new int[height]; + fScore[x] = new int[height]; + + parent[x] = new cell*[height]; + + for (int y = 0; y < height; y++) { + closed[x][y] = false; + inOpen[x][y] = false; + + gScore[x][y] = width * height + 100000; /*тупо большое число чтоб было больше чем клеток в лаберинте*/ + fScore[x][y] = width * height + 100000; + + parent[x][y] = nullptr; + } + } + + cell** open = new cell*[width * height]; /*клетки с потенциалом на посещение*/ + int openCount = 0; /*это количество потенц клеток, а также индекс следующего незанятого места*/ + + int sx = start->getX(); + int sy = start->getY(); + + gScore[sx][sy] = 0; + fScore[sx][sy] = heuristic(start, exit); + + open[openCount] = start; + openCount++; + + inOpen[sx][sy] = true; + bool found = false; + + while (openCount > 0) { + int bestIndex = 0; + + for (int i = 1; i < openCount; i++) { + int ix = open[i]->getX(); + int iy = open[i]->getY(); + + int bx = open[bestIndex]->getX(); + int by = open[bestIndex]->getY(); + + if (fScore[ix][iy] < fScore[bx][by]) { + bestIndex = i; /*(fSchore наименьший в [bestIndex])*/ + } + } + + cell* current = open[bestIndex]; + + if (current == exit) { + found = true; + break; + } + + int cx = current->getX(); + int cy = current->getY(); + + open[bestIndex] = open[openCount - 1]; + openCount--; + + inOpen[cx][cy] = false; + closed[cx][cy] = true; + + 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 (closed[nx][ny]) { + continue; + } + + int tentativeG = gScore[cx][cy] + 1; + + if (tentativeG < gScore[nx][ny]) { + parent[nx][ny] = current; + + gScore[nx][ny] = tentativeG; + fScore[nx][ny] = gScore[nx][ny] + heuristic(next, exit); + + if (!inOpen[nx][ny]) { + open[openCount] = next; + openCount++; + + inOpen[nx][ny] = true; + } + } + } + delete[] neighbors; + } + + cell** path; + if (found) { + path = PathBuilder::buildPath(start, exit, parent); + } + else { + path = new cell*[1]; + path[0] = nullptr; + } + + delete[] open; + + for (int x = 0; x < width; x++) { + delete[] closed[x]; + delete[] inOpen[x]; + delete[] gScore[x]; + delete[] fScore[x]; + delete[] parent[x]; + } + delete[] closed; + delete[] inOpen; + delete[] gScore; + delete[] fScore; + delete[] parent; + + return path; } };