#pragma once #include #include #include #include namespace std { template <> struct hash { size_t operator()(const V2ST& v) const { size_t h1 = hash{}(v.x); size_t h2 = hash{}(v.y); return h1 ^ (h2 << 1); } }; } class Minesweeper : public Game { public: enum RunState { start, pause, resume, game_over, exit }; enum Difficulty { beginner, intermediate, expert }; public: Minesweeper(); ~Minesweeper() = default; bool Update(std::vector& events) override; void ProcessEventDuringPause(SDL_Event& event); void ProcessEventDuringResume(SDL_Event& event); private: void Reset(Difficulty Difficulty); void InitIsMineBitmap(int32_t mine_count); void InitAdjacentMineCounters(); void UncoverMines(); void Uncover(int32_t x, int32_t y); void ToggleFlag(int32_t x, int32_t y); bool IsCovered(int32_t x, int32_t y); bool IsFlagged(int32_t x, int32_t y); bool IsMine(int32_t x, int32_t y); V2F32 ScreenPosToViewPos(V2F32 screen_pos); private: void DrawBoard(); void DrawStartMenu(); void DrawPauseMenu(); void DrawGameOverMenu(); private: static constexpr int32_t MAX_MAP_HEIGHT = 32; static constexpr int32_t MAX_MAP_WIDTH = 32; static constexpr std::string_view s_FontFilepath = "./fonts/dejavu_ttf/DejaVuSans.ttf"; private: RunState m_run_state = start; Difficulty m_difficulty = beginner; float m_world_width = 4.0f; float m_world_height = 3.0f; int32_t m_grid_width; int32_t m_grid_height; V2F32 m_grid_pos; V2F32 m_cell_outer_size; V2F32 m_cell_inner_size; uint32_t m_is_covered_bitmap[MAX_MAP_HEIGHT] {}; uint32_t m_is_flagged_bitmap[MAX_MAP_HEIGHT] {}; uint32_t m_is_mine_bitmap[MAX_MAP_HEIGHT] {}; int32_t m_adjacent_mine_counts[MAX_MAP_WIDTH * MAX_MAP_HEIGHT] {}; Font m_font; std::array m_digit_glyphs; };