Skip to content

Commit

Permalink
feat: save system
Browse files Browse the repository at this point in the history
  • Loading branch information
Billocap committed Feb 3, 2024
1 parent 9e9e8bc commit e5df70f
Show file tree
Hide file tree
Showing 12 changed files with 216 additions and 10 deletions.
4 changes: 4 additions & 0 deletions include/game/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <grid/grid.h>
#include <menu/menu.h>
#include <io.h>

#include "events.h"

Expand Down Expand Up @@ -56,6 +57,9 @@ namespace std
void add_menu(string name, Menu *menu);
void go_to(string name);
Menu *get_menu();
Menu *get_menu(string name);
void load_data();
void save_data();
};
}

Expand Down
4 changes: 4 additions & 0 deletions include/grid/grid.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,14 @@ namespace std
vector<GridCell *> get_neighbors(int x, int y);
void place_bombs(int amount);
void reveal();
void reveal_at(int x, int y);
void reveal_all(bool won);
void flag();
void flag_at(int x, int y);
void focus();
void check_state();
string to_save();
void from_save(string data);

private:
/// @brief Current cell in focus by the pointer.
Expand Down
6 changes: 3 additions & 3 deletions include/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@

namespace std
{
// #region FileIO

vector<string> read_file(string path);

// #endregion FileIO
string read_save(string path);
void write_save(string path, string data);
void delete_save(string path);
}

#endif
1 change: 1 addition & 0 deletions include/menu/menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ namespace std
Menu(TextBanner *banner);

void add_option(string label, IMenuAction *action);
void remove_option(int id);
void pointer_up();
void pointer_down();
void execute();
Expand Down
12 changes: 12 additions & 0 deletions include/menu/opts.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ namespace std
void execute();
};

/// @brief Represents a menu option that loads previous saves.
class ContinueOption : public IMenuAction
{
public:
ContinueOption(Game *game);

void execute();

private:
Game *game;
};

/// @brief Represents a menu option that exits the game.
class ExitOption : public IMenuAction
{
Expand Down
2 changes: 1 addition & 1 deletion include/menu/render.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
#include "menu.h"

int render_option(std::MenuOption *option, std::RenderEvent *event);
int render_menu(std::Menu *menu, std::RenderEvent *event);
void render_menu(std::Menu *menu, std::RenderEvent *event);

#endif
40 changes: 40 additions & 0 deletions lib/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ namespace std
}
else
{
this->game->save_data();

this->game->get_grid()->on_key_press->notify(event);
}
}
Expand All @@ -73,9 +75,13 @@ namespace std

void GridStateHandler::notify(GridStateEvent *event)
{
delete_save("save");

this->game->pause();
this->game->finished = true;
this->game->won = event->won;

this->game->get_menu("main")->remove_option(0);
}

// #endregion Events
Expand Down Expand Up @@ -160,10 +166,39 @@ namespace std
break;
}

this->save_data();

this->grid->state->subscribe(this->on_grid_state);
this->go_to("game");
}

/// @brief Creates a new game from a previous save file.
void Game::load_data()
{
this->resume();

this->finished = false;
this->won = false;

this->grid = new Grid(8, 8);

auto data = read_save("save");

this->grid->from_save(data);

this->grid->state->subscribe(this->on_grid_state);
this->go_to("game");
}

/// @brief Saves the game by overwriting previous save.
void Game::save_data()
{
auto data = this->grid->to_save();

if (data.length() > 0)
write_save("save", data);
}

/// @brief Returns the main grid.
/// @return A pointer to the main grid.
Grid *Game::get_grid()
Expand Down Expand Up @@ -196,6 +231,11 @@ namespace std
return this->menus[this->screen];
}

Menu *Game::get_menu(string name)
{
return this->menus[name];
}

// #endregion Game
}

Expand Down
87 changes: 87 additions & 0 deletions lib/grid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,93 @@ namespace std
this->focused->is_focused = true;
}

void Grid::flag_at(int x, int y)
{
this->get_cell(x, y)->flag();
}

void Grid::reveal_at(int x, int y)
{
this->get_cell(x, y)->reveal();
}

