From a137e31ba00510ca8d0bd033c043301a54cbcc59 Mon Sep 17 00:00:00 2001 From: Joshua Moerman Date: Wed, 5 Feb 2014 14:33:55 +0100 Subject: [PATCH] Adds a random generator. Fixes some warnings. Adds some comments --- include/clusters.hpp | 10 +++++++++- include/field.hpp | 32 +++++++++++++++++++++++++------- include/generator.hpp | 21 +++++++++++++++++++++ include/solver.hpp | 10 ---------- main.cpp | 32 +++++--------------------------- 5 files changed, 60 insertions(+), 45 deletions(-) create mode 100644 include/generator.hpp diff --git a/include/clusters.hpp b/include/clusters.hpp index b0d5c23..da5b895 100644 --- a/include/clusters.hpp +++ b/include/clusters.hpp @@ -45,4 +45,12 @@ auto all_clusters(Field const & field){ return ret; } -#undef Set +template +auto make_empty(Field field, Cluster const & c){ + using namespace std; + for(auto&& p : c){ + field.get(p) = 0; + } + field.collapse(); + return field; +} diff --git a/include/field.hpp b/include/field.hpp index c2fda4d..0685fc6 100644 --- a/include/field.hpp +++ b/include/field.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -23,7 +24,7 @@ struct small_vector{ // Position {0,0} is bottom left. // Position {W-1, H-1} is top right. -template +template struct Field{ using Position = std::pair; @@ -31,15 +32,20 @@ struct Field{ std::copy(std::begin(g), std::end(g), std::begin(grid)); } + //! \brief Returns true if p represents a valid position auto valid(Position const & p) const { return p.first >= 0 && p.second >= 0 && p.first < W && p.second < H; } + //! \brief Returns true if p represents an empty cell auto empty(Position const & p) const { + assert(valid(p)); return get(p) == 0; } + //! \brief Returns all neighbors of p + //! Only returns valid neighbors (and p does not need to be valid) auto neighbors(Position const & p) const { small_vector ret; @@ -57,24 +63,31 @@ struct Field{ return ret; } + //! \brief Let the block fall (all the way) auto collapse(){ while(vcollapse()); while(hcollapse()); } + //! \brief Returns an array of all valid positions auto const & all_positions() const { using Indices = std::make_index_sequence; return all_positions_impl(Indices{}); } + //! \brief Get (mutable) value at p T& get(Position const & p){ - return grid[p.first + p.second*W]; + assert(valid(p)); + return grid[static_cast(p.first + p.second*W)]; } + //! \brief Get value at p T const& get(Position const & p) const { - return grid[p.first + p.second*W]; + assert(valid(p)); + return grid[static_cast(p.first + p.second*W)]; } + //! \brief Pretty prints grid to out void print(std::ostream& out) const { for(auto y = H; y; --y){ for(auto x = 0; x < W; ++x){ @@ -86,14 +99,16 @@ struct Field{ private: std::array grid; + //! \brief Helper function for all_positions() template auto const & all_positions_impl(std::index_sequence) const { - static const std::array ret = { + static const std::array ret = {{ Position{I % W, I / W}... - }; + }}; return ret; } + //! \brief Single vertical collapsing step auto vcollapse(){ using namespace std; bool some_change = false; @@ -112,6 +127,7 @@ private: return some_change; } + //! \brief Single horizontal collapsing step auto hcollapse(){ using namespace std; bool some_change = false; @@ -132,7 +148,8 @@ private: return some_change; } - auto empty_column(size_t x){ + //! \brief Returns true if the whole column at x is empty + auto empty_column(int x){ for(auto y = 0; y < H; ++y){ if(!empty({x, y})){ return false; @@ -142,7 +159,8 @@ private: } }; -template +//! \brief Helper function to create a field (T will be deducted) +template auto create_rectangular_field(std::initializer_list grid){ return Field(grid); } diff --git a/include/generator.hpp b/include/generator.hpp new file mode 100644 index 0000000..cb0ba57 --- /dev/null +++ b/include/generator.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "field.hpp" + +#include + +namespace detail { + template + auto random_field(URNG&& r, std::index_sequence){ + std::uniform_int_distribution dis(0, 4); + return create_rectangular_field({ + ((void)I, dis(r))... + }); + } +} + +template +auto random_field(URNG&& r){ + using Indices = std::make_index_sequence; + return detail::random_field(r, Indices{}); +} diff --git a/include/solver.hpp b/include/solver.hpp index 39f85b7..5dc2eb4 100644 --- a/include/solver.hpp +++ b/include/solver.hpp @@ -2,16 +2,6 @@ #include "clusters.hpp" -template -auto make_empty(Field field, Container const & c){ - using namespace std; - for(auto&& p : c){ - field.get(p) = 0; - } - field.collapse(); - return field; -} - template auto solve(Field const & field){ for(auto&& p : field.all_positions()){ diff --git a/main.cpp b/main.cpp index 12ef925..8431dcb 100644 --- a/main.cpp +++ b/main.cpp @@ -2,8 +2,10 @@ #include "field.hpp" #include "clusters.hpp" #include "solver.hpp" +#include "generator.hpp" #include +#include #include #include @@ -17,35 +19,11 @@ auto is_void(Field const & field){ int main(){ using namespace std; -// constexpr auto W = 10; -// constexpr auto H = 10; -// auto field = create_rectangular_field({ -// 2, 1, 1, 1, 2, 1, 2, 4, 1, 2, -// 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, -// 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, -// 2, 1, 1, 4, 2, 4, 2, 1, 2, 1, -// 1, 1, 1, 3, 2, 2, 2, 3, 3, 4, -// 3, 2, 2, 1, 1, 1, 2, 2, 2, 2, -// 1, 1, 2, 1, 3, 1, 1, 4, 2, 3, -// 1, 1, 1, 1, 3, 1, 3, 2, 1, 2, -// 1, 1, 1, 1, 2, 4, 1, 3, 1, 2, -// 1, 1, 1, 1, 2, 2, 1, 1, 4, 9 -// }); + std::random_device rd; + std::mt19937 gen(rd()); - constexpr auto W = 9; - constexpr auto H = 9; - auto field = create_rectangular_field({ - 2, 1, 1, 1, 2, 1, 2, 4, 1, - 2, 2, 2, 1, 2, 2, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 2, 2, - 2, 1, 1, 4, 2, 4, 2, 1, 2, - 1, 1, 1, 3, 2, 2, 2, 3, 3, - 3, 2, 2, 1, 1, 1, 2, 2, 2, - 1, 1, 2, 1, 3, 1, 1, 4, 2, - 1, 1, 1, 1, 3, 1, 3, 2, 1, - 1, 1, 1, 1, 2, 4, 1, 3, 9 - }); + auto field = random_field<5, 5>(gen); field.print(std::cout);