aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Kummerlaender2016-12-10 15:39:39 +0100
committerAdrian Kummerlaender2016-12-10 15:39:39 +0100
commitefe0aeed5f1854628df8bace645a072d569fe7b9 (patch)
tree290402d8cb55e6599cac6b452ef04c2ce26d485b
parent839e1335d9f58cd4b681163e14299efe1eec5eb1 (diff)
downloadtermlife-efe0aeed5f1854628df8bace645a072d569fe7b9.tar
termlife-efe0aeed5f1854628df8bace645a072d569fe7b9.tar.gz
termlife-efe0aeed5f1854628df8bace645a072d569fe7b9.tar.bz2
termlife-efe0aeed5f1854628df8bace645a072d569fe7b9.tar.lz
termlife-efe0aeed5f1854628df8bace645a072d569fe7b9.tar.xz
termlife-efe0aeed5f1854628df8bace645a072d569fe7b9.tar.zst
termlife-efe0aeed5f1854628df8bace645a072d569fe7b9.zip
Introduce `BoxIndicator` and `BoxTraverser` helper classes
`BoxIndicator` implements an indicator function for the world area. Together with `BoxTraverser` it is used to simplifiy action validation and area traversion.
-rw-r--r--src/box_indicator.h40
-rw-r--r--src/box_traverser.h26
-rw-r--r--src/world.h68
3 files changed, 97 insertions, 37 deletions
diff --git a/src/box_indicator.h b/src/box_indicator.h
new file mode 100644
index 0000000..db750e4
--- /dev/null
+++ b/src/box_indicator.h
@@ -0,0 +1,40 @@
+#ifndef LIFE_SRC_BOX_INDICATOR_
+#define LIFE_SRC_BOX_INDICATOR_
+
+namespace life {
+namespace util {
+
+class BoxIndicator {
+ public:
+ BoxIndicator(
+ const std::size_t offset_x,
+ const std::size_t offset_y,
+ const std::size_t size_x,
+ const std::size_t size_y):
+ a_x_{offset_x},
+ a_y_{offset_y},
+ b_x_{a_x_ + size_x},
+ b_y_{a_y_ + size_y} { }
+
+ BoxIndicator(const std::size_t size_x, const std::size_t size_y):
+ BoxIndicator(0, 0, size_x, size_y) { }
+
+ bool operator()(const std::size_t x, const std::size_t y) const {
+ return x >= this->a_x_
+ && x < this->b_x_
+ && y >= this->a_y_
+ && y < this->b_y_;
+ }
+
+ protected:
+ const std::size_t a_x_;
+ const std::size_t a_y_;
+ const std::size_t b_x_;
+ const std::size_t b_y_;
+
+};
+
+}
+}
+
+#endif // LIFE_SRC_BOX_INDICATOR_
diff --git a/src/box_traverser.h b/src/box_traverser.h
new file mode 100644
index 0000000..1bc0edd
--- /dev/null
+++ b/src/box_traverser.h
@@ -0,0 +1,26 @@
+#ifndef LIFE_SRC_BOX_TRAVERSER_
+#define LIFE_SRC_BOX_TRAVERSER_
+
+#include <functional>
+
+#include "box_indicator.h"
+
+namespace life {
+namespace util {
+
+struct BoxTraverser : public BoxIndicator {
+ using BoxIndicator::BoxIndicator;
+
+ void for_each(const std::function<void(std::size_t, std::size_t)> f) const {
+ for ( std::size_t x = this->a_x_; x < this->b_x_; x++ ) {
+ for ( std::size_t y = this->a_y_; y < this->b_y_; y++ ) {
+ f(x, y);
+ }
+ }
+ }
+};
+
+}
+}
+
+#endif // LIFE_SRC_BOX_TRAVERSER_
diff --git a/src/world.h b/src/world.h
index 72cc32f..b60c658 100644
--- a/src/world.h
+++ b/src/world.h
@@ -6,6 +6,8 @@
#include <tuple>
#include <cstdint>
+#include "box_traverser.h"
+
namespace life {
template<
@@ -14,19 +16,18 @@ template<
>
class World {
public:
- World() {
- for ( std::size_t j = 0; j < HEIGHT; j++ ) {
- for ( std::size_t i = 0; i < WIDTH; i++ ) {
- this->matrix_[j][i] = false;
- }
- }
+ static const std::size_t width = WIDTH;
+ static const std::size_t height = HEIGHT;
+
+ World():
+ area_(width, height) {
+ this->area_.for_each([&](std::size_t i, std::size_t j) {
+ this->matrix_[j][i] = false;
+ });
}
bool isLifeAt(std::ptrdiff_t x, std::ptrdiff_t y) const {
- if ( x >= 0 &&
- x < WIDTH &&
- y >= 0 &&
- y < HEIGHT ) {
+ if ( this->area_(x, y) ) {
return this->matrix_[y][x];
} else {
return false; // end of world is dead
@@ -69,19 +70,13 @@ class World {
}
void summonLifeAt(std::size_t x, std::size_t y) {
- if ( x >= 0 &&
- x < WIDTH &&
- y >= 0 &&
- y < HEIGHT ) {
+ if ( this->area_(x, y) ) {
this->matrix_[y][x] = true;
}
}
void extinguishLifeAt(std::size_t x, std::size_t y) {
- if ( x >= 0 &&
- x < WIDTH &&
- y >= 0 &&
- y < HEIGHT ) {
+ if ( this->area_(x, y) ) {
this->matrix_[y][x] = false;
}
}
@@ -91,25 +86,23 @@ class World {
std::stack<std::tuple<std::size_t, std::size_t, bool>> updates;
- for ( std::size_t j = 0; j < HEIGHT; j++ ) {
- for ( std::size_t i = 0; i < WIDTH; i++ ) {
- const std::uint8_t d = this->lifeDensityAt(i, j);
-
- if ( this->matrix_[j][i] ) {
- if ( d < 2 ) {
- updates.push(std::make_tuple(i, j, false));
- } else if ( d == 2 || d == 3 ) {
- updates.push(std::make_tuple(i, j, true));
- } else if ( d > 3 ) {
- updates.push(std::make_tuple(i, j, false));
- }
- } else {
- if ( d == 3 ) {
- updates.push(std::make_tuple(i, j, true));
- }
+ this->area_.for_each([&](std::size_t i, std::size_t j) {
+ const std::uint8_t d = this->lifeDensityAt(i, j);
+
+ if ( this->matrix_[j][i] ) {
+ if ( d < 2 ) {
+ updates.push(std::make_tuple(i, j, false));
+ } else if ( d == 2 || d == 3 ) {
+ updates.push(std::make_tuple(i, j, true));
+ } else if ( d > 3 ) {
+ updates.push(std::make_tuple(i, j, false));
+ }
+ } else {
+ if ( d == 3 ) {
+ updates.push(std::make_tuple(i, j, true));
}
}
- }
+ });
while ( !updates.empty() ) {
const auto& update = updates.top();
@@ -125,14 +118,15 @@ class World {
std::get<1>(update)
);
}
-
+
updates.pop();
}
}
private:
- std::size_t age_ = 0;
+ const util::BoxTraverser area_;
+ std::size_t age_ = 0;
std::array<std::array<bool, WIDTH>, HEIGHT> matrix_;
};