89 lines
2.1 KiB
C++
89 lines
2.1 KiB
C++
#pragma once
|
|
|
|
#include "utilities.hpp"
|
|
|
|
#include <cassert>
|
|
#include <utility>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
#include <random>
|
|
#include <iosfwd>
|
|
|
|
// Position {0,0} is bottom left.
|
|
// Position {W-1, H-1} is top right.
|
|
// template <typename T>
|
|
struct DynamicGrid{
|
|
using Position = std::pair<int, int>;
|
|
|
|
DynamicGrid(int width, int height, std::vector<int> && data);
|
|
|
|
//! \brief Returns an array of all valid positions (may be empty)
|
|
auto const & all_positions() const{
|
|
return positions;
|
|
}
|
|
|
|
//! \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 Get (mutable) value at p
|
|
auto & get(Position const & p){
|
|
assert(valid(p));
|
|
return grid[static_cast<size_t>(p.first + p.second*W)];
|
|
}
|
|
|
|
//! \brief Get value at p
|
|
auto const& get(Position const & p) const {
|
|
assert(valid(p));
|
|
return grid[static_cast<size_t>(p.first + p.second*W)];
|
|
}
|
|
|
|
//! \brief Returns true if p represents an empty cell
|
|
auto empty(Position const & p) const {
|
|
assert(valid(p));
|
|
return get(p) == 0;
|
|
}
|
|
|
|
//! \brief Return true if the whole grid is empty
|
|
auto empty() const {
|
|
for(auto&& p : all_positions()){
|
|
if(!empty(p)) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//! \brief Returns all neighbors of p
|
|
//! Only returns valid neighbors (and p does not need to be valid)
|
|
small_vector<Position, 4> neighbors(Position const & p) const;
|
|
|
|
//! \brief Let the block fall (all the way)
|
|
void collapse();
|
|
|
|
//! \brief Pretty prints grid to out
|
|
void print(std::ostream& out) const;
|
|
|
|
private:
|
|
int W;
|
|
int H;
|
|
std::vector<int> grid;
|
|
std::vector<Position> positions;
|
|
|
|
//! \brief Single vertical collapsing step
|
|
auto vcollapse();
|
|
|
|
//! \brief Single horizontal collapsing step
|
|
auto hcollapse();
|
|
|
|
//! \brief Returns true if the whole column at x is empty
|
|
auto empty_column(int x);
|
|
};
|
|
|
|
template <typename URNG>
|
|
auto random_dynamic_grid(int W, int H, int C, URNG&& r){
|
|
std::uniform_int_distribution<int> dis(1, C);
|
|
std::vector<int> v(W*H);
|
|
std::generate_n(std::begin(v), W*H, [&]{ return dis(r); });
|
|
return DynamicGrid(W, H, std::move(v));
|
|
}
|