Skip to content

Instantly share code, notes, and snippets.

@eisterman
Created November 2, 2017 20:13
Show Gist options
  • Save eisterman/f991bf5eac517efd5847d3d5261ee0f7 to your computer and use it in GitHub Desktop.
Save eisterman/f991bf5eac517efd5847d3d5261ee0f7 to your computer and use it in GitHub Desktop.
Demotest NewGameOfLifeXL
//
// Created by fpasqua on 02/11/17.
//
#ifndef NEWGAMEOFLIFEXL_GAMEOFLIFE_H
#define NEWGAMEOFLIFEXL_GAMEOFLIFE_H
#include <cstddef>
#include <array>
#include "Rule.hpp"
namespace GoL {
template <class T, std::size_t x, std::size_t y>
using table_t = std::array<std::array<T,y>,x>;
template<std::size_t max_x, std::size_t max_y, typename T = bool>
class GoLEngine {
public:
explicit GoLEngine(const Rule<T> & rule = CONWAY) : m_rule{rule} {}
void setRule(const Rule<T> & rule) { m_rule = rule; }
void run(size_t iter = 1);
Rule<T> getRule() const { return m_rule; }
T get(size_t x, size_t y) const { return m_table.at(x%max_x).at(y%max_y); }
void set(size_t x, size_t y, T state) { m_table.at(x).at(y) = state; }
void reset();
unsigned long long int getGen() const { return m_gen; }
size_t getXMax() const { return max_x; }
size_t getYMax() const { return max_y; }
protected:
// Useful Function
virtual void run_once(table_t<T, max_x, max_y> & tmp_table);
size_t counting_full(size_t x, size_t y) const;
inline bool is_confine(size_t x, size_t y) const {
return ( x == 0 || x == max_x -1 || y == 0 || y == max_y -1);
}
// Attributes
Rule<T> m_rule;
unsigned long long int m_gen = 0; // Generazione
table_t<T, max_x, max_y> m_table;
};
void GoLEngine::reset() {
for (auto ax : m_table)
ax.fill(0);
m_gen = 0;
}
size_t GoLEngine::counting_full(size_t x, size_t y) const {
size_t empty = 0;
size_t full = 0;
for(auto i = x-1; i <= x+1; i++)
for(auto j = y-1; j <= y+1; j++) {
if(!(i == x && j == y))
this->get(i,j) ? full++ : empty++;
}
return full;
}
template<std::size_t max_x, std::size_t max_y, typename T = bool>
void GoLEngine::run(size_t iter) {
table_t<T, max_x, max_y> tmp_table = m_table;
for(int i = 0; i < iter; i++) {
run_once(tmp_table);
m_table = tmp_table;
m_gen++;
}
}
template<std::size_t max_x, std::size_t max_y, typename T = bool>
void GoLEngine::run_once(table_t<T, max_x, max_y> & tmp_table) {
for(size_t i = 0; i < max_x; i++)
for(size_t j = 0; j < max_y; j++) {
size_t full = counting_full(i, j);
tmp_table.at(i).at(j) = m_rule.apply(full, tmp_table.at(i).at(j));
}
}
}
#endif //NEWGAMEOFLIFEXL_GAMEOFLIFE_H
//
// Created by fpasqua on 02/11/17.
//
#ifndef NEWGAMEOFLIFEXL_RULE_H
#define NEWGAMEOFLIFEXL_RULE_H
#include <cstddef>
#include <vector>
#include <algorithm>
#include <stdexcept>
namespace GoL {
template <typename T = bool>
class Rule {
public:
Rule() = default;
Rule(const std::vector<size_t> & B, const std::vector<size_t> & S);
Rule(const Rule & old) = default;
Rule(Rule &&) noexcept = default;
~Rule() = default;
T apply(size_t full, T state) const;
std::vector<size_t> getBirth() const { return m_Birth; }
std::vector<size_t> getStay() const { return m_Stay; }
protected:
std::vector<size_t> m_Birth;
std::vector<size_t> m_Stay;
};
Rule::Rule(const std::vector<size_t> & B, const std::vector<size_t> & S) {
if (std::any_of(B.begin(), B.end(), [](size_t n){ return (n < 0 || n > 8); }))
throw std::range_error("Birth Rule must be between 0 and 8.");
if (std::any_of(S.begin(), S.end(), [](size_t n){ return (n < 0 || n > 8); }))
throw std::range_error("Birth Rule must be between 0 and 8.");
// TODO: Check repeating
m_Birth = B;
m_Stay = S;
}
template <typename T = bool>
T Rule::apply(size_t full, T state) const {
if(state) {
return std::find(m_Stay.begin(), m_Stay.end(), full) != m_Stay.end();
} else {
return std::find(m_Birth.begin(), m_Birth.end(), full) != m_Birth.end();
}
}
const Rule CONWAY({3}, {3,2});
}
#endif //NEWGAMEOFLIFEXL_RULE_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment