diff options
-rw-r--r-- | README.md | 43 | ||||
-rw-r--r-- | image_converter/converter.c | 4 | ||||
-rw-r--r-- | img_handler.cpp | 27 | ||||
-rw-r--r-- | img_handler.hpp | 9 | ||||
-rw-r--r-- | main.cpp | 18 | ||||
-rw-r--r-- | puzzle.hpp | 12 | ||||
-rw-r--r-- | puzzle.png | bin | 0 -> 114081 bytes | |||
-rw-r--r-- | solution_algorithm.cpp | 1 | ||||
-rw-r--r-- | solution_algorithm.hpp | 4 |
9 files changed, 96 insertions, 22 deletions
@@ -1,2 +1,43 @@ -<a href="https://scratko.xyz/games/puzzle.zip" target="_blank">Download Windows +# Picture puzzle + +<img src="puzzle.png" /> + +A desktop game similar to the standard widget in windows 7. The game is written +in C++ (including C++17 standard). FLTK was used as a graphics library. This +library is not as heavy as Qt, and allows to quickly create an application with +graphical widgets. + +The essence of the game should be clear: to collect the image in its original +form, moving one puzzle per move. + +The application has the following features: + +- *upload your image in any format and resolution. The program itself will + resize, cut into puzzles, create the appropriate directory and save them in + it.* + +- *showing the complete solution of the puzzle using the optimization algorithm + A\*.* + +- *the game is distributed in a single executable file by embedding the original + standard image (toucan image) in the executable file. The image data is stored + in an array in an object file (resources.o)* + +- *support for \*unix and Windows platforms* + +## Building + +For \*nix platform, you need to install FLTK library and then do the following: + +``` +git clone https://git.scratko.xyz/picture-puzzle +cd picture-puzzle +make +./main +``` + +## For Windows platform + +The built executable file (under x86_64) is available at the link: <a +href="https://scratko.xyz/games/puzzle.exe" target="_blank">Download Windows version</a> diff --git a/image_converter/converter.c b/image_converter/converter.c index 4252e71..cccb9ad 100644 --- a/image_converter/converter.c +++ b/image_converter/converter.c @@ -1,3 +1,7 @@ +/* + * Embedding standard image data into a file resources.cpp + */ + #include <stdlib.h> #include <stdio.h> #include <string.h> diff --git a/img_handler.cpp b/img_handler.cpp index 921f639..6c62728 100644 --- a/img_handler.cpp +++ b/img_handler.cpp @@ -1,3 +1,8 @@ +/* + * Processing of images uploaded by the user + * (resizing, cropping, saving) + */ + #include "img_handler.hpp" #include "puzzle.hpp" @@ -14,7 +19,7 @@ #include <iostream> #include <string> -ImageHandler::ImageHandler(const char *p) : path_to_file(p) { +ImageHandler::ImageHandler(const char *p) : source_path(p) { img_data = nullptr; resized_data = nullptr; /* @@ -25,24 +30,24 @@ ImageHandler::ImageHandler(const char *p) : path_to_file(p) { std::filesystem::create_directory(res_path); #if defined(_WIN32) - auto it = path_to_file.find_last_of('\\'); + auto it = source_path.find_last_of('\\'); #else - auto it = path_to_file.find_last_of('/'); + auto it = source_path.find_last_of('/'); #endif - std::string file_name = path_to_file.substr(it + 1); + std::string file_name = source_path.substr(it + 1); std::string fn_withot_ext = file_name.substr(0, file_name.find_first_of('.')); #if defined(_WIN32) - path_to_save = "resources\\" + fn_withot_ext + "\\"; + destination_directory = "resources\\" + fn_withot_ext + "\\"; #else - path_to_save = "resources/" + fn_withot_ext + '/'; + destination_directory = "resources/" + fn_withot_ext + '/'; #endif - std::filesystem::create_directory(path_to_save); + std::filesystem::create_directory(destination_directory); } void ImageHandler::load_img() { - img_data = stbi_load(path_to_file.c_str(), &in_width, &in_height, + img_data = stbi_load(source_path.c_str(), &in_width, &in_height, &channel, 0); } @@ -62,11 +67,11 @@ void ImageHandler::save_img() for(j = 0; j < puzzles_per_side; ++j, ++k) { x = i * puzzle_size; y = j * puzzle_size; - std::string tmp_name = - path_to_save + + std::string tmp_path = + destination_directory + std::to_string(k / puzzles_per_side) + std::to_string(k % puzzles_per_side) + ".png"; - stbi_write_png(tmp_name.c_str(), puzzle_size, puzzle_size, channel, + stbi_write_png(tmp_path.c_str(), puzzle_size, puzzle_size, channel, resized_data + channel * (x + y * width), width * channel); } diff --git a/img_handler.hpp b/img_handler.hpp index 8c5754a..cb53807 100644 --- a/img_handler.hpp +++ b/img_handler.hpp @@ -1,3 +1,8 @@ +/* + * Processing of images uploaded by the user + * (resizing, cropping, saving) + */ + #ifndef IMG_HANDLER_HPP_SENTRY #define IMG_HANDLER_HPP_SENTRY @@ -12,8 +17,8 @@ class ImageHandler { int channel; int in_width; int in_height; - std::string path_to_file; - std::string path_to_save; + std::string source_path; + std::string destination_directory; unsigned char *img_data; unsigned char *resized_data; public: @@ -9,10 +9,26 @@ #include "gameplay.hpp" #include "menu_callbacks.hpp" +class MainWindow : public Fl_Window { +public: + MainWindow(int w, int h, const char *title) : Fl_Window(w, h, title) {} + /* + * Ending program by esc key while the computer is solving a puzzle + */ + int handle(int event) { + if(event == FL_KEYDOWN && Fl::event_length() != 0 && + Fl::event_key() == FL_Escape) + { + exit(0); + } + return Fl_Window::handle(event); + } +}; + int main() { srand(time(nullptr)); - Fl_Window *win = new Fl_Window(320, 355, "Picture puzzle"); + MainWindow *win = new MainWindow(320, 355, "Picture puzzle"); GameParams *params = GameParams::SetUpParams(win); Fl_Sys_Menu_Bar *sys_bar = new Fl_Sys_Menu_Bar(0, 0, 355, 20, nullptr); sys_bar->add("&File/&New game", nullptr, new_game_callback, params); @@ -43,6 +43,9 @@ private: coordinates empty_box; std::vector<std::unique_ptr<Puzzle>> puzzles; Fl_Window *win; + /* + * selecting the current directory where the user image is stored + */ std::string cur_directory; GameParams(Fl_Window *a_win = nullptr) @@ -55,11 +58,6 @@ private: void CreateNewPuzzles(); void SelectRandomPicture(); Fl_PNG_Image *LoadPictureParts(std::unique_ptr<Puzzle>& tmp_puzzle); - - friend class PuzzleGame; - friend class ASearch; - friend void press_button_callback(Fl_Widget*, void*); - friend void solve_problem_callback(Fl_Widget*, void*); public: void SetXYEmptyBox(int x, int y) { empty_box.x = x; empty_box. y = y; } coordinates GetXYEmptyBox() { return empty_box; } @@ -70,6 +68,10 @@ public: gi->CalculateStandardPuzzlePos(); return gi; } + friend class PuzzleGame; + friend class ASearch; + friend void press_button_callback(Fl_Widget*, void*); + friend void solve_problem_callback(Fl_Widget*, void*); }; #endif diff --git a/puzzle.png b/puzzle.png Binary files differnew file mode 100644 index 0000000..30dd62b --- /dev/null +++ b/puzzle.png diff --git a/solution_algorithm.cpp b/solution_algorithm.cpp index f0b7861..d96374b 100644 --- a/solution_algorithm.cpp +++ b/solution_algorithm.cpp @@ -178,6 +178,7 @@ void ASearch::ShowSolution(Node *goal) (*puzzle_pos)->position(goal->state[i].x, goal->state[i].y); gp->win->redraw(); Fl::flush(); + Fl::check(); usleep(40000); } } diff --git a/solution_algorithm.hpp b/solution_algorithm.hpp index 440264b..f182aa8 100644 --- a/solution_algorithm.hpp +++ b/solution_algorithm.hpp @@ -16,8 +16,6 @@ private: Node *parent_p; int depth; int evaluation; - friend struct std::hash<std::shared_ptr<Node>>; - friend class ASearch; public: Node(std::vector<GameParams::coordinates>& s, Node *p = nullptr, int d = 0, int e = 0) @@ -30,6 +28,8 @@ public: return first->evaluation > second->evaluation; } }; + friend struct std::hash<std::shared_ptr<Node>>; + friend class ASearch; }; template<> |