string Grid::to_save()
{
string data;

data += this->width;
data += this->height;

for (auto y = 0; y < this->height; y++)
{
for (auto x = 0; x < this->width; x++)
{
auto cell = this->get_cell(x, y);

auto state = (cell->has_bomb << 2) | (cell->has_flag << 1) | cell->is_revealed;

data += state + 8;
}
}

return data;
}

void Grid::from_save(string data)
{
int width = data[0];
int height = data[1];

this->width = width;
this->height = height;

this->cells.clear();
this->bombs.clear();
this->safe_cells.clear();

for (auto y = 0; y < height; y++)
{
for (auto x = 0; x < width; x++)
{
auto c = new GridCell(x, y);

this->cells.push_back(c);
}
}

for (auto y = 0; y < height; y++)
{
for (auto x = 0; x < width; x++)
{
int state = data[2 + y * width + x];

if (state & 4)
this->place_bomb_at(x, y);

if (state & 2)
{
this->flag_at(x, y);
}
else if (state & 1)
{
this->reveal_at(x, y);
}
}
}

for (auto cell : this->cells)
{
if (cell->has_bomb)
{
this->bombs.push_back(cell);
}
else
{
this->safe_cells.push_back(cell);
}
}
}

// #endregion Grid
}

Expand Down
39 changes: 36 additions & 3 deletions lib/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace std
{
// #region FileIO

/// @brief Reads a basic text file.
/// @param path File path.
/// @return A vector containing all of the lines in the file.
Expand All @@ -27,5 +25,40 @@ namespace std
return data;
}

// #endregion FileIO
string read_save(string path)
{
ifstream file(path);
string data;

if (file.is_open())
{
string line;

while (getline(file, line))
{
data += line;
}

file.close();
}

return data;
};

void write_save(string path, string data)
{
ofstream file(path);

if (file.is_open())
{
file << data;

file.close();
}
}

void delete_save(string path)
{
remove(path.c_str());
}
}
11 changes: 8 additions & 3 deletions lib/menu/menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ namespace std
this->options.push_back(new MenuOption(label, action));
}

void Menu::remove_option(int id)
{
auto it = this->options.begin() + id;

this->options.erase(it);
}

void Menu::pointer_up()
{
this->options[this->pointer]->focused = false;
Expand Down Expand Up @@ -128,7 +135,7 @@ int render_option(std::MenuOption *option, std::RenderEvent *event)
return event->y + 1;
}

int render_menu(std::Menu *menu, std::RenderEvent *event)
void render_menu(std::Menu *menu, std::RenderEvent *event)
{
init_pair(1, COLOR_WHITE, COLOR_BLACK);

Expand Down Expand Up @@ -159,6 +166,4 @@ int render_menu(std::Menu *menu, std::RenderEvent *event)
printw("Gabriel Quintino");
attron(COLOR_PAIR(1));
}

return y + 1;
}
14 changes: 14 additions & 0 deletions lib/menu/opts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@ namespace std

// #endregion ExitOption

// #region ContinueOption

ContinueOption::ContinueOption(Game *game)
{
this->game = game;
}

void ContinueOption::execute()
{
this->game->load_data();
}

// #endregion ContinueOption

// #region GoToOption

GoToOption::GoToOption(Game *game, string name) : IMenuAction()
Expand Down
6 changes: 6 additions & 0 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
#include <ncursesw/ncurses.h>
#include <string>
#include <iostream>
#include <filesystem>
#include <fstream>

#include <events/kbd.h>
#include <events/render.h>
#include <game/game.h>
#include <grid/grid.h>
#include <menu/menu.h>
#include <menu/opts.h>
#include <ui/ui.h>
Expand Down Expand Up @@ -34,6 +37,9 @@ int main()

Menu menu(&title_banner);

if (filesystem::exists("save"))
menu.add_option("Continue", new ContinueOption(&main_game));

menu.add_option("New game", new GoToOption(&main_game, "diff"));
menu.add_option("Exit", new ExitOption(&main_game));

Expand Down

0 comments on commit e5df70f

Please sign in to comment.