diff --git a/application.cpp b/application.cpp index bc27fbc..18d6a6e 100644 --- a/application.cpp +++ b/application.cpp @@ -10,12 +10,16 @@ Application::Application() : render_window({SCREEN_WIDTH, SCREEN_HEIGHT}, "Sliding Puzzle") {} -void Application::run() +bool Application::init(int splitting, const std::string &path) { render_window.setFramerateLimit(60); - render_window.display(); + return board.init(splitting, path); +} +void Application::run() +{ // Main game cycle + render_window.display(); while (render_window.isOpen()) { processInput(); diff --git a/application.h b/application.h index fc51fdb..1b0e2bc 100644 --- a/application.h +++ b/application.h @@ -8,6 +8,9 @@ class Application public: explicit Application(); + // Init game + bool init(int splitting, const std::string& path); + // Launch game void run(); diff --git a/board.cpp b/board.cpp index 14205ba..265b356 100644 --- a/board.cpp +++ b/board.cpp @@ -2,70 +2,10 @@ #include #include -const std::string picture_dest = "art.png"; - -Board::Board(int splitting) : +Board::Board() : selection_index(0), on_selection(false) -{ - // PREPARING INITIAL BOARD STATE // - - if (!global_texture.loadFromFile(picture_dest) ) - return; - - if (splitting <= 1) // If it's 1, the game is already over - { - sf::Sprite* sp = new sf::Sprite(global_texture); - vec_field.push_back(new Cell{0, 0, sp}); - return; - } - - const int width = global_texture.getSize().x; - const int height = global_texture.getSize().y; - - Cell::side_length = (width < height) ? width / splitting : height / splitting; - cells_on_height = height / Cell::side_length; - cells_on_width = width / Cell::side_length; - - vec_field.reserve(cells_on_height * cells_on_width); - - /* Iterating board cells' screen positions. - * The initial image after this would look exactly like the loaded picture, not shuffled yet. */ - Cells::size_type index = 0; - for (int x = 0; x < height; x += Cell::side_length) - { - if ((height - x) >= Cell::side_length) - { - for (int y = 0; y < width; y += Cell::side_length) - { - if ((width - y) >= Cell::side_length) - { - sf::Sprite* sp = new sf::Sprite(global_texture, sf::IntRect(y, x, Cell::side_length, Cell::side_length)); - sp->setPosition(static_cast(y), static_cast(x)); - - vec_field.push_back(new Cell({index, index, sp})); - ++index; - } - } - } - } - - // SHUFFLING // - - srand(static_cast(time(nullptr))); - for (Cells::size_type curr_i = 0; curr_i < vec_field.size(); ++curr_i) - { - Cells::size_type swap_i; - do - { // find two different tiles - swap_i = rand() & (vec_field.size() - 1); - } while (curr_i == swap_i); - - swapCells(curr_i, swap_i); - } - - setSelectionVertex(selection_index); -} +{} Board::~Board() { @@ -217,4 +157,68 @@ bool Board::isWinCondition() const return std::all_of(vec_field.begin(), vec_field.end(), [](const Cell *cell){ return cell->current_index == cell->inital_index; }); } +bool Board::init(int splitting, const std::string& path) +{ + // PREPARING INITIAL BOARD STATE // + + if (!global_texture.loadFromFile(path) ) + return EXIT_FAILURE; + + if (splitting <= 1) // If it's 1, the game is already over + { + sf::Sprite* sp = new sf::Sprite(global_texture); + vec_field.push_back(new Cell{0, 0, sp}); + return EXIT_SUCCESS; // why not + } + + const int width = global_texture.getSize().x; + const int height = global_texture.getSize().y; + + Cell::side_length = (width < height) ? width / splitting : height / splitting; + cells_on_height = height / Cell::side_length; + cells_on_width = width / Cell::side_length; + + vec_field.reserve(cells_on_height * cells_on_width); + + /* Iterating board cells' screen positions. + * The initial image after this would look exactly like the loaded picture, not shuffled yet. */ + Cells::size_type index = 0; + for (int x = 0; x < height; x += Cell::side_length) + { + if ((height - x) >= Cell::side_length) + { + for (int y = 0; y < width; y += Cell::side_length) + { + if ((width - y) >= Cell::side_length) + { + sf::Sprite* sp = new sf::Sprite(global_texture, sf::IntRect(y, x, Cell::side_length, Cell::side_length)); + sp->setPosition(static_cast(y), static_cast(x)); + + vec_field.push_back(new Cell({index, index, sp})); + ++index; + } + } + } + } + + // SHUFFLING // + + srand(static_cast(time(nullptr))); + for (Cells::size_type curr_i = 0; curr_i < vec_field.size(); ++curr_i) + { + Cells::size_type swap_i; + do + { // find two different tiles + swap_i = rand() & (vec_field.size() - 1); + } while (curr_i == swap_i); + + swapCells(curr_i, swap_i); + } + + // Set initial position of cursor + setSelectionVertex(selection_index); + + return EXIT_SUCCESS; +} + int Board::Cell::side_length = 0; diff --git a/board.h b/board.h index bef8dde..1e83106 100644 --- a/board.h +++ b/board.h @@ -23,7 +23,7 @@ enum class DIRECTION class Board { public: - explicit Board(int splitting = 1); + explicit Board(); ~Board(); // Output current graphical state on application window @@ -38,25 +38,28 @@ public: // Did player win the game bool isWinCondition() const; + // Set play image + bool init(int splitting, const std::string& path); + private: // Game tile struct Cell { - std::vector::size_type inital_index; - std::vector::size_type current_index; + std::vector::size_type inital_index; + std::vector::size_type current_index; sf::Sprite *sprite; static int side_length; }; using Cells = std::vector; - using RefCells = std::vector; sf::VertexArray rect_selection; Cells::size_type selection_index; Cells::size_type cells_on_width; // amount of cells on horizontal side of board Cells::size_type cells_on_height; // amount of cells on vertical side of board + Cells vec_field; sf::Texture global_texture; bool on_selection; diff --git a/main.cpp b/main.cpp index 20ccd15..f666eb8 100644 --- a/main.cpp +++ b/main.cpp @@ -1,7 +1,70 @@ #include "application.h" +#include "output_util.h" +#include +#include +#include -int main() +constexpr static int MIN_ARGC = 2; +constexpr static int MAX_ARGC = 4; + +static std::tuple error(const char* msg) +{ + std::cout << msg; + return {EXIT_FAILURE, 0, {}}; +} + +static std::tuple parseInput(int argc, char **argv) +{ + int splitting = -1; + std::string path; + + switch (argc) + { + default: + return error(output::NO_ARG_MSG); + + case MIN_ARGC: + // maybe --help + if (strcmp(argv[1], output::HELP_FLAG) == 0) + return error(output::HELP_MSG); + + /* HERE PARSE FILEPATH INSTEAD */ return error(output::NO_ARG_MSG); + break; + + case (MAX_ARGC - 1): + case MAX_ARGC: + // full stack + if (strcmp(argv[1], output::SPLITTING_FLAG) == 0) + { + if (std::isdigit(*argv[2])) + splitting = std::stoi(argv[2]); + + if (splitting < 1) + return error(output::SPLITTING_MSG); + + /* HERE PARSE FILEPATH INSTEAD */ return error(output::NO_ARG_MSG); + } + + return error(output::NO_ARG_MSG); + break; + } + + return {EXIT_SUCCESS, splitting, path}; +} + +int main(int argc, char **argv) { - Application game; - game.run(); + auto[ret_code, splitting, path] = parseInput(argc, argv); + + if (ret_code) // Error code is EXIT_FAILURE + return ret_code; + + Application app; + if (app.init(splitting, path)) + { + app.run(); + return EXIT_SUCCESS; + } + + return EXIT_FAILURE; } diff --git a/output_util.h b/output_util.h new file mode 100644 index 0000000..72cd93e --- /dev/null +++ b/output_util.h @@ -0,0 +1,21 @@ +#pragma once + +namespace output { + const char* HELP_FLAG = "--help"; + const char* SPLITTING_FLAG = "-s"; + + const char* NO_ARG_MSG = "Please at least provide a path to a target image. --help for more information.\n"; + const char* HELP_MSG = "usage: sliding-puzzle [-OPTIONS...] FILE-OR-DIRECTORY\n\n" + " Necessarily provide the latter variable as path to either a directory\n" + " which contains arts (one will be picked randomly) or a specific\n" + " image file of .bmp, .dds, .jpg, .png, .tga, or .psd format.\n\n" + " Options:\n" + " [-s num] Provide it if you want to explicitly define\n" + " qualifier for image slicing, it's counted\n" + " by the smallest side of given source texture.\n" + " Hence, if your image is square, the amount of tiles\n" + " will be num * num.\n"; + const char* SPLITTING_MSG = "-s should be given with a positive num as in [-s num].\n"; + + +} diff --git a/sliding-puzzle.pro b/sliding-puzzle.pro index e153abb..7f26da2 100644 --- a/sliding-puzzle.pro +++ b/sliding-puzzle.pro @@ -12,6 +12,7 @@ SOURCES += \ HEADERS += \ board.h \ filepath_util.h \ - application.h + application.h \ + output_util.h unix:LIBS += -lsfml-graphics -lsfml-audio -lsfml-window -lsfml-system