minor refactoring

This commit is contained in:
twistdroach 2023-04-29 22:25:01 -04:00
parent 61dcadbbba
commit 4c68bb4b6d
9 changed files with 74 additions and 69 deletions

@ -14,7 +14,7 @@ int main() {
DistanceGrid grid(10, 10);
Sidewinder::on(grid);
auto start = grid.getCellRef(0, 0);
auto& start = grid.getCellRef(0, 0);
grid.setStart(start);
// run Dijkstra's algorithm to find farthest cell

@ -2,26 +2,20 @@
#include "Grid.h"
#include "Cell.h"
#include <random>
static std::random_device rd;
static std::mt19937 gen(rd());
#include "Utils.h"
void BinaryTree::on(Grid &grid) {
for (auto &cell: grid) {
std::vector < Cell * > neighbors;
std::vector<std::reference_wrapper<Cell>> neighbors;
if (cell.hasNorth()) {
neighbors.emplace_back(cell.north);
neighbors.emplace_back(*cell.north);
}
if (cell.hasEast()) {
neighbors.emplace_back(cell.east);
neighbors.emplace_back(*cell.east);
}
if (!neighbors.empty()) {
std::uniform_int_distribution<std::vector<Cell*>::size_type> dist(0, neighbors.size() - 1);
auto index = dist(gen);
auto neighbor = neighbors[index];
cell.link(*neighbor);
auto& neighbor = utils::randomElement(neighbors);
cell.link(neighbor);
}
}
}

@ -1,3 +1,3 @@
add_library(maze STATIC Cell.cpp Grid.cpp BinaryTree.cpp Sidewinder.cpp Distances.cpp AldousBroder.cpp Wilsons.cpp)
add_library(maze STATIC Cell.cpp Grid.cpp BinaryTree.cpp Sidewinder.cpp Distances.cpp AldousBroder.cpp Wilsons.cpp Utils.cpp)
target_include_directories(maze PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

@ -9,8 +9,8 @@ class Distances {
public:
Distances(const Cell& root);
[[nodiscard]] int getDistance(const Cell& cell) const;
[[nodiscard]] std::vector<std::reference_wrapper<const Cell>> getCells() const;
void setDistance(const Cell& cell, int distance);
[[nodiscard]] std::vector<std::reference_wrapper<const Cell>> getCells() const;
[[nodiscard]] bool contains(const Cell& cell) const;
[[nodiscard]] Distances pathTo(const Cell& goal) const;
[[nodiscard]] std::tuple<const Cell&, int> max() const;

@ -79,13 +79,13 @@ std::string Grid::toString() const {
for (auto& cell : row) {
std::string body = contentsOf(cell);
std::string east_boundary_text = "|";
if (cell.east && cell.isLinked(*cell.east)) {
if (cell.hasEast() && cell.isLinked(*cell.east)) {
east_boundary_text = " ";
}
top += body + east_boundary_text;
std::string south_boundary_text = "---";
if (cell.south && cell.isLinked(*cell.south)) {
if (cell.hasSouth() && cell.isLinked(*cell.south)) {
south_boundary_text = " ";
}
bottom += south_boundary_text + "+";

@ -2,33 +2,21 @@
#include "Grid.h"
#include "Cell.h"
#include <random>
static std::random_device rd;
static std::mt19937 gen(rd());
/* from https://stackoverflow.com/questions/43329352/generating-random-boolean-c */
bool randomBool() {
static auto bdist = std::uniform_int_distribution<>(0,1);
return bdist(gen);
}
#include "Utils.h"
void Sidewinder::on(Grid &grid) {
for (auto row: grid.byRow()) {
std::vector<Cell *> run;
std::vector<std::reference_wrapper<Cell>> run;
for (auto &cell: row) {
run.emplace_back(&cell);
bool at_eastern_boundary = !cell.east;
bool at_northern_boundary = !cell.north;
run.emplace_back(cell);
bool at_eastern_boundary = !cell.hasEast();
bool at_northern_boundary = !cell.hasNorth();
bool should_close_out = at_eastern_boundary || (!at_northern_boundary && randomBool());
bool should_close_out = at_eastern_boundary || (!at_northern_boundary && utils::randomBool());
if (should_close_out) {
auto dist = std::uniform_int_distribution<std::vector<Cell *>::size_type>(0, run.size() - 1);
auto index = dist(gen);
auto &member = run[index];
if (member->north) {
member->link(*member->north);
auto& member = utils::randomElement(run);
if (member.hasNorth()) {
member.link(*member.north);
}
run.clear();
} else {

38
src/Utils.cpp Normal file

@ -0,0 +1,38 @@
#include "Utils.h"
#include "Cell.h"
#include <random>
static std::random_device rd;
static std::mt19937 gen(rd());
namespace utils {
/* from https://stackoverflow.com/questions/43329352/generating-random-boolean-c */
bool randomBool() {
static auto bdist = std::uniform_int_distribution<>(0, 1);
return bdist(gen);
}
Cell& randomElement(std::vector<std::reference_wrapper<Cell>> &v) {
if (v.empty()) {
throw std::invalid_argument("vector is empty");
}
std::uniform_int_distribution<std::vector<Cell>::size_type> dist(0, v.size() - 1);
auto index = dist(gen);
return v[index];
}
bool containsElement(std::vector<std::reference_wrapper<Cell>> &v, Cell &c) {
return std::find_if(v.begin(), v.end(), [&c] (const std::reference_wrapper<Cell> target) {
return c == target;
}) != v.end();
}
void removeElement(std::vector<std::reference_wrapper<Cell>> &v, Cell &c) {
v.erase(std::remove_if(v.begin(), v.end(), [&c] (const std::reference_wrapper<Cell> target) {
return c == target;
}), v.end());
}
}

10
src/Utils.h Normal file

@ -0,0 +1,10 @@
#pragma once
#include "Cell.h"
namespace utils {
bool randomBool();
Cell& randomElement(std::vector<std::reference_wrapper<Cell>> &v);
bool containsElement(std::vector<std::reference_wrapper<Cell>> &v, Cell &c);
void removeElement(std::vector<std::reference_wrapper<Cell>> &v, Cell &c);
}

@ -1,43 +1,18 @@
#include "Wilsons.h"
#include "Cell.h"
#include <random>
static std::random_device rd;
static std::mt19937 gen(rd());
Cell& randomElement(std::vector<std::reference_wrapper<Cell>> &v) {
if (v.empty()) {
throw std::invalid_argument("vector is empty");
}
std::uniform_int_distribution<std::vector<Cell>::size_type> dist(0, v.size() - 1);
auto index = dist(gen);
return v[index];
}
bool findCell(std::vector<std::reference_wrapper<Cell>> &v, Cell &c) {
return std::find_if(v.begin(), v.end(), [&c] (const std::reference_wrapper<Cell> target) {
return c == target;
}) != v.end();
}
void removeCell(std::vector<std::reference_wrapper<Cell>> &v, Cell &c) {
v.erase(std::remove_if(v.begin(), v.end(), [&c] (const std::reference_wrapper<Cell> target) {
return c == target;
}), v.end());
}
#include "Utils.h"
void Wilsons::on(Grid &grid) {
std::vector<std::reference_wrapper<Cell>> unvisited(grid.begin(), grid.end());
auto& first = randomElement(unvisited);
removeCell(unvisited, first);
auto& first = utils::randomElement(unvisited);
utils::removeElement(unvisited, first);
while (!unvisited.empty()) {
std::vector<std::reference_wrapper<Cell>> path;
std::reference_wrapper<Cell> cell = randomElement(unvisited);
std::reference_wrapper<Cell> cell = utils::randomElement(unvisited);
path.emplace_back(cell);
while (findCell(unvisited, cell)) {
while (utils::containsElement(unvisited, cell)) {
cell = cell.get().randomNeighbor();
auto it = std::find_if(path.begin(), path.end(),
[&](const std::reference_wrapper<Cell> &i)
@ -53,7 +28,7 @@ void Wilsons::on(Grid &grid) {
}
for (int i = 0; i < path.size() - 1; i++) {
path[i].get().link(path[i + 1].get());
removeCell(unvisited, path[i]);
utils::removeElement(unvisited, path[i]);
}
}