-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMap.hpp
168 lines (137 loc) · 4.48 KB
/
Map.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#pragma once
#include "Tile.hpp"
#include <vector>
#include <string>
#include <SFML/Graphics.hpp>
#include <bitset>
// View map interface
class IMapView
{
public:
// Call when tile is changed
virtual void notify(int y, int x) = 0;
// Call only when map is just generated or map size is changed
virtual void reload() = 0;
};
/*
Main map class. This represent all map logic (generate minesweeper map, reveal tile, mark tile, double click reveal tile etc)
*/
class Map
{
IMapView * view;
std::vector<std::vector<Tile>> map; // Map vector. This have Y(X) size 2 more than sizeY(sizeX) (to take care of border check)
int sizeX, sizeY;
// 4KB for one row
std::vector<std::bitset<4096>> revealIterativeMark;
int mineTiles; // Number of mines
int markedTiles; // Number of marked tiles
int hiddenTiles; // Number of hidden tiles
sf::Clock gameTimer;
int bombsAround(int y, int x); // Return number of bombs around tile.
// If that tile is actually a bomb this will return Tile::MINE
void checkWin(); // Set the win boolean to true if map is resolved
void revealIterative(int y, int x); // Iterative reveal. Call only when user is clicked at the empty tile (no bombs around)
void setStatus(int y, int x, Tile::Status status); // Call everytime when you must change status of mine
// and View must be notified (this notify the view)
void revealAllBombs(); // Reveal all bombs. Call only when user lose or win
bool win;
bool lose;
float lastGameTime;
bool gameStart = false;
public:
Map(int sizeY, int sizeX, int mines); // Notice! std::vector<std::vector<Tile>> Y(X) size is 2 more than sizeY(sizeX).
// This is to simplify border check (bordes will be equal Tile::BORDER)
void handleView(IMapView * view); // Handle the Interface Map View (needed for notify view)
void generateMap(); // Generate random map
void generateMap(int seed); // Generate map from seed
void reveal(int y, int x); // Reveal the tile, and take care of the all special cases.
void revealDoubleClick(int y, int x); // Reveal the tiles when user click both mouse
void mark(int y, int x); // Mark or unmark the tile (set proper Mark Status)
bool isLose(); // Return true if player lose
bool isWin(); // Return true if player won
std::string toString(); // Convert map to the string (usefull for std::cout debug)
int getMineCount(); // Return mine number in the map
int getMineUpperbound(); // Return mine upper bound
int getSizeX(); // Return sizeX
int getSizeY(); // Return sizeY
void setSize(int y, int x, int mineNumber); // Change map size and number of bombs, regenrate map and call view reload
void setMineNumber(int number);
int getValue(int y, int x); // Get value of tile (bombs around, or -1 if tile is a mine)
int getStatus(int y, int x); // Get status of tile (if tile is hidden, marked or revealed)
int getMarkStatus(int y, int x); // Get status of mark (if mark is correct or wrong)
float getGameTime();
int getRemainMines();
};
// INLINE METHODS
///..............
inline void Map::checkWin()
{
win = (hiddenTiles == mineTiles) && !lose;
}
inline void Map::setStatus(int y, int x, Tile::Status status)
{
if (y < 1 || x < 1 || x > sizeX + 1 || y > sizeY + 1)
throw std::out_of_range("Out of range");
map[y][x].setStatus(status);
view->notify(y - 1, x - 1);
}
inline void Map::generateMap()
{
generateMap(std::rand());
}
inline void Map::handleView(IMapView * view)
{
this->view = view;
}
inline bool Map::isLose()
{
return lose;
}
inline bool Map::isWin()
{
return win;
}
inline int Map::getMineCount()
{
return mineTiles;
}
inline int Map::getSizeX()
{
return sizeX;
}
inline int Map::getSizeY()
{
return sizeY;
}
inline int Map::getValue(int y, int x)
{
if (y < -1 || x < -1 || y > sizeY || x > sizeX)
throw std::out_of_range("Out of range");
return map[y + 1][x + 1];
}
inline int Map::getStatus(int y, int x)
{
if (y < -1 || x < -1 || y > sizeY || x > sizeX)
throw std::out_of_range("Out of range");
return map[y + 1][x + 1].getStatus();
}
inline int Map::getMarkStatus(int y, int x)
{
if (y < -1 || x < -1 || y > sizeY || x > sizeX)
throw std::out_of_range("Out of range");
return map[y + 1][x + 1].getMarkStatus();
}
inline int Map::getMineUpperbound()
{
return sizeX * sizeY - 1;
}
inline float Map::getGameTime()
{
if (win || lose || !gameStart)
return lastGameTime;
return gameTimer.getElapsedTime().asSeconds();
}
inline int Map::getRemainMines()
{
return mineTiles - markedTiles;
}