Add command line arguments support
This commit is contained in:
parent
ea4aa3c36c
commit
855eb9b5dc
|
@ -10,10 +10,10 @@ Application::Application() :
|
||||||
render_window({SCREEN_WIDTH, SCREEN_HEIGHT}, "Sliding Puzzle")
|
render_window({SCREEN_WIDTH, SCREEN_HEIGHT}, "Sliding Puzzle")
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool Application::init(int splitting, const std::string &path)
|
bool Application::init(const std::string &path, int splitting)
|
||||||
{
|
{
|
||||||
render_window.setFramerateLimit(60);
|
render_window.setFramerateLimit(60);
|
||||||
return board.init(splitting, path);
|
return board.init(path, splitting);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::run()
|
void Application::run()
|
||||||
|
|
|
@ -9,7 +9,7 @@ public:
|
||||||
explicit Application();
|
explicit Application();
|
||||||
|
|
||||||
// Init game
|
// Init game
|
||||||
bool init(int splitting, const std::string& path);
|
bool init(const std::string& path, int splitting);
|
||||||
|
|
||||||
// Launch game
|
// Launch game
|
||||||
void run();
|
void run();
|
||||||
|
|
|
@ -157,18 +157,18 @@ bool Board::isWinCondition() const
|
||||||
return std::all_of(vec_field.begin(), vec_field.end(), [](const Cell *cell){ return cell->current_index == cell->inital_index; });
|
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)
|
bool Board::init(const std::string& path, int splitting)
|
||||||
{
|
{
|
||||||
// PREPARING INITIAL BOARD STATE //
|
// PREPARING INITIAL BOARD STATE //
|
||||||
|
|
||||||
if (!global_texture.loadFromFile(path) )
|
if (!global_texture.loadFromFile(path) )
|
||||||
return EXIT_FAILURE;
|
return false;
|
||||||
|
|
||||||
if (splitting <= 1) // If it's 1, the game is already over
|
if (splitting <= 1) // If it's 1, the game is already over
|
||||||
{
|
{
|
||||||
sf::Sprite* sp = new sf::Sprite(global_texture);
|
sf::Sprite* sp = new sf::Sprite(global_texture);
|
||||||
vec_field.push_back(new Cell{0, 0, sp});
|
vec_field.push_back(new Cell{0, 0, sp});
|
||||||
return EXIT_SUCCESS; // why not
|
return true; // why not
|
||||||
}
|
}
|
||||||
|
|
||||||
const int width = global_texture.getSize().x;
|
const int width = global_texture.getSize().x;
|
||||||
|
@ -218,7 +218,7 @@ bool Board::init(int splitting, const std::string& path)
|
||||||
// Set initial position of cursor
|
// Set initial position of cursor
|
||||||
setSelectionVertex(selection_index);
|
setSelectionVertex(selection_index);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Board::Cell::side_length = 0;
|
int Board::Cell::side_length = 0;
|
||||||
|
|
2
board.h
2
board.h
|
@ -39,7 +39,7 @@ public:
|
||||||
bool isWinCondition() const;
|
bool isWinCondition() const;
|
||||||
|
|
||||||
// Set play image
|
// Set play image
|
||||||
bool init(int splitting, const std::string& path);
|
bool init(const std::string& path, int splitting);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,19 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
static std::tuple<std::filesystem::path, std::filesystem::file_status, size_t> file_info(const std::filesystem::directory_entry& entry)
|
namespace filepath
|
||||||
{
|
{
|
||||||
const auto fs (std::filesystem::status(entry));
|
static std::tuple<std::filesystem::path, std::filesystem::file_status> getFileInfo(const std::filesystem::directory_entry& entry)
|
||||||
return {entry.path(),
|
{
|
||||||
fs,
|
const auto file_status (std::filesystem::status(entry));
|
||||||
std::filesystem::is_regular_file(fs) ? std::filesystem::file_size(entry.path()) : 0u};
|
return {entry.path(), file_status};
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool endsWith(const std::string& string, const std::string& ending)
|
||||||
|
{
|
||||||
|
if (ending.size() > string.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return std::equal(ending.rbegin(), ending.rend(), string.rbegin());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
101
main.cpp
101
main.cpp
|
@ -1,38 +1,111 @@
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
#include "output_util.h"
|
#include "output_util.h"
|
||||||
|
#include "filepath_util.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
constexpr static int MIN_ARGC = 2;
|
/////////////////////////////////////////////////////////////////////////
|
||||||
constexpr static int MAX_ARGC = 4;
|
|
||||||
|
static constexpr int NO_ARGC = 1;
|
||||||
|
static constexpr int MIN_ARGC = 2;
|
||||||
|
static constexpr int MAX_ARGC = 4;
|
||||||
|
static constexpr int DEFAULT_SPLITTING = 5;
|
||||||
|
static const std::string DEFAULT_PATH = "."; // current folder, I guess
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static std::tuple<int, int, std::string> error(const char* msg)
|
static std::tuple<int, int, std::string> error(const char* msg)
|
||||||
{
|
{
|
||||||
std::cout << msg;
|
std::cout << msg;
|
||||||
return {EXIT_FAILURE, 0, {}};
|
return {EXIT_FAILURE, -1, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::tuple<int, std::string> parsePath(const std::string &argv)
|
||||||
|
{
|
||||||
|
std::filesystem::path path(argv);
|
||||||
|
if (!std::filesystem::exists(path))
|
||||||
|
{
|
||||||
|
std::cout << "Path " << path << " does not exist.\n";
|
||||||
|
return {EXIT_FAILURE, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maybe user chose a specific image, not a folder
|
||||||
|
if (std::filesystem::is_regular_file(path))
|
||||||
|
return {EXIT_SUCCESS, path.string()};
|
||||||
|
|
||||||
|
// So... it is a folder
|
||||||
|
// Creating a vector of everything in the given directory
|
||||||
|
std::vector<std::tuple<std::filesystem::path, std::filesystem::file_status>> dir_items;
|
||||||
|
std::transform(std::filesystem::directory_iterator(path), {}, std::back_inserter(dir_items), filepath::getFileInfo);
|
||||||
|
|
||||||
|
std::set<std::string> allowed_ext = {".bmp", ".dds", ".jpg", ".png", ".tga", ".psd"};
|
||||||
|
|
||||||
|
// Now getting images
|
||||||
|
std::vector<std::string> dir_image_items;
|
||||||
|
for (const auto &[local_path, status] : dir_items)
|
||||||
|
{
|
||||||
|
const std::string str_path = local_path.string();
|
||||||
|
if (std::filesystem::is_regular_file(local_path) &&
|
||||||
|
std::any_of(allowed_ext.begin(), allowed_ext.end(), [&](const std::string& e) { return filepath::endsWith(str_path, e); }))
|
||||||
|
{
|
||||||
|
dir_image_items.emplace_back(str_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir_image_items.empty())
|
||||||
|
{
|
||||||
|
std::cout << "No images found at " << path << "\n --help for more information.\n";
|
||||||
|
return {EXIT_FAILURE, {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Loading random image file from " << path << "\n";
|
||||||
|
srand(static_cast<unsigned int>(time(nullptr)));
|
||||||
|
return {EXIT_SUCCESS, dir_image_items[rand() & (dir_image_items.size() - 1)]};
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::tuple<int, int, std::string> parseInput(int argc, char **argv)
|
static std::tuple<int, int, std::string> parseInput(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int splitting = -1;
|
int splitting = DEFAULT_SPLITTING;
|
||||||
std::string path;
|
std::string path = DEFAULT_PATH;
|
||||||
|
|
||||||
switch (argc)
|
switch (argc)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
return error(output::NO_ARG_MSG);
|
return error(output::NO_ARG_MSG);
|
||||||
|
|
||||||
|
case NO_ARGC:
|
||||||
|
{
|
||||||
|
// Just launch the application with default parameters
|
||||||
|
std::cout << "No arguments given. Launching at \"" + DEFAULT_PATH + "\" with splitting " + std::to_string(DEFAULT_SPLITTING) + "\n";
|
||||||
|
const auto &[ret_code, ret_path] = parsePath(DEFAULT_PATH);
|
||||||
|
|
||||||
|
if (ret_code)
|
||||||
|
return error(output::IMG_FAIL_MSG);
|
||||||
|
|
||||||
|
path = ret_path;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case MIN_ARGC:
|
case MIN_ARGC:
|
||||||
|
{
|
||||||
// maybe --help
|
// maybe --help
|
||||||
if (strcmp(argv[1], output::HELP_FLAG) == 0)
|
if (strcmp(argv[1], output::HELP_FLAG) == 0)
|
||||||
return error(output::HELP_MSG);
|
return error(output::HELP_MSG);
|
||||||
|
|
||||||
/* HERE PARSE FILEPATH INSTEAD */ return error(output::NO_ARG_MSG);
|
const auto &[ret_code, ret_path] = parsePath(argv[1]);
|
||||||
|
|
||||||
|
if (ret_code)
|
||||||
|
return error(output::IMG_FAIL_MSG);
|
||||||
|
|
||||||
|
path = ret_path;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case (MAX_ARGC - 1):
|
case (MAX_ARGC - 1):
|
||||||
case MAX_ARGC:
|
case MAX_ARGC:
|
||||||
|
{
|
||||||
// full stack
|
// full stack
|
||||||
if (strcmp(argv[1], output::SPLITTING_FLAG) == 0)
|
if (strcmp(argv[1], output::SPLITTING_FLAG) == 0)
|
||||||
{
|
{
|
||||||
|
@ -42,25 +115,31 @@ static std::tuple<int, int, std::string> parseInput(int argc, char **argv)
|
||||||
if (splitting < 1)
|
if (splitting < 1)
|
||||||
return error(output::SPLITTING_MSG);
|
return error(output::SPLITTING_MSG);
|
||||||
|
|
||||||
/* HERE PARSE FILEPATH INSTEAD */ return error(output::NO_ARG_MSG);
|
const auto &[ret_code, ret_path] = parsePath(argv[3]);
|
||||||
}
|
|
||||||
|
|
||||||
return error(output::NO_ARG_MSG);
|
if (ret_code)
|
||||||
|
return error(output::IMG_FAIL_MSG);
|
||||||
|
|
||||||
|
path = ret_path;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {EXIT_SUCCESS, splitting, path};
|
return {EXIT_SUCCESS, splitting, path};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
auto[ret_code, splitting, path] = parseInput(argc, argv);
|
const auto&[ret_code, splitting, path] = parseInput(argc, argv);
|
||||||
|
|
||||||
if (ret_code) // Error code is EXIT_FAILURE
|
if (ret_code) // Error code is EXIT_FAILURE
|
||||||
return ret_code;
|
return ret_code;
|
||||||
|
|
||||||
Application app;
|
Application app;
|
||||||
if (app.init(splitting, path))
|
if (app.init(path, splitting))
|
||||||
{
|
{
|
||||||
app.run();
|
app.run();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace output {
|
namespace output
|
||||||
|
{
|
||||||
const char* HELP_FLAG = "--help";
|
const char* HELP_FLAG = "--help";
|
||||||
const char* SPLITTING_FLAG = "-s";
|
const char* SPLITTING_FLAG = "-s";
|
||||||
|
|
||||||
|
@ -16,6 +17,5 @@ namespace output {
|
||||||
" Hence, if your image is square, the amount of tiles\n"
|
" Hence, if your image is square, the amount of tiles\n"
|
||||||
" will be num * num.\n";
|
" will be num * num.\n";
|
||||||
const char* SPLITTING_MSG = "-s should be given with a positive num as in [-s num].\n";
|
const char* SPLITTING_MSG = "-s should be given with a positive num as in [-s num].\n";
|
||||||
|
const char* IMG_FAIL_MSG = "Couldn't load image from given path.\n";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue