-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfield.cpp
More file actions
130 lines (108 loc) · 3.1 KB
/
Copy pathfield.cpp
File metadata and controls
130 lines (108 loc) · 3.1 KB
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
#include "field.h"
#include <random>
#include <cassert>
#include <QTimer>
#include <QDebug>
#include "snake.h"
#ifdef NDEBUG
#define SEED static_cast<std::default_random_engine::result_type>(time(nullptr))
#else
#define SEED std::default_random_engine::default_seed
#endif //NDEBUG
Field::Field(size_t width, size_t height)
: _width(width)
, _height(height)
{
_field.resize(height, std::vector<Cell>(width));
}
size_t Field::width() const
{
return _width;
}
size_t Field::height() const
{
return _height;
}
const Cell &Field::get(size_t x, size_t y) const { return _field[y][x]; }
const Cell &Field::get(Coordinates coordinates) const { return get(size_t(coordinates.x), size_t(coordinates.y)); }
void Field::set(size_t x, size_t y, Cell cell)
{
if (_field[y][x] != cell)
{
Coordinates coordinates(x, y);
if (_recordingChanges) _changedCells.insert(coordinates);
if (cell.isEmpty())
_nonEmptyCells.erase(coordinates);
else
_nonEmptyCells.insert(coordinates);
}
_field[y][x] = cell;
}
void Field::set(Coordinates coordinates, Cell cell)
{
set(size_t(coordinates.x), size_t(coordinates.y), cell);
}
Coordinates Field::getFreeCells(size_t count, Orientation orientation)
{
const Direction dir = orientation == Orientation::Horizontal ? Direction::East : Direction::South;
static std::default_random_engine engine(SEED);
std::uniform_int_distribution<int> xDistr(0, static_cast<int>(_width) - 1);
std::uniform_int_distribution<int> yDistr(0, static_cast<int>(_height) - 1);
int maxTries = 100;
while (maxTries--)
{
Coordinates coordinates;
coordinates.x = xDistr(engine);
coordinates.y = yDistr(engine);
// check
bool onlyFree = true;
for (int i = 0; i < int(count) && onlyFree; ++i)
{
auto currentCoordinates = coordinates.shift(dir, i);
onlyFree &= validatePosition(currentCoordinates)
&& get(currentCoordinates).isEmpty();
}
if (onlyFree)
return coordinates;
}
return {};
}
Coordinates Field::nextPosition(Coordinates currentPosition, Direction direction) const
{
auto nxt = currentPosition.shift(direction, 1);
return validatePosition(nxt) ? nxt : currentPosition;
}
unsigned int Field::applesCount() const
{
return _applesCount;
}
void Field::placeApple(Coordinates coordinates)
{
assert(get(coordinates).isEmpty());
set(coordinates, CellType::Apple);
++_applesCount;
}
void Field::consumeApple()
{
assert(_applesCount > 0);
--_applesCount;
}
void Field::startRecordingChangedCells()
{
if (_recordingChanges) return;
_recordingChanges = true;
_changedCells.clear();
}
std::set<Coordinates> Field::stopRecordingChangedCells()
{
_recordingChanges = false;
return _changedCells;
}
std::set<Coordinates> Field::getNonEmptyCells() const
{
return _nonEmptyCells;
}
bool Field::validatePosition(Coordinates pos) const
{
return pos.x >= 0 && pos.x < static_cast<int>(_width) && pos.y >= 0 && pos.y < static_cast<int>(_height);
}