Adds a random generator. Fixes some warnings. Adds some comments
This commit is contained in:
parent
083141d346
commit
a137e31ba0
5 changed files with 60 additions and 45 deletions
|
@ -45,4 +45,12 @@ auto all_clusters(Field const & field){
|
|||
return ret;
|
||||
}
|
||||
|
||||
#undef Set
|
||||
template <typename Field, typename Cluster>
|
||||
auto make_empty(Field field, Cluster const & c){
|
||||
using namespace std;
|
||||
for(auto&& p : c){
|
||||
field.get(p) = 0;
|
||||
}
|
||||
field.collapse();
|
||||
return field;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
|
@ -23,7 +24,7 @@ struct small_vector{
|
|||
|
||||
// Position {0,0} is bottom left.
|
||||
// Position {W-1, H-1} is top right.
|
||||
template <size_t W, size_t H, typename T>
|
||||
template <int W, int H, typename T>
|
||||
struct Field{
|
||||
using Position = std::pair<int, int>;
|
||||
|
||||
|
@ -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<Position, 4> 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<W*H>;
|
||||
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<size_t>(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<size_t>(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<T, W*H> grid;
|
||||
|
||||
//! \brief Helper function for all_positions()
|
||||
template<std::size_t... I>
|
||||
auto const & all_positions_impl(std::index_sequence<I...>) const {
|
||||
static const std::array<const Position, W*H> ret = {
|
||||
static const std::array<const Position, W*H> 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 <size_t W, size_t H, typename T>
|
||||
//! \brief Helper function to create a field (T will be deducted)
|
||||
template <int W, int H, typename T>
|
||||
auto create_rectangular_field(std::initializer_list<T> grid){
|
||||
return Field<W, H, T>(grid);
|
||||
}
|
||||
|
|
21
include/generator.hpp
Normal file
21
include/generator.hpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include "field.hpp"
|
||||
|
||||
#include <random>
|
||||
|
||||
namespace detail {
|
||||
template <int W, int H, typename URNG, size_t... I>
|
||||
auto random_field(URNG&& r, std::index_sequence<I...>){
|
||||
std::uniform_int_distribution<int> dis(0, 4);
|
||||
return create_rectangular_field<W, H>({
|
||||
((void)I, dis(r))...
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template <int W, int H, typename URNG>
|
||||
auto random_field(URNG&& r){
|
||||
using Indices = std::make_index_sequence<W*H>;
|
||||
return detail::random_field<W, H>(r, Indices{});
|
||||
}
|
|
@ -2,16 +2,6 @@
|
|||
|
||||
#include "clusters.hpp"
|
||||
|
||||
template <typename Field, typename Container>
|
||||
auto make_empty(Field field, Container const & c){
|
||||
using namespace std;
|
||||
for(auto&& p : c){
|
||||
field.get(p) = 0;
|
||||
}
|
||||
field.collapse();
|
||||
return field;
|
||||
}
|
||||
|
||||
template <typename Field>
|
||||
auto solve(Field const & field){
|
||||
for(auto&& p : field.all_positions()){
|
||||
|
|
32
main.cpp
32
main.cpp
|
@ -2,8 +2,10 @@
|
|||
#include "field.hpp"
|
||||
#include "clusters.hpp"
|
||||
#include "solver.hpp"
|
||||
#include "generator.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
|
@ -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<W, H>({
|
||||
// 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<W, H>({
|
||||
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);
|
||||
|
||||
|
|
Reference in a new issue