Je suis un débutant en programmation et hier j'ai commencer à me mettre au c++ et au sfml.
J'ai donc commencer un petit projet où le principe et juste de cliquer sur une cible qui se déplace pour accumuler des points.
Mon programme fonctionne, bien je n'ai pas de soucis mais j'aimerais l'améliorer notamment en utilisant des classes car là tout mon programme est dans mon main, mais ... Je bloque, j'ai beau lire et relire et le chapitre sur les classe dans le cours sur le c++, je n'arrive pas à m'imaginer comment faire mes classes, quelles fonctions mettre dans quelle classe? Dois-je en faire une? Plusieurs?
Aussi, même si mon programme fonctionne bien, j'aimerais votre avis sur la façon de faire, comment l'améliorer etc.. car je suis bien conscient que ce n'est pas parfait, mais je ne cherche qu'à m'améliorer.
De manière générale, on considère qu'une fonction composée de plus de 40 à 50 lignes est beaucoup trop longue (50 étant le "chiffre magique" utilisé à l'époque où les moniteurs ne pouvaient afficher que 25 lignes à la fois) ... D'aucuns considèrent même que la limite se trouve plus près des 20 ou 25 lignes.
Alors, que dire d'une fonction de presque 450 lignes, à part qu'elle est au moins... 10 à 20 fois trop longue?
Sans même avoir vraiment regardé le code de ta fonction main, j'ai déjà identifié au minimum quatre boucles "while" qui me semblent déjà relativement longues, et qui mériteraient sans doute de se retrouver dans des fonctions séparées.
Cela te permettrait de t'y retrouver beaucoup plus facilement et t'éviterait d'avoir recours à ces #pragma region / pragma endregion dont je doute très fort (comme pour tous les pragma) qu'ils ne soient standard
Et comme la règle sur le forum est "aides nous à te venir en aide", je crains fort que tu n'auras pas d'autres réponses avant d'avoir effectivement fait en sorte de nous présenter des fonctions qui "ne soient pas trop longues". Du moins, je sais que je ne regarderai pas le code plus attentivement avant que ce ne soit le cas
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
Je suis un débutant en programmation et hier j'ai commencer à me mettre au c++ et au sfml.
J'ai donc commencer un petit projet où le principe et juste de cliquer sur une cible qui se déplace pour accumuler des points.
Mon programme fonctionne, bien je n'ai pas de soucis mais j'aimerais l'améliorer notamment en utilisant des classes car là tout mon programme est dans mon main, mais ... Je bloque, j'ai beau lire et relire et le chapitre sur les classe dans le cours sur le c++, je n'arrive pas à m'imaginer comment faire mes classes, quelles fonctions mettre dans quelle classe? Dois-je en faire une? Plusieurs?
Salut,
Passer de la programmation procédurale (linéaire, à base de fonctions) vers la programmation objet (utiliser des classes) est un exercice plus difficile qu'il n'y parrait. Pose toi les bonnes questions, fais abstraction des données, et raisonne en terme de services.
Un façon naïve d'y arriver est d'identifier clairement ce dont tu auras besoin. Tu as besoin de "choses" (tiens ? un nom) qui vont "agir" (tiens ? un verbe). Et c'est comme cela que tu va trouver tes premières classes: Un nom = un classe. Un verbe = une fonction membre.
Un pragma sert justement à gérer des fonctionnalités non standards. Ici, le pragma region risque d'être non utilisable si tu utilises un autre compilateur.
alexisbenoit a écrit:
Artemix: comme je suis debutant j'ai encore beaucoup de mal, lequel de mes include n'est pas bon?
Tes include sont tous corrects, ce sont bien des includes C++. Seul windows.h pourrait être douteux, mais il n'a pas d'équivalent pur C++ à ma connaissance.
Avant de penser classes, on peut commencer par assimiler un découpage fonctionnel. Une fonction peut être assimilée à une classe qui ne sait que faire une unique action. Ton code contient 4 parties qui se ressemblent fortement produire une fonction qui serait utilisée 4 fois serait un premier pas.
Voilà mon programme avec des fonctions faites, mais il reste relativement long quand même encore(void main fait une centaine de ligne).
Par contre il y a une fonction que je n'arrive pas à faire fonctionner je l'ai donc mise en commentaire donc si vous avez le temps de jeter un coup d'oeil et me dire pourquoi elle ne fonctionne pas n'hésitez pas.
Les tableaux vont te permettre de rassembler les données entre elles pour pouvoir les traiter plus facilement, par exemple avec les "for-ranged loops":
C'est un bon début, tu as pu mettre en place des fonctions et factoriser des choses. Il reste des choses factorisables, et l'utilisation d'objets devrait permettre de clarifier cela.
Attention, en C++ on ne doit pas utiliser les pointeurs dans la mesure où c'est possible, ce qui est presque toujours le cas. Or presque toutes tes fonctions reçoivent des pointeurs au lieu de valeurs, références ou const référence suivant les cas. Exemple :
void gestionSouris( sf::RenderWindow &window, bool &decompte, bool &click ) {
sf::Event event;
while ( window.pollEvent( event ) ) {
switch ( event.type ) {
case sf::Event::Closed: window.close(); break;
case sf::Event::MouseLeft: decompte = false; break;
case sf::Event::MouseEntered: decompte = true; break;
case sf::Event::MouseButtonReleased: click = false; break;
}
}
}
Si on doit passer beaucoup de paramètres à une fonction et que ces paramètres sont des données constantes, ce serait peut-être mieux sous la forme d'un service rendu par un objet.
Tes fonctions creerXXX sont curieuses, elles reçoivent l'objet en paramètre (parfois via pointeur, parfois par copie), elles retournent l'objet créé; mais l'objet retourné est parfois ignoré. Ça n'est pas cohérent, si elles créént elles n'ont pas d'objet en entrée et l'objet créé doit être utilisé en sortie. L'objet RenderWindow n'est peut-être pas copiable, ce qui serait l'erreur dans ta fonction creerFenetre() que je te propose de remplacer par :
En effet je me suis rendu compte après avoir posté que mes fonction créer pourrait être des void plutôt que des fonctions retournant l'objet.
J'utilise beaucoup de pointeurs d'une part car c'est comme ça que j'avais appris et d'autre part car je n'aime pas créer de copie d'objet mais modifier l'objet directement. On ne m'avait jamais dit qu'il fallait en utiliser le moins possible.
Et concernant les référence, je ne m'étais pas attardé dessus vu que j'utilisait des pointeurs donc je ne sait pas vraiment comment cela fonctionne.
Je viens d'essayer ta fonction pour initialiser la fenêtre et ça fonctionne parfaitement, merci. Mais je ne comprend pas pourquoi avec les pointeur ça ne fonctionnait pas alors que techniquement je ne fais pas de copie?
J'ai remplacer tous mes pointeurs par des références du coup.
Mais dans ta fonction pour bouger les cercles tu utilise un vecteur, or la personne plus haut me conseille d'utiliser des tableaux . Il y a une réelle différence?
Je pose beaucoup de question car je suis un novice et je suis plutôt curieux, j'aime apprendre. Merci de votre patience en tout cas
EDIT: une question qui peut te paraître bête mais pour déclarer le prototype je peut faire comment si je veux que "enum EDirection { HG_HD=0, HD_BD=1, BD_BG=2, BG_HG=3 };" soit dans la fonction main? car il ne reconnaitra pas encore EDirection à ce stade? Ou suis-je obliger de déclarer EDirection en variable globale? On m'avait conseillé de ne aps en utiliser.
- Edité par alexisbenoit 28 juillet 2017 à 19:59:00
A moins que tu ne saches précisément ce que tu fais et pourquoi les pointeurs seraient potentiellement plus adaptés que référence ou copie, ne les utilise pas.
Surtout que là, tu n'utilisais même pas des pointeurs "intelligents" de C++ (std::unique_ptr par exemple), mais des pointeurs nus, ce qui est encore plus horrible à gérer.
A noter qu'il en va de même pour la gestion de la mémoire:
Une règle d'or est de ne jamais utiliser new/delete sans précisément savoir ce que ça fait et pourquoi c'est mieux que laisser la librairie le gérer (STL ou une lib externe).
Ce n'était pas spécialement dirigé contre ton programme, mais contre une erreur que les débutants (et même les experts) font, qui consiste à gérer l'allocation mémoire soi-même (une variable créée et allouée avec new doit absolument être delete avant la fin du programme sinon fuite mémoire, et ça c'est problématique)
Peut-être que tu ne compiles pas avec au moins le standard 2011 (avec gnu g++ c'est l'option '-std=c++11' sans les guillemets) mais je te conseille d'utiliser un compilateur suffisamment à jour : gcc-6 ou gcc-7 avec l'option 'std=c++14' ou mieux si tu as un de ces deux derniers : -std=c++17
J'avais essayé la version tableau mais j'avais mis un '.' à la place de "->" je comprenais pas pourquoi ça ne fonctionnait pas.
Et pour la première version j'avais essayé : " std::vector<sf::CircleShape*>::iterator " après des recherche sur internet et ça ne fonctionnait pas non plus.
Du coup tu viens de corriger mes 2 essais, merci
Par contre dans la 3eme méthode j'aurais jamais trouvé.
Et re les gens, j’espère que vous avez passé un bon weekend-end,
Demain je reprendrais mon programme pour y rajouter des fonctionnalité comme un bouton pause, une musique de fond etc..., mais bref, du coup je voudrais revenir sur ma question de base qui est comment organiser ma ou mes classe? Combien devrais-je en faire?
J'ai pensé à une classe Créer ou je mettrais les fonction qui créent la fenêtre les cercle, le sprite etc... et une autre classe Gérer ou il y aurait la fonction pour gérer la souris, gérer le déplacement, compter le score, et afficher. Qu'en pensez vous?
Et re les gens, j’espère que vous avez passé un bon weekend-end,
Demain je reprendrais mon programme pour y rajouter des fonctionnalité comme un bouton pause, une musique de fond etc..., mais bref, du coup je voudrais revenir sur ma question de base qui est comment organiser ma ou mes classe?(1) Combien devrais-je en faire?(2)
(1) De la manière la "plus logique" pour te permettre de t'y retrouver
(2) autant que nécessaire que pour te permettre de représenter chaque nom (ou groupe nominal) utilisé dans ton analyse des besoins dans le code que tu vas écrire
J'ai pensé à une classe Créer ou je mettrais les fonction qui créent la fenêtre les cercle, le sprite etc... et une autre classe Gérer ou il y aurait la fonction pour gérer la souris, gérer le déplacement, compter le score, et afficher. Qu'en pensez vous?
Ce sont des termes beaucoup trop génériques que pour être effectivement utiles, car ils correspondent à de trop nombreuses responsabilités, qui mériteraient toutes d'être prises en charge par une classe distincte (*). En plus, les classes représentent des nom (tout comme n'importe quel type de donnée), et les verbes représentent des actions, et sont donc représentés dans le code par des fonctions.
Au pire, tu devrais au minimum choisir "Creator" ("créateur") et "manager" plutot que Creer et Gerer
(*) un petit bémol quand même : une classe Creator pourrait avoir du sens, si elle ressemble au patron de conception factory. Tu devras cependant veiller séparer clairement la création des différents "grand types de données" en autant de fabriques différentes
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
En recherche d'emploi.
Mon site web de jeux SDL2 entre autres : https://www.ant01.fr
En recherche d'emploi.
Mon site web de jeux SDL2 entre autres : https://www.ant01.fr
En recherche d'emploi.