From 4db43221f776fd5a82e7100eeb0ba40d851012c2 Mon Sep 17 00:00:00 2001 From: kahero <75095373+kaherro@users.noreply.github.com> Date: Mon, 19 Jan 2026 18:33:05 +0300 Subject: [PATCH 1/2] [feat]: Added kruskal's and wilson's algorithms for maze generation --- mazes.cpp | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 180 insertions(+), 4 deletions(-) diff --git a/mazes.cpp b/mazes.cpp index 5a7950b..ee42c28 100644 --- a/mazes.cpp +++ b/mazes.cpp @@ -1,6 +1,10 @@ #include #include #include +#include +#include +#include +#include #include using namespace std; @@ -9,21 +13,27 @@ class MazeVisualizer { int width = 10, height = 10; vector> maze; - void Vizualize() { + void Visualize() { string buffer = ""; for (int i = 0; i < 1 + height * 2; i++) { for (int j = 0; j < 1 + width * 2; j++) { + if(maze[i][j] == '.') { + buffer += "\033[93m\xDB\033[0m"; // yellow + buffer += "\033[93m\xDB\033[0m"; // yellow + continue; + } buffer += maze[i][j]; buffer += maze[i][j]; } buffer += '\n'; } cout << "\033[H" << buffer; + Sleep(30); } void dfs(int x, int y, vector> &visited) { - Vizualize(); maze[x][y] = ' '; + Visualize(); visited[x][y] = true; vector> directions = {{0, 2}, {2, 0}, {0, -2}, {-2, 0}}; random_shuffle(directions.begin(), directions.end()); @@ -37,14 +47,180 @@ class MazeVisualizer { } } + pair dsu_find(pair v, vector>>& parent) { + while (v != parent[v.first][v.second]) { + v = parent[v.first][v.second]; + } + return v; + } + + bool dsu_unite(pair a, pair b, + vector>>& parent, vector>& rank) { + a = dsu_find(a, parent); + b = dsu_find(b, parent); + if (a != b) { + if (rank[a.first][a.second] < rank[b.first][b.second]) { + swap(a, b); + } + parent[b.first][b.second] = a; + if (rank[a.first][a.second] == rank[b.first][b.second]) { + rank[a.first][a.second]++; + } + return true; + } + return false; + } + + void kruskal() { + vector, pair>> walls; + for (int i = 1; i < height * 2; i += 2) { + for (int j = 1; j < width * 2; j += 2) { + if (i + 2 < height * 2 + 1) { + walls.push_back({{i, j}, {i + 2, j}}); + } + if (j + 2 < width * 2 + 1) { + walls.push_back({{i, j}, {i, j + 2}}); + } + } + } + + random_shuffle(walls.begin(), walls.end()); + vector>> parent(1 + height * 2, vector>(1 + width * 2)); + vector> rank(1 + height * 2, vector(1 + width * 2, 0)); + + for (int i = 1; i < 1 + height * 2; i += 2) { + for (int j = 1; j < 1 + width * 2; j += 2) { + parent[i][j] = {i, j}; + } + } + + for (auto& wall : walls) { + auto u = wall.first; + auto v = wall.second; + int wallX = (u.first + v.first) / 2; + int wallY = (u.second + v.second) / 2; + if (dsu_find(u, parent) != dsu_find(v, parent)) { + maze[u.first][u.second] = ' '; + maze[wallX][wallY] = ' '; + maze[v.first][v.second] = ' '; + dsu_unite(u, v, parent, rank); + Visualize(); + } + } + Visualize(); + } + + void wilson() { + vector> visited(1 + height * 2, vector(1 + width * 2, false)); + int startX = 1 + 2 * (rand() % height); + int startY = 1 + 2 * (rand() % width); + maze[startX][startY] = ' '; + visited[startX][startY] = true; + Visualize(); + + vector> unvisited; + for (int i = 1; i < 1 + height * 2; i += 2) { + for (int j = 1; j < 1 + width * 2; j += 2) { + if (!(i == startX && j == startY)) { + unvisited.push_back({i, j}); + } + } + } + random_shuffle(unvisited.begin(), unvisited.end()); + + while (!unvisited.empty()) { + int i = rand() % unvisited.size(); + pair current = unvisited[i]; + int x = current.first; + int y = current.second; + + vector> path; + unordered_map> visited_path; + pair prev = {x, y}; + while (!visited[x][y]) { + path.push_back({x, y}); + visited_path[x][y] = true; + maze[x][y] = '.'; + maze[(x + prev.first) / 2][(y + prev.second) / 2] = '.'; + vector> directions = {{0, 2}, {2, 0}, {0, -2}, {-2, 0}}; + vector> valid_moves; + for (auto& dir : directions) { + int vx = x + dir.first; + int vy = y + dir.second; + if (vx >= 1 && vx < 1 + height * 2 && + vy >= 1 && vy < 1 + width * 2) { + valid_moves.push_back({vx, vy}); + } + } + + if (!valid_moves.empty()) { + pair next = valid_moves[rand() % valid_moves.size()]; + maze[(x + next.first) / 2][(y + next.second) / 2] = '.'; + if (visited_path[next.first][next.second]) { + auto it = path.begin(); + while (it != path.end()) { + if (it->first == next.first && it->second == next.second) { + break; + } + visited_path[it->first][it->second] = false; + maze[it->first][it->second] = '\xDB'; + prev = {it->first, it->second}; + ++it; + maze[(prev.first + it->first) / 2][(prev.second + it->second) / 2] = '\xDB'; + } + path.erase(path.begin(), it); + } + prev = {x, y}; + x = next.first; + y = next.second; + } + Visualize(); + } + path.push_back({x, y}); + + for (size_t i = 0; i < path.size() - 1; i++) { + int x1 = path[i].first; + int y1 = path[i].second; + int x2 = path[i + 1].first; + int y2 = path[i + 1].second; + maze[x1][y1] = ' '; + visited[x1][y1] = true; + maze[(x1 + x2) / 2][(y1 + y2) / 2] = ' '; + for (auto it = unvisited.begin(); it != unvisited.end(); ++it) { + if (it->first == x1 && it->second == y1) { + unvisited.erase(it); + break; + } + } + Visualize(); + } + Visualize(); + } + } + public: MazeVisualizer() : maze(1 + height * 2, vector(1 + width * 2, '\xDB')) {} - - void generate_maze(int height, int width) { + + void dfs(int height, int width) { this->height = height; this->width = width; maze = vector>(1 + height * 2, vector(1 + width * 2, '\xDB')); vector> visited(1 + height * 2, vector(1 + width * 2, false)); + Visualize(); dfs(1, 1, visited); } + void kruskal(int height, int width) { + this->height = height; + this->width = width; + maze = vector>(1 + height * 2, vector(1 + width * 2, '\xDB')); + Visualize(); + kruskal(); + } + void wilson(int height, int width) { + this->height = height; + this->width = width; + maze = vector>(1 + height * 2, vector(1 + width * 2, '\xDB')); + Visualize(); + wilson(); + } }; From 9f8e92f8abd6976fdc223f1680b05b2cfa0f1e98 Mon Sep 17 00:00:00 2001 From: kahero <75095373+kaherro@users.noreply.github.com> Date: Mon, 19 Jan 2026 18:34:47 +0300 Subject: [PATCH 2/2] [fix]: Fixed input menu bug in main.cpp and added new maze generating options --- main.cpp | 90 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 27 deletions(-) diff --git a/main.cpp b/main.cpp index b5c5ce9..f14d3b0 100644 --- a/main.cpp +++ b/main.cpp @@ -2,15 +2,23 @@ #include #include "sortings.cpp" #include "mazes.cpp" +#include + +void clear_input_buffer() { + while (_kbhit()) { + _getch(); + } +} using namespace std; class Menu { private: - int enter_n() { + int enter_permutation() { system("cls"); cout << "Enter size of permutation to be sort:\n"; int n = -1; + clear_input_buffer(); cin >> n; while (cin.fail() || n <= 0 || n > 200) { system("cls"); @@ -23,6 +31,23 @@ class Menu { } return n; } + pair enter_maze() { + system("cls"); + cout << "Enter size of maze (height width):\n"; + int height = -1, width = -1; + cin >> height >> width; + clear_input_buffer(); + while (cin.fail() || height <= 0 || width <= 0 || height > 50 || width > 50) { + system("cls"); + cout << "Invalid size. Please enter height (1-50) and width (1-50).\n"; + cin.clear(); + cin.ignore(numeric_limits::max(), '\n'); + cin >> height >> width; + cin.clear(); + cin.ignore(numeric_limits::max(), '\n'); + } + return {height, width}; + } void sort_selection_menu() { string menuItems[8] = { "Bubble sort", "Selection sort", "Merge sort", "Quick sort", @@ -63,7 +88,7 @@ class Menu { case 0: { system("cls"); SortVisualizer sorter; - int n = enter_n(); + int n = enter_permutation(); system("cls"); sorter.random_array(n); sorter.bubble_sort(); @@ -73,7 +98,7 @@ class Menu { case 1: { system("cls"); SortVisualizer sorter; - int n = enter_n(); + int n = enter_permutation(); system("cls"); sorter.random_array(n); sorter.selection_sort(); @@ -83,7 +108,7 @@ class Menu { case 2: { system("cls"); SortVisualizer sorter; - int n = enter_n(); + int n = enter_permutation(); system("cls"); sorter.random_array(n); sorter.merge_sort(); @@ -93,7 +118,7 @@ class Menu { case 3: { system("cls"); SortVisualizer sorter; - int n = enter_n(); + int n = enter_permutation(); system("cls"); sorter.random_array(n); sorter.quick_sort(); @@ -103,7 +128,7 @@ class Menu { case 4: { system("cls"); SortVisualizer sorter; - int n = enter_n(); + int n = enter_permutation(); system("cls"); sorter.random_array(n); sorter.heap_sort(); @@ -113,7 +138,7 @@ class Menu { case 5: { system("cls"); SortVisualizer sorter; - int n = enter_n(); + int n = enter_permutation(); system("cls"); sorter.random_array(n); sorter.bogo_sort(); @@ -123,7 +148,7 @@ class Menu { case 6: { system("cls"); SortVisualizer sorter; - int n = enter_n(); + int n = enter_permutation(); system("cls"); sorter.random_array(n); sorter.miracle_sort(); @@ -135,6 +160,8 @@ class Menu { cout << "Exiting...\n"; Sleep(1000); main_menu_display(); + menuActive = false; + return; } } } @@ -144,14 +171,14 @@ class Menu { } void maze_selection_menu() { - string menuItems[2] = { "Generate maze", "Exit" }; + string menuItems[4] = { "DFS", "Kruskal", "Wilson", "Exit" }; int selected = 0; bool menuActive = true; while (menuActive) { system("cls"); cout << "=== MAZE MENU ===\n\n"; - for (int i = 0; i < 2; i++) { + for (int i = 0; i < 4; i++) { if (i == selected) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 11); // cyan cout << "> " << menuItems[i] << " <" << endl; @@ -168,41 +195,50 @@ class Menu { while (menuActive) { if (GetAsyncKeyState(VK_UP) & 1) { selected--; - if (selected < 0) selected = 2; + if (selected < 0) selected = 3; break; } else if (GetAsyncKeyState(VK_DOWN) & 1){ selected++; - if (selected > 2) selected = 0; + if (selected > 3) selected = 0; break; } else if (GetAsyncKeyState(VK_RETURN) & 1){ switch (selected){ case 0: { - system("cls"); - cout << "Enter size of maze (height width): "; - int height = -1, width = -1; - cin >> height >> width; - while (cin.fail() || height <= 0 || width <= 0 || height > 50 || width > 50) { - system("cls"); - cout << "Invalid size. Please enter height (1-50) and width (1-50).\n"; - cin.clear(); - cin.ignore(numeric_limits::max(), '\n'); - cin >> height >> width; - cin.clear(); - cin.ignore(numeric_limits::max(), '\n'); - } + int height, width; + tie(height, width) = enter_maze(); system("cls"); MazeVisualizer mazeVis; - mazeVis.generate_maze(height, width); + mazeVis.dfs(height, width); system("pause"); return; } case 1: { + int height, width; + tie(height, width) = enter_maze(); + system("cls"); + MazeVisualizer mazeVis; + mazeVis.kruskal(height, width); + system("pause"); + return; + } + case 2: { + int height, width; + tie(height, width) = enter_maze(); + system("cls"); + MazeVisualizer mazeVis; + mazeVis.wilson(height, width); + system("pause"); + return; + } + case 3: { system("cls"); cout << "Exiting...\n"; Sleep(1000); main_menu_display(); + menuActive = false; + return; } } } @@ -282,4 +318,4 @@ int main() { Menu menu; menu.main_menu_display(); -} +} \ No newline at end of file