1
Fork 0
This repository has been archived on 2025-04-09. You can view files and clone it, but cannot push or open issues or pull requests.
puzzle-wuzzle-generator/lib/dynamic_grid.cpp
2014-02-18 16:13:35 +01:00

108 lines
2.1 KiB
C++

#include "dynamic_grid.hpp"
#include "colored_output.hpp"
#include <functional>
#include <iostream>
//! \brief Helper function for all_positions()
static auto all_positions_impl(int W, int H) {
std::vector<DynamicGrid::Position> r;
for(int y = 0; y < H; ++y)
for(int x = 0; x < W; ++x)
r.emplace_back(x, y);
return r;
}
DynamicGrid::DynamicGrid(int width, int height, std::vector<int> && data)
: W(width), H(height), grid(std::move(data)) {
assert(grid.size() == W*H);
positions = all_positions_impl(W, H);
}
small_vector<DynamicGrid::Position, 4>
DynamicGrid::neighbors(Position const & p) const {
small_vector<Position, 4> ret;
static Position nbs[] = {
{-1, 0}, {1, 0}, {0, 1}, {0, -1}
};
for(auto&& n : nbs){
auto q = Position{p.first + n.first, p.second + n.second};
if(valid(q)){
ret.push_back(q);
}
}
return ret;
}
auto DynamicGrid::empty_column(int x){
for(auto y = 0; y < H; ++y){
if(!empty({x, y})){
return false;
}
}
return true;
}
auto DynamicGrid::vcollapse(){
using namespace std;
bool some_change = false;
for(auto&& p : all_positions()){
if(empty(p)) continue;
auto q = p;
q.second--;
if(!valid(q)) continue;
if(!empty(q)) continue;
swap(get(p), get(q));
some_change = true;
}
return some_change;
}
auto DynamicGrid::hcollapse(){
using namespace std;
bool some_change = false;
for(auto x = 0; x < W-1; ++x){
if(!empty_column(x)) continue;
auto x2 = x+1;
for(; x2 < W; ++x2){
if(!empty_column(x2)) break;
}
if(x2 == W) return some_change;
for(auto y = 0; y < H; ++y){
swap(get({x, y}), get({x2, y}));
}
some_change = true;
}
return some_change;
}
void DynamicGrid::collapse(){
while(vcollapse());
while(hcollapse());
}
void DynamicGrid::print(std::ostream& out) const {
for(auto y = H; y; --y){
for(auto x = 0; x < W; ++x){
out << colored_block(get({x, y-1})) << (x == W-1 ? "\n" : "");
}
}
}
size_t DynamicGrid::hash() const {
std::string hs(W*H, '\0');
auto it = hs.begin();
for(auto&&p : all_positions()){
*it++ = static_cast<char>(get(p));
}
return std::hash<std::string>()(hs);
}