#include "engine/matrix.hpp" #include "engine/vector2.hpp" #include "getopt.h" #include "maze.hpp" #include "random_generator.hpp" #include "utils.hpp" #include #include #include void optarg_error(int arg, std::string error) { std::cout << "Error: Invalid option argument for -" << arg << ". " << error << std::endl; exit(EXIT_FAILURE); } void validate_start_coords(unsigned int start_x, unsigned int start_y, unsigned int width, unsigned int height) { if (start_x >= width) { throw "The x start coordinate cannot be higher than or equal to the maze's width"; } if (start_y >= height) { throw "The y start coordinate cannot be higher than or equal to the maze's " "height"; } } /** * Parses a unsigned integer command-line argument. * * @param num_dst A pointer to a place to store the result value * @param arg The command-line argument character * @param check_zero Whether or not to make sure that the result is not zero */ void parse_uint_arg(unsigned int *num_dst, int arg, bool check_zero = false) { try { *num_dst = str_to_uint(std::string(optarg)); if (check_zero && *num_dst == 0) { throw "It should not be 0"; } } catch (const char *error) { optarg_error(arg, std::string(error)); } } const struct option options[] = {{"width", required_argument, NULL, 'w'}, {"height", required_argument, NULL, 'h'}, {"wall", required_argument, NULL, 'W'}, {"seed", required_argument, NULL, 's'}, {"start-x", required_argument, NULL, 'x'}, {"start-y", required_argument, NULL, 'y'}, {"help", no_argument, NULL, 0}, {NULL, 0, NULL, 0}}; int main(int argc, char *argv[]) { unsigned int maze_width = 40U; unsigned int maze_height = 20U; std::unique_ptr start_x = nullptr; std::unique_ptr start_y = nullptr; std::shared_ptr random_gen = nullptr; std::string wall = "█"; int arg; while ((arg = getopt_long(argc, argv, "w:h:W:s:x:y:", options, nullptr)) != -1) { switch (arg) { case 'w': parse_uint_arg(&maze_width, arg, true); break; case 'h': parse_uint_arg(&maze_height, arg, true); break; case 'x': start_x = std::make_unique(); parse_uint_arg(start_x.get(), arg); break; case 'y': start_y = std::make_unique(); parse_uint_arg(start_y.get(), arg); break; case 'W': wall = optarg; break; case 's': unsigned int seed; parse_uint_arg(&seed, arg, true); random_gen = std::make_shared(seed); break; case 0: std::cout << "Usage: " << argv[0] << " [OPTION]...\n\n" "Options:\n" " -w, --width WIDTH The width of the maze (Default: 40)\n" " -h, --height HEIGHT The height of the maze (Default: 20)\n" " -x, --start-x X The x coordinate for the start " "position " "(Default: random)\n" " -y, --start-y Y The y coordinate for the start " "position " "(Default: random)\n" " -W, --wall WALL Single character used as maze walls " "(Default: '█')\n" " -s, --seed SEED The randomization seed used for maze " "generation\n" " --help Displays usage information" << std::endl; return EXIT_SUCCESS; case '?': std::cout << "\nTry '" << argv[0] << " --help' for more information" << std::endl; return EXIT_FAILURE; } } if (random_gen == nullptr) { random_gen = std::make_shared(); } if (start_x == nullptr) { start_x = std::make_unique(random_gen->in_range(0, maze_width - 1U)); } if (start_y == nullptr) { start_y = std::make_unique(random_gen->in_range(0, maze_height - 1U)); } try { validate_start_coords(*start_x, *start_y, maze_width, maze_height); } catch (const char *error) { std::cout << "Error: " << error << std::endl; return EXIT_FAILURE; } Matrix matrix(maze_height * 2U + 1U, maze_width * 2U + 1U); matrix.fill(wall); auto start_pos = std::make_shared(*start_x * 2U + 1U, *start_y * 2U + 1U); matrix_to_maze(&matrix, start_pos, " ", random_gen); matrix.print(); }