From efe0aeed5f1854628df8bace645a072d569fe7b9 Mon Sep 17 00:00:00 2001 From: Adrian Kummerlaender Date: Sat, 10 Dec 2016 15:39:39 +0100 Subject: 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. --- src/box_indicator.h | 40 +++++++++++++++++++++++++++++++ src/box_traverser.h | 26 ++++++++++++++++++++ src/world.h | 68 ++++++++++++++++++++++++----------------------------- 3 files changed, 97 insertions(+), 37 deletions(-) create mode 100644 src/box_indicator.h create mode 100644 src/box_traverser.h 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 + +#include "box_indicator.h" + +namespace life { +namespace util { + +struct BoxTraverser : public BoxIndicator { + using BoxIndicator::BoxIndicator; + + void for_each(const std::function 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 #include +#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> 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, HEIGHT> matrix_; }; -- cgit v1.2.3