diff --git a/GPA675Lab1GOL/GOLTeamH.cpp b/GPA675Lab1GOL/GOLTeamH.cpp index 71c630b..73ca7fa 100644 --- a/GPA675Lab1GOL/GOLTeamH.cpp +++ b/GPA675Lab1GOL/GOLTeamH.cpp @@ -35,22 +35,33 @@ GOL::Color GOLTeamH::color(State state) const return state == GOL::State::alive ? mAliveColor : mDeadColor; } +// TODO GOL::Statistics GOLTeamH::statistics() const { - return GOL::Statistics{ + return std::move(GOL::Statistics{ .rule = mRule, .borderManagement = mBorderManagement, .width = width(), .height = height(), .totalCells = size(), .iteration = mIteration, - //.totalDeadAbs = mData.totalDead() - }; + .totalDeadAbs = mData.totalDead(), + .totalAliveAbs = mData.totalAlive(), + .totalDeadRel = mData.totalDeadRel(), + .totalAliveRel = mData.totalAliveRel() + // .tendencyAbs = ..., + // .tendencyRel = ... + }); } +// TODO GOL::ImplementationInformation GOLTeamH::information() const { - return ImplementationInformation(); + return std::move(ImplementationInformation{ + .title{"Laboratoire 1"}, + .authors{{"Timothée Leclaire-Fournier"}, {"et Martin Euzenat"} } + // Réponses aux questions... + }); } void GOLTeamH::resize(size_t width, size_t height, State defaultState) @@ -66,16 +77,21 @@ bool GOLTeamH::setRule(std::string const& rule) std::bitset<9> parsedRuleRevive, parsedRuleSurvive; // On vérifie que la chaine de charactères contient un B au début. - // 5 = chaine minimale + // 5 = taille minimale if (rule.size() < 5 || !(rule[0] == 'B' || rule[0] == 'b')) return false; for (size_t i{ 1 }; i < rule.length(); i++) { + // On utilise std::optional comme levier pour vérifier si un char est un nombre. auto opt = convertCharToNumber(rule[i]); - // Si c'est un chiffre, on continue. + // Si c'est un chiffre, on continue en enregistrant la valeur. if (opt.has_value()) { - firstPart ? parsedRuleRevive.set(opt.value()) : parsedRuleSurvive.set(opt.value()); + if (firstPart) + parsedRuleRevive.set(opt.value()); + else + parsedRuleSurvive.set(opt.value()); + continue; } @@ -86,10 +102,11 @@ bool GOLTeamH::setRule(std::string const& rule) firstPart = false; continue; } - else // Aucun slash + s + else // Aucun slash + s, alors pas bon. return false; } + // Si les les deux règles ont au moins un nombre, alors OK. if (parsedRuleRevive.any() && parsedRuleSurvive.any()) { mParsedRuleRevive = parsedRuleRevive; mParsedRuleSurvive = parsedRuleSurvive; @@ -102,39 +119,53 @@ bool GOLTeamH::setRule(std::string const& rule) void GOLTeamH::setBorderManagement(BorderManagement borderManagement) { mBorderManagement = borderManagement; + mIteration = 0; } void GOLTeamH::setState(int x, int y, State state) { mData.setAt(x, y, state); + mIteration = 0; } void GOLTeamH::fill(State state) { - mData.resize(mData.width(), mData.height(), state); + mData.fill(state); + mIteration = 0; } void GOLTeamH::fillAlternately(State firstCell) { + mData.fillAternately(firstCell); + mIteration = 0; } void GOLTeamH::randomize(double percentAlive) { + mData.randomize(percentAlive); + mIteration = 0; } +// TODO bool GOLTeamH::setFromPattern(std::string const& pattern, int centerX, int centerY) { + mIteration = 0; return false; } +// TODO bool GOLTeamH::setFromPattern(std::string const& pattern) { + mIteration = 0; return false; } void GOLTeamH::setSolidColor(State state, Color const& color) { - + if (state == State::dead) + mDeadColor = color; + else + mAliveColor = color; } void GOLTeamH::processOneStep() diff --git a/GPA675Lab1GOL/GOLTeamH.h b/GPA675Lab1GOL/GOLTeamH.h index 3eac5a5..329c745 100644 --- a/GPA675Lab1GOL/GOLTeamH.h +++ b/GPA675Lab1GOL/GOLTeamH.h @@ -32,6 +32,7 @@ public: void setSolidColor(State state, Color const& color) override; void processOneStep() override; void updateImage(uint32_t* buffer, size_t buffer_size) const override; + private: std::optional mRule; std::optional mBorderManagement; diff --git a/GPA675Lab1GOL/Grid.cpp b/GPA675Lab1GOL/Grid.cpp index e0a5931..ef37ec1 100644 --- a/GPA675Lab1GOL/Grid.cpp +++ b/GPA675Lab1GOL/Grid.cpp @@ -7,6 +7,7 @@ Grid::Grid() } Grid::Grid(size_t width, size_t height, CellType initValue) + :mWidth{ width }, mHeight{ height }, mEngine(mRandomDevice), mDistribution(0.0, 1.0) { resize(width, height, initValue); } @@ -37,9 +38,13 @@ size_t Grid::size() const // Mutateur modifiant la taille de la grille et initialise le contenu par la valeur spécifiée. void Grid::resize(size_t width, size_t height, CellType initValue) { - mData.reserve(width * height); + // TODO: Performance de resize avec beaucoup d'appel? + // Investiguer reserve + resize + mData.resize(width * height); mWidth = width; mHeight = height; + + fill(initValue); } // Accesseur retournant la valeur d'une cellule à une certaine coordonnée. @@ -82,9 +87,45 @@ Grid::DataType& Grid::data() return mData; } -// TODO -Grid::DataType Grid::totalDead() +// https://en.cppreference.com/w/cpp/algorithm/count +size_t Grid::totalDead() const { - return DataType(); + return std::count_if(mData.begin(), mData.end(), [](auto& i) { return i == CellType::dead; }); +} -} \ No newline at end of file +float Grid::totalDeadRel() const +{ + return static_cast(totalDead()) / static_cast(size()); +} + +size_t Grid::totalAlive() const +{ + return std::count_if(mData.begin(), mData.end(), [](auto& i) { return i == CellType::alive; }); +} + +float Grid::totalAliveRel() const +{ + return static_cast(totalAlive()) / static_cast(size()); +} + +void Grid::fill(CellType value) +{ + for (auto& i : mData) + i = value; +} + +void Grid::fillAternately(CellType initValue) +{ + auto otherValue = (initValue == CellType::alive) ? CellType::dead : CellType::alive; + + for (size_t i{}; i < mData.size(); i++) + mData[i] = !(i % 2) ? initValue : otherValue; +} + +void Grid::randomize(double percentAlive) +{ + for (auto& i : mData) { + if (mDistribution(mEngine) < percentAlive) + i = CellType::alive; + } +} diff --git a/GPA675Lab1GOL/Grid.h b/GPA675Lab1GOL/Grid.h index 956408d..75d04e5 100644 --- a/GPA675Lab1GOL/Grid.h +++ b/GPA675Lab1GOL/Grid.h @@ -1,6 +1,8 @@ #pragma once +#include #include +#include #include "GOL.h" class Grid // Classe facilitant la gestion d'un tableau dynamique 2d. @@ -37,8 +39,22 @@ public: // DataType const& data() const; // Accesseur en lecture seule sur le "buffer" de la grille. DataType& data(); // Accesseur en lecture/écriture sur le "buffer" de la grille. - DataType totalDead(); + size_t totalDead() const; + float totalDeadRel() const; + + size_t totalAlive() const; + float totalAliveRel() const; + + void fill(CellType value); + void fillAternately(CellType initValue); + void randomize(double percentAlive); + private: // DataType mData; // Il y a des attributs essentiels au fonctionnement de cette classe. size_t mWidth, mHeight; // À vous de les déterminer. + + // Random + std::random_device mRandomDevice; + std::mt19937 mEngine; + std::uniform_real_distribution<> mDistribution; }; \ No newline at end of file diff --git a/GPA675Lab1GOL/main.cpp b/GPA675Lab1GOL/main.cpp index 6be73ab..18a2d52 100644 --- a/GPA675Lab1GOL/main.cpp +++ b/GPA675Lab1GOL/main.cpp @@ -1,26 +1,14 @@ - #include #include "GOLApp.h" - - -//TEST DE COMMIT +#include "GOLTeamH.h" int main(int argc, char* argv[]) { QApplication application(argc, argv); GOLApp window; - - // - // Ajouter votre implémentation ici. - // Évidemment, n'oubliez pas de faire l'inclusion du fichier contenant - // votre classe. - // - // Par exemple : - // - // window.addEngine(new MonImplementationGOL); - // + window.addEngine(new GOLTeamH()); window.show(); return application.exec();