diff --git a/GPA675Lab1GOL/GOLTeamH.cpp b/GPA675Lab1GOL/GOLTeamH.cpp index 3fd0c3b..39d1285 100644 --- a/GPA675Lab1GOL/GOLTeamH.cpp +++ b/GPA675Lab1GOL/GOLTeamH.cpp @@ -323,58 +323,15 @@ void GOLTeamH::randomize(double percentAlive) // TODO bool GOLTeamH::setFromPattern(std::string const& pattern, int centerX, int centerY) { - // Analyse du pattern - size_t pos = 0; + auto sq = parsePattern(pattern); - // Vérification du '[' initial - if (pattern[pos++] != '[') { - std::cerr << "Erreur de format : '[' manquant." << std::endl; + if (!sq.has_value()) return false; - } - // Lecture de la largeur - size_t width = std::stoi(pattern.substr(pos), &pos); - if (width <= 0) { - std::cerr << "Erreur de format : Largeur invalide." << std::endl; - return false; - } + fillDataFromPattern(pattern, sq.value(), centerX, centerY); - // Vérification du 'x' - if (pattern[pos++] != 'x') { - std::cerr << "Erreur de format : 'x' manquant." << std::endl; - return false; - } - - // Lecture de la hauteur - size_t height = std::stoi(pattern.substr(pos), &pos); - if (height <= 0) { - std::cerr << "Erreur de format : Hauteur invalide." << std::endl; - return false; - } - - // Vérification du ']' - if (pattern[pos++] != ']') { - std::cerr << "Erreur de format : ']' manquant." << std::endl; - return false; - } - - // Vérification de la taille du reste du pattern - if (pattern.length() - pos != width * height) { - std::cerr << "Erreur de format : Taille du patron incorrecte." << std::endl; - return false; - } - - // Remplissage de la grille aux positions spécifiées par le patron - for (size_t y = 0; y < height; ++y) { - for (size_t x = 0; x < width; ++x) { - char cellChar = pattern[pos++]; - State cellState = (cellChar == '0') ? State::dead : State::alive; - mData.setAt(centerX + x, centerY + y, cellState); - } - } - - return true; mIteration = 0; + return true; } //! \brief Mutateur remplissant la grille par le patron passé en argument. @@ -388,59 +345,20 @@ bool GOLTeamH::setFromPattern(std::string const& pattern, int centerX, int cente //! \param pattern Le patron à appliquer. //! \return true si le patron est valide, false sinon. -// TODO bool GOLTeamH::setFromPattern(std::string const& pattern) { - // Analyse du pattern - size_t pos = 0; + auto sq = parsePattern(pattern); - // Vérification du '[' initial - if (static_cast(pattern[pos++]) != '[') { - std::cerr << "Erreur de format : '[' manquant." << std::endl; + if (!sq.has_value()) return false; - } - // Lecture de la largeur - size_t width = std::stoi(pattern.substr(pos), &pos); - if (width <= 0) { - std::cerr << "Erreur de format : Largeur invalide." << std::endl; - return false; - } - pos++; - if (pattern[pos++] != 120 ) { - std::cerr << "Erreur de format : 'x' manquant." << std::endl; - return false; - } - // Lecture de la hauteur - size_t height = std::stoi(pattern.substr(pos), &pos); - pos = pos + 4; - if (height <= 0) { - std::cerr << "Erreur de format : Hauteur invalide." << std::endl; - return false; - } - - // Vérification du ']' - if (static_cast(pattern[pos++]) != ']') { - std::cerr << "Erreur de format : ']' manquant." << std::endl; - return false; - } - pos++; - - size_t centerX = mData.width() / 2 - width/2; - size_t centerY = mData.height() / 2 - height/2; + size_t centerX = mData.width() / 2 - (sq.value().width / 2); + size_t centerY = mData.height() / 2 - (sq.value().height / 2); - // Remplissage de la grille aux positions spécifiées par le patron - for (size_t y = 0; y < height; ++y) { - for (size_t x = 0; x < width; ++x) { - char cellChar = pattern[pos++]; - mData.setAt(centerX + x, centerY + y, State::dead); - State cellState = (cellChar == '0') ? State::dead : State::alive; - mData.setAt(centerX + x, centerY + y, cellState); - } - } + fillDataFromPattern(pattern, sq.value(), centerX, centerY); - return true; mIteration = 0; + return true; } //! \brief Mutateur modifiant la couleur d'un état. @@ -623,3 +541,65 @@ std::optional GOLTeamH::convertCharToNumber(const char c) return (c - 48); } + +std::optional GOLTeamH::parsePattern(std::string const& pattern) +{ + // Analyse du pattern + size_t pos{}, processedNumbers{}; + + // Vérification du '[' initial + if (pattern[pos++] != '[') { + std::cerr << "Erreur de format : '[' manquant." << std::endl; + return std::nullopt; + } + + // Lecture de la largeur + size_t width = std::stoi(pattern.substr(pos), &processedNumbers); + pos += processedNumbers; + + if (width <= 0) { + std::cerr << "Erreur de format : Largeur invalide." << std::endl; + return std::nullopt; + } + + // Vérification du 'x' + if (pattern[pos++] != 'x') { + std::cerr << "Erreur de format : 'x' manquant." << std::endl; + return std::nullopt; + } + + // Lecture de la hauteur + size_t height = std::stoi(pattern.substr(pos), &processedNumbers); + pos += processedNumbers; + + if (height <= 0) { + std::cerr << "Erreur de format : Hauteur invalide." << std::endl; + return std::nullopt; + } + + // Vérification du ']' + if (pattern[pos++] != ']') { + std::cerr << "Erreur de format : ']' manquant." << std::endl; + return std::nullopt; + } + + // Vérification de la taille du reste du pattern + if (pattern.length() - pos != width * height) { + std::cerr << "Erreur de format : Taille du patron incorrecte." << std::endl; + return std::nullopt; + } + + return std::move(GOLTeamH::sizeQueried{ .width = width, .height = height, .pos = pos }); +} + +void GOLTeamH::fillDataFromPattern(std::string const& pattern, sizeQueried& sq, + int centerX, int centerY) +{ + // Remplissage de la grille aux positions spécifiées par le patron + for (size_t y = 0; y < sq.height; ++y) { + for (size_t x = 0; x < sq.width; ++x) { + State cellState = (pattern[sq.pos++] == '0') ? State::dead : State::alive; + mData.setAt(centerX + x, centerY + y, cellState); + } + } +} diff --git a/GPA675Lab1GOL/GOLTeamH.h b/GPA675Lab1GOL/GOLTeamH.h index cef7b0c..c36e3af 100644 --- a/GPA675Lab1GOL/GOLTeamH.h +++ b/GPA675Lab1GOL/GOLTeamH.h @@ -1,7 +1,7 @@ #pragma once #ifndef GOLTEAMH_H #define GOLTEAMH_H - + #include #include @@ -45,17 +45,21 @@ constexpr unsigned char MAX_ALPHA = 255; class GOLTeamH : public GOL { public: + struct sizeQueried { + size_t width, height, pos; + }; + // - le constructeur par défaut : _class_() // - le constructeur d'initialisation proposé : _class_(size_t width, size_t height, State defaultState = State::dead) // - le destructeur : ~_class_() GOLTeamH(); - GOLTeamH(GOLTeamH const &) = delete; - GOLTeamH(GOLTeamH &&) = delete; - GOLTeamH& operator =(GOLTeamH const &) = delete; + GOLTeamH(GOLTeamH const&) = delete; + GOLTeamH(GOLTeamH&&) = delete; + GOLTeamH& operator =(GOLTeamH const&) = delete; GOLTeamH& operator =(GOLTeamH&&) = delete; - virtual ~GOLTeamH()=default; - + virtual ~GOLTeamH() = default; + // inline puisque trivial. size_t width() const override { return mData.width(); } size_t height() const override { return mData.height(); } @@ -107,6 +111,9 @@ private: // Fonctions utilisées à l'interne. std::optional convertCharToNumber(const char c); + std::optional parsePattern(std::string const& pattern); + void fillDataFromPattern(std::string const& pattern, sizeQueried& sq, + int centerX, int centerY); }; #endif GOLTEAMH_H \ No newline at end of file