Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 18 sur 18
  1. #1
    Invité régulier
    Homme Profil pro
    Inscrit en
    décembre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : décembre 2012
    Messages : 11
    Points : 5
    Points
    5

    Par défaut Problème de logique de déplacement

    Bonjour,

    J'ai un projet de C++ pour cette année qui a pour but de "gérer" le déplacement d'une population de fourmis (Ouais assez bizarre comme projet )
    (Il y a des règles de déplacement pour les fourmis)

    Pour cela on a implémenté les classes suivantes:
    Etat (les états des cases du plateau : afin d'avoir leurs direction et de savoir si elles sont occupées ou pas)
    Plateau (Il contient la hauteur et la largeur du quadrillage, ainsi qu'un double pointeur de type Etat: Etat** tab)
    Fourmi (Instancier une fourmi dans le plateau)
    Fourmilière (Je suis pas encore arrivé à cette partie donc on en aura pas besoin)

    Je ne vais pas exposer la totalité de mes codes par peur que d'autres élèves de la même école puissent les réutiliser pour leurs faveurs. (Sachant que c'est un projet individuel et il y a des vérifications pour les cheaters).

    Alors mon problème se pose dans la logique de déplacement de ces fourmis qui se déplacent comme ainsi:



    TROU : case centrale du quadrillage.

    Mes classes:

    Etat.h

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #pragma once
    #include <iostream>
    using namespace std;
    class Etat
    {
    private:
    	bool occupe;
    	int direction;
    public:
    	Etat();
    	Etat(bool o, int d);
    	bool get_o();
    	int get_d();
    	void set_o(bool o);
    	void set_d(int d);
    	void modif_d();
    	void AfficherEtat();
    };
    Plateau.h

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #pragma once
    #include "Etat.h"
    #include <iostream>
    using namespace std;
     
    class Plateau
    {
     
    private:
     
    	int hauteur, largeur;
    	Etat** tab;
     
    public:
     
    	Plateau();
    	Plateau(int h, int l);
    	Plateau(Plateau const& CopiePlateau);
    	~Plateau();
    	void affiche();
    	Etat& get_case(int i, int j);
    	int get_h();
    	int get_l();
    	Plateau operator++ (int);
    	void NouvelleFourmi(int posX, int posY);
     
     
    };
    Fourmi.h

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #pragma once
    #include "Plateau.h"
    class Fourmi
    {
    private:
    	int i,j;
    	int d;
    public:
    	Fourmi(Plateau& plat);
    	int get_d();
    };
    Et finalement une partie de Plateau.cpp dans lequel j'ai écrit la logique de déplacement des 7 fourmis d'une façon manuelle:


    Code :
    1
    2
    3
    4
    void Plateau::NouvelleFourmi( int posX, int posY )
    {
    /* méthode manuelle */
    }
    x = axe des ordonnées.
    y = axe des abscisses.
    (Oui oui je sais, je les ai inversé je suis plus à l'aise comme ça )


    Est-il déjà possible de le faire avec des boucles ?

    Je vous remercie.

  2. #2
    Rédacteur/Modérateur
    Avatar de 3DArchi
    Inscrit en
    juin 2008
    Messages
    7 636
    Détails du profil
    Informations forums :
    Inscription : juin 2008
    Messages : 7 636
    Points : 13 095
    Points
    13 095

    Par défaut

    Salut,
    Citation Envoyé par saitron Voir le message
    ainsi qu'un double pointeur de type Etat: Etat** tab)
    J'espère qu'il ne s'agit pas d'une contrainte de l'énoncé de l'exercice car c'est une très mauvaise idée.

    Citation Envoyé par saitron Voir le message
    Etat.h

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #pragma once
    #include <iostream>
    using namespace std;
    class Etat
    {
    private:
    	bool occupe;
    	int direction;
    public:
    	Etat();
    	Etat(bool o, int d);
    	bool get_o();
    	int get_d();
    	void set_o(bool o);
    	void set_d(int d);
    	void modif_d();
    	void AfficherEtat();
    };
    direction mériterait un type plus explicite que int, par exemple une énumération. Dans une variable int, j'ai envie de mettre 0,1,2,3 mais aussi -2341234 ou encore 42. Cela a-t-il un sens ?
    La présence des accesseurs brise l'encapsulation. Ce qui montre probablement un problème de conception.
    A-tu vraiment besoin des deux constructeurs ? Vas-tu instancier Etat avec autre chose que ses valeurs par défaut ?

    On ne met pas de using namespace dans un fichier d'en-tête .h !!!

    Citation Envoyé par saitron Voir le message
    Plateau.h

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #pragma once
    #include "Etat.h"
    #include <iostream>
    using namespace std;
     
    class Plateau
    {
     
    private:
     
    	int hauteur, largeur;
    	Etat** tab;
     
    public:
     
    	Plateau();
    	Plateau(int h, int l);
    	Plateau(Plateau const& CopiePlateau);
    	~Plateau();
    	void affiche();
    	Etat& get_case(int i, int j);
    	int get_h();
    	int get_l();
    	Plateau operator++ (int);
    	void NouvelleFourmi(int posX, int posY);
     
     
    };
    C'est une très mauvaise idée d'utiliser un double pointeur nu. Regardes donc du côté de std::vector. D'autant que rien qu'en lisant ta classe, je suis sûr qu'il y a un bug (big 4).
    Pourquoi un constructeur par défaut Plateau(); ? Cela a-t-il un sens de construire un plateau par défaut (vide?) ?
    Si hauteur et largeur sont de type int (au moins dans l'interface publique de la classe) cela signifie que (-32056, 2147483647) est un couple de valeurs valides ?
    Encore une fois, les accesseurs trahissent un problème de responsabilité de la classe.
    La surcharge des opérateurs doit se faire en cohérence avec la sémantique usuelle de ceux-ci. Que signifie Plateau()++? Probablement rien. Je pense que Plateau operator++ (int); devrait être remplacée par une fonction au nom plus explicite. Se souvenir qu'avant d'être une prouesse technique, un code doit se lire par un humain.
    Il n'y a pas de constance (const) et en particulier dans Etat& get_case(int i, int j);. Déjà qu'un accesseur, c'est bof, mais retourner une référence non constante vers un état interne, c'est risquer un bannissement de la communauté des développeurs .

    Citation Envoyé par saitron Voir le message
    Fourmi.h

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #pragma once
    #include "Plateau.h"
    class Fourmi
    {
    private:
    	int i,j;
    	int d;
    public:
    	Fourmi(Plateau& plat);
    	int get_d();
    };
    Intuitivement, je dirais que Fourmi n'a pas besoin de connaître Plateau. je suis donc surpris de le voir dans son constructeur.
    Avoir des membres int i,j et int d n'aide pas du tout à comprendre le code. Donnes des noms compréhensibles (longs s'il le faut) que ce soit aux variables, aux types (mais en fait à tout ce que tu manipules)

    Citation Envoyé par saitron Voir le message
    x = axe des ordonnées.
    y = axe des abscisses.
    (Oui oui je sais, je les ai inversé je suis plus à l'aise comme ça )
    C'est souvent une très mauvaise idée d'inverser le sens de notions usuellement partagées. Un relecteur de ton code (par exemple un prof qui corrige) ne va rapidement plus rien comprendre à ce que tu veux faire même si tu lui a informé de ce changement au début de ton code. Même si je te dis que dorénavant, j'appelle une table chat, dix phrases en dessous tu risques de l'avoir oublier et ne plus rien comprendre à ce que je dis.

    Citation Envoyé par saitron Voir le message
    La méthode que j'ai développé me donne une logique de déplacement limitée aux 7 Fourmis. Je n'arrive pas à concevoir une logique de déplacement automatique - càd quelque soit le nombre de fourmi et quelque soit la taille du quadrillage - avec des boucles.
    Est-il déjà possible de le faire avec des boucles ?
    Oui. Mais commence par formuler ton raisonnement en français, comme tu pourrais l'expliquer à un voisin de chat. Tu expliques ce que tu attends d'une case et tu dois finir par quelque chose comme et 'ainsi de suite pour la suivante'. Tu auras ainsi trouver le cœur de ta boucle. Il ne te reste plus qu'à déterminer ce que tu fais au frontière du tableau (tu débordes sur le chat ?). Une fois ce raisonnement clairement exprimé, tu peux te poser la question de son implémentation. (Car pour l'instant on a surtout l'impression que tu cherches une solution toute faite). Prend une feuille et un stylo et retourne sur ton chat avant de commencer à développer.

  3. #3
    Invité régulier
    Homme Profil pro
    Inscrit en
    décembre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : décembre 2012
    Messages : 11
    Points : 5
    Points
    5

    Par défaut

    Salut, merci pour votre réponse.

    Citation Envoyé par 3DArchi Voir le message
    direction mériterait un type plus explicite que int, par exemple une énumération. Dans une variable int, j'ai envie de mettre 0,1,2,3 mais aussi -2341234 ou encore 42. Cela a-t-il un sens ?
    J'ai fait une condition qui oblige à la direction d'être comprise entre 1 et 4, donc impossible de saisir nombres invalides.

    Citation Envoyé par 3DArchi Voir le message
    La présence des accesseurs brise l'encapsulation. Ce qui montre probablement un problème de conception.
    A-tu vraiment besoin des deux constructeurs ? Vas-tu instancier Etat avec autre chose que ses valeurs par défaut ?
    Tout ce que j'ai implémenté est définie dans le cahier de charge.

    Citation Envoyé par 3DArchi Voir le message
    On ne met pas de using namespace dans un fichier d'en-tête .h !!!
    Je l'ai mit juste au cas où j'ai oublié quelques chose, ça ne tue pas le programme non plus

    Citation Envoyé par 3DArchi Voir le message
    C'est une très mauvaise idée d'utiliser un double pointeur nu. Regardes donc du côté de std::vector. D'autant que rien qu'en lisant ta classe, je suis sûr qu'il y a un bug (big 4).
    J'ai fait exactement ce qui est demandé dans le cahier de charge, toutefois, mon programme compile sans bug et sans la moindre erreur.

    Citation Envoyé par 3DArchi Voir le message
    Pourquoi un constructeur par défaut Plateau(); ? Cela a-t-il un sens de construire un plateau par défaut (vide?) ?
    Le constructeur par défaut initialise l'hauteur à 9 et la largeur à 15, puis ensuite déclare dynamiquement le tableau avec les dimensions choisie, et il initialise aussi toutes case à FALSE, et la direction à 1.

    Citation Envoyé par 3DArchi Voir le message
    La surcharge des opérateurs doit se faire en cohérence avec la sémantique usuelle de ceux-ci. Que signifie Plateau()++? Probablement rien. Je pense que Plateau operator++ (int); devrait être remplacée par une fonction au nom plus explicite. Se souvenir qu'avant d'être une prouesse technique, un code doit se lire par un humain.
    Plateau operator++ (int); ajoute 2 lignes au quadrillage au niveau de la hauteur et de la largeur. (C'est demandé dans le cahier de charge).

    Citation Envoyé par 3DArchi Voir le message
    Il n'y a pas de constance (const) et en particulier dans Etat& get_case(int i, int j);. Déjà qu'un accesseur, c'est bof, mais retourner une référence non constante vers un état interne, c'est risquer un bannissement de la communauté des développeurs .
    C'est exactement ce qui est demandé dans le cahier de charge, ça retourne une référence non constant, mais bon pour l'instant je n'ai pas peu de problème avec cette méthode, elle marche parfaitement.

    Citation Envoyé par 3DArchi Voir le message
    Intuitivement, je dirais que Fourmi n'a pas besoin de connaître Plateau. je suis donc surpris de le voir dans son constructeur.
    Avoir des membres int i,j et int d n'aide pas du tout à comprendre le code. Donnes des noms compréhensibles (longs s'il le faut) que ce soit aux variables, aux types (mais en fait à tout ce que tu manipules)
    Je vous rappelle encore une fois que je suis exactement ce qui est dans le cahier de charge, on nous a demandé de créer un constructeur de Fourmi qui prends en paramètre une référence vers un Plateau (cette méthode marche parfaitement, il n y a vraiment aucun problème ici).

    Citation Envoyé par 3DArchi Voir le message
    C'est souvent une très mauvaise idée d'inverser le sens de notions usuellement partagées. Un relecteur de ton code (par exemple un prof qui corrige) ne va rapidement plus rien comprendre à ce que tu veux faire même si tu lui a informé de ce changement au début de ton code. Même si je te dis que dorénavant, j'appelle une table chat, dix phrases en dessous tu risques de l'avoir oublier et ne plus rien comprendre à ce que je dis.
    Oui vous avez raison sur ce point, je vais le prendre en considération dans mes futurs projet. Pour ce projet on a une soutenance donc je ne pense pas que le prof va me blâmer pour ça.

    Citation Envoyé par 3DArchi Voir le message
    Oui. Mais commence par formuler ton raisonnement en français, comme tu pourrais l'expliquer à un voisin de chat. Tu expliques ce que tu attends d'une case et tu dois finir par quelque chose comme et 'ainsi de suite pour la suivante'. Tu auras ainsi trouver le cœur de ta boucle. Il ne te reste plus qu'à déterminer ce que tu fais au frontière du tableau (tu débordes sur le chat ?). Une fois ce raisonnement clairement exprimé, tu peux te poser la question de son implémentation. (Car pour l'instant on a surtout l'impression que tu cherches une solution toute faite). Prend une feuille et un stylo et retourne sur ton chat avant de commencer à développer.
    Je ne cherche pas une "réponse toute faite", j'ai passé plus d'une semaine à essayer d'écrire un algorithme mais quand je le fait sur code soit ça plante soit ça compile pas, mais quand j'écrivais le code je n'avais pas l'impression que je fesais bien les choses.
    J'ai juste besoin d'un petit "startup" après je pourrais le continuer tout seul.
    Tout de même, j'ai une petite idée sur les boucles qu'il y aura:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    	for (int di = 1; di <= 4; di++) // Les directions
    	{
    		for(int i=0; i<largeur; i++)
    		{
    			for (int j=0; j<hauteur; j++)
    			{
    				if (tab[posX][posY].get_d() == di && /* Je plante ici je sais pas quoi mettre dans les conditions. */)
    				{
    				}
    			}
    		}
    	}

  4. #4
    Invité régulier
    Inscrit en
    décembre 2010
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : décembre 2010
    Messages : 3
    Points : 6
    Points
    6

    Par défaut

    Tu es dans l'erreur. Absolument toutes les remarques formulées par 3DArchi sont fondées et cohérentes.

    Ce que tu trouves à répondre à cela est « ça ne tue pas le programme non plus », « mon programme compile sans bug et sans la moindre erreur. », ...

    Si tu avais essayé de chercher un peu sur le net, tu aurais découvert que placer une directive using à l'intérieur d'un fichier header, c'est plus que gravement déconseillé et réprimendé par le haut conseil décisionnel du C++.
    D'autre part, ce n'est parce que ton code compile et « semble » fonctionner (comment peux-tu être sûr à 100% qu'il n'y a pas de fuite mémoire, en utilisant tes pointeurs bruts ?), qu'il est pour autant correct. C'est une règle qu'il faut que tu comprennes. Ce n'est pas parce que ça compile sans erreur ni warning (et encore, tu devrais sûrement régler ton compilateur pour être moins permissif, avec quelques flags supplémentaires), que c'est correct et valide.

    En l'occurence, la quasi totalité des classes qui te sont demandées d'implémenter (et oui, je sais que cela t'es imposé, et je trouve ça proffondément stupide), ont de graves problèmes de sémantique et comportent des erreurs.
    Les accesseurs qui brisent l'encapsulation, les noms de fonctions membres hasardeux, les constructeurs par copie alors qu'ils ne devraient pas avoir lieu d'être, le manque flagrant de constness, la sémantique plus que louche de l'operator++, ...
    Bref, malheureusement, le code qui t'ai donné dans ce projet (je l'ai lu) est très mauvais, et tu devrais négocier pour ne pas avoir à le respecter.

  5. #5
    Invité régulier
    Homme Profil pro
    Inscrit en
    décembre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : décembre 2012
    Messages : 11
    Points : 5
    Points
    5

    Par défaut

    D'accord je vous remercie de m'avoir éclairci la situation.
    Je comprends donc que la conception du projet (Classes, attributs...) n'est pas bien faite.
    à votre avis, dois-je continuer avec leurs règles malgré ça ? où dois-je tout reprendre dès le début avec la bonne conception ?

    Concernant la logique de déplacement, j'ai pensé à ça mais je sais pas si c'est le bon début ou pas.

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    	for (int di = 1; di <= 4; di++) // Les directions
    	{
    		for(int i=0; i<largeur; i++)
    		{
    			for (int j=0; j<hauteur; j++)
    			{
    				if (tab[posX][posY].get_d() == di && /* Je plante ici je ne sais pas quoi mettre dans les conditions. */)
    				{
    				}
    			}
    		}
    	}

  6. #6
    Expert Confirmé Avatar de jabbounet
    Homme Profil pro frederic frances
    Consultant informatique
    Inscrit en
    juin 2009
    Messages
    1 911
    Détails du profil
    Informations personnelles :
    Nom : Homme frederic frances
    Âge : 39

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : juin 2009
    Messages : 1 911
    Points : 2 968
    Points
    2 968

    Par défaut

    Citation Envoyé par saitron Voir le message
    D'accord je vous remercie de m'avoir éclairci la situation.
    Je comprends donc que la conception du projet (Classes, attributs...) n'est pas bien faite.
    à votre avis, dois-je continuer avec leurs règles malgré ça ? où dois-je tout reprendre dès le début avec la bonne conception ?

    Concernant la logique de déplacement, j'ai pensé à ça mais je sais pas si c'est le bon début ou pas.

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    	for (int di = 1; di <= 4; di++) // Les directions
    	{
    		for(int i=0; i<largeur; i++)
    		{
    			for (int j=0; j<hauteur; j++)
    			{
    				if (tab[posX][posY].get_d() == di && /* Je plante ici je ne sais pas quoi mettre dans les conditions. */)
    				{
    				}
    			}
    		}
    	}
    je ne vais pas ajouter aux remarques pertinentes des autres mais pourquoi i et j ne sont pas présent dans la condition?
    Code :
    1
    2
     
    				if (tab[posX][posY].get_d() == di && /* Je plante ici je ne sais pas quoi mettre dans les conditions. */)
    bazar: http://www.improetcompagnie.com/publ...ctacles-6.html

    BÉPO la disposition de clavier francophone, ergonomique et libre: http://bepo.fr/wiki/Accueil

    Emacs Wiki: http://www.emacswiki.org/

    En attente de ce que produira: http://www.pushmid.com

  7. #7
    Invité régulier
    Homme Profil pro
    Inscrit en
    décembre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : décembre 2012
    Messages : 11
    Points : 5
    Points
    5

    Par défaut

    Justement c'est ici où je me plante, je n'arrive à pas déterminer les conditions avec i et j. ça devrait être quelque chose comme ça:


    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    	for (int di = 1; di <= 4; di++) // Les directions
    	{
    		for(int i=0; i<largeur; i++)
    		{
    			for (int j=0; j<hauteur; j++)
    			{
    				if (tab[posX][posY].get_d() == di && tab[posX-i][posY].get_o() == false /* Je plante ici je ne sais pas quoi mettre dans les conditions. */)
    				{
                                           // set occupe à true
    				}
    			}
    		}
    	}
    Je pense que je devrais juste manipuler des choses de ce genre:
    tab[posX-i][posY-j]
    tab[posX+i][posY-j]
    Je n'arrive pas à trouver le bon chemin mais pourtant j'ai l'idée comment cela devrait se faire.

    Bon ce n'est pas grave si je n'arrive à le faire avec cette méthode, j'ai au moins la méthode naïve que j'ai développé et avec laquelle je pourrais continuer mon projet.

    Merci quand même pour votre aide.

  8. #8
    Modérateur
    Avatar de koala01
    Profil pro Philippe Dunski
    Inscrit en
    octobre 2004
    Messages
    9 756
    Détails du profil
    Informations personnelles :
    Nom : Philippe Dunski
    Âge : 42

    Informations forums :
    Inscription : octobre 2004
    Messages : 9 756
    Points : 17 265
    Points
    17 265

    Par défaut

    Salut
    Citation Envoyé par saitron Voir le message
    J'ai fait une condition qui oblige à la direction d'être comprise entre 1 et 4, donc impossible de saisir nombres invalides.
    Le fait est que les énumérations présentent de très gros avantage par rapport à l'utilisation d'en entier + conditions :
    1. Il s'agit de constantes de compilation. Quand tu t'attaqueras à la programmation génériques (au template), tu en comprendras toute
    2. l'importance
    3. Cela améliore la vérification de types : Quand tu manipules un entier, tu peux passer au choix un char, un short ou un int, qui seront (pour les deux premiers) automatiquement convertis en entiers, alors que, lorsque tu manipule une énumération, tu ne peux passer qu'une des valeurs énumérées qui est déclarée dedans
    4. Le compilateur peut faire des vérifications sur les énumérations qu'il ne peut pas faire avec un entier (par exemple, il t'enverra au minimum un avertissement si tu n'as pas géré toutes les valeurs énumérées dans un switch... case)
    5. Les valeurs énumérées utilisent des identifiants qu'il ne tient qu'à toi de rendre explicites : tu auras beaucoup plus facile à te retrouver dans ton code en utilisant "gauche","haut","droite" et "bas" que 1, 2, 3 et 4
    6. Tu n'as pas besoin de connaitre la valeur exacte de la valeur énumérée, alors que tu dois retenir à quoi correspondent respectivement 1, 2, 3 et 4 et que cela rend donc la correction d'erreurs plus compliquée (vas t'en retrouver une partie du code ou tu as utilisé 3 au lieu de 1, alors que tu auras beaucou plus facile à retrouver "droite" a lors que tu voulais écrire "gauche" )

    Tout ce que j'ai implémenté est définie dans le cahier de charge.
    Le problème, c'est que le cahiers des charges contient d'énormes lacunes et problèmes de conception.

    Or, c'est, quelque part le rôle du développeur que d'attirer l'attention sur ce genre de lacunes

    J'ai presque envie de dire que, comme tu as une soutenance sur ce projet, tu devrais (pour autant que tu aies compris les raisons invoquées par 3DArchi, mais on peut toutes les expliciter en cas de besoin ) ton prof ne pourrait qu'être favorablement surpris si tu la commençais par un grand "désolé monsieur, mais je n'ai pas respecté le cahier des charges à cause des problèmes qu'ils contenait et pour les raisons suivantes".
    Je l'ai mit juste au cas où j'ai oublié quelques chose, ça ne tue pas le programme non plus
    Ne dis jamais cela

    Si l'on te déconseille fortement de placer une directive using namespace dans un fichier d'en-tête, c'est qu'il y a de bonnes raisons, entre autres, celle que tu n'a aucun contrôle sur les fichiers dans lesquels il sera inclus de manière indirecte.

    Les espaces de noms sont faits pour permettre d'éviter l'ambiguité des noms dans les projets importants!

    Imagines que tu veuilles rajouter une partie graphique à ton application. Tu pourrais parfaitement décider de définir une classe "vector", et, si tu inclus (ce qui risque d'arriver) le fichier d'en-tête dans lequel il y a la directive using namespace et celui dans lequel tu as défini ta propre classe vector, tu comprendras ta douleur
    J'ai fait exactement ce qui est demandé dans le cahier de charge, toutefois, mon programme compile sans bug et sans la moindre erreur.
    visiblement, non, vu que tu éprouves des difficultés à surpasser certaines limites qui n'ont absolument raison d'être
    Le constructeur par défaut initialise l'hauteur à 9 et la largeur à 15, puis ensuite déclare dynamiquement le tableau avec les dimensions choisie, et il initialise aussi toutes case à FALSE, et la direction à 1.
    Soit, mais je n'utiliserais pas un pointeur de pointeur pour ce faire...

    J'utiliserais un std::vector<int> que je déclarerais comme ayant 9*15 éléments (pour le constructeur par défaut) ou, si tu préfères, hauteur * largeur éléments
    Plateau operator++ (int); ajoute 2 lignes au quadrillage au niveau de la hauteur et de la largeur. (C'est demandé dans le cahier de charge).
    Plutôt que d'utiliser l'opérateur ++ qui as classiquement une signification propre, crées une fonction enlargeBy2 (par exemple) qui aura l'avantage d'être beaucoup plus explicite, et de ne pas mentir sur ce qui est fait

    C'est typiquement le genre de cas dans lequel ton professeur ne pourra qu'être d'accord avec toi quant au non respect du cahier des charges

    Dis toi que je fais du C++ de manière intensive depuis plus de cinq ans maintenant, et que je n'en ai pas encore fait le tour.

    Ce n'est donc pas avec quelques heures de cours par semaines étalées sur 3 à six mois que tu pourras considérer que tu le maitrise correctement.

    Par contre, le but de ton prof est, sans doute, de t'apprendre à réfléchir par toi-même.

    Montres lui que tu as sur réfléchir par toi meme et que tu as su prendre les bonnes décisions (en les justifiant, bien sur), il ne pourra jamais te buser pour cela
    C'est exactement ce qui est demandé dans le cahier de charge, ça retourne une référence non constant, mais bon pour l'instant je n'ai pas peu de problème avec cette méthode, elle marche parfaitement.
    Encore une fois, c'est une erreur du cahier des charges, ou à tout le moins un manque de précision.

    Si le cahier des charges indique simplement "renvoie une référence", alors, tu peux parfaitement considérer que tu le respecte en renvoyant "une référence constante", dans le sens où c'est simplement un manque de précision

    S'il exprime clairement qu'il faut renvoyer une "référence non constante", alors, c'est une erreur grave de conception, qu'il t'appartient de corriger (en justifiant, encore une fois la correction )
    Je vous rappelle encore une fois que je suis exactement ce qui est dans le cahier de charge, on nous a demandé de créer un constructeur de Fourmi qui prends en paramètre une référence vers un Plateau (cette méthode marche parfaitement, il n y a vraiment aucun problème ici).
    Et, heu... Elle sert à quoi dans ton code, parce que placer un argument inutile ne sert strictement à rien

    Encore une fois, ou bien tu n'as pas compris le but de cet argument, et là, tu es peut etre mal, ou bien, il s'agit d'une erreur de conception dont le mieux qu'on puisse espérer est que le prof s'attende à ce que tu la corrige
    Oui vous avez raison sur ce point, je vais le prendre en considération dans mes futurs projet. Pour ce projet on a une soutenance donc je ne pense pas que le prof va me blâmer pour ça.
    Tu sais, les conventions sont faites pour être respectées...

    C'est grace à ces conventions que deux personnes arrivent à se comprendre quand elles discutent, et il n'y a pas de raison qu'il en aille différemment quand elle le font par l'intermédiaire d'un code

    Je te conseilles donc très sérieusement de revoir ta position à ce sujet
    Je ne cherche pas une "réponse toute faite", j'ai passé plus d'une semaine à essayer d'écrire un algorithme
    Si tu as vraiment mis une semaine pour écrire cet algorithme, et sans vouloir être outrageant... hummm... bon, je vais garder le reste pour moi car je crains de l'être :calim2
    mais quand je le fait sur code soit ça plante soit ça compile pas,
    Alors, de deux choses l'une :

    Ou bien tu n'as pas choisi la bonne méthode pour représenter ton algorithme (personnellement, j'apprécie énormément le nassi-schneiderman, meme si d'aucuns pensent que cela fait trop "petit dessin"), car le propre d'un algorithme devrait d'être "en traduction directe"

    Ou bien il y a purement et simplement un problème dans ton algorithme, et alors, c'est à toi de revoir la logique
    mais quand j'écrivais le code je n'avais pas l'impression que je fesais bien les choses.:
    C'est déjà pas mal, car cela t'incite à poser des questions
    J'ai juste besoin d'un petit "startup" après je pourrais le continuer tout seul.
    Tout de même, j'ai une petite idée sur les boucles qu'il y aura:
    Le meilleur départ que tu puisses espérer est de respecter toutes les remarques de 3DArchi...

    Tu verras, ses conseils valent de l'or dans le cas présent
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    Rédacteur/Modérateur
    Avatar de 3DArchi
    Inscrit en
    juin 2008
    Messages
    7 636
    Détails du profil
    Informations forums :
    Inscription : juin 2008
    Messages : 7 636
    Points : 13 095
    Points
    13 095

    Par défaut

    Salut,
    Je peux comprendre que le cahier des charges contiennent des contresens et des absurdités. Ce n'était pas précisé dans le post original, c'est pourquoi je me suis permis de donner ces avis. (ceci dit, n'oublies pas alors de nous envoyer ton prof par ici qu'on lui passe un savon, il y en a marre de devoir reprendre la formation C++ from scratch dans le monde industriel)
    Il reste que je ne vois toujours pas ton algorithme énoncé en bête français. Donc j'ai du mal à savoir ce que tu veux implémenter et dont pouvoir essayer de t'aider.

  10. #10
    Invité régulier
    Inscrit en
    décembre 2010
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : décembre 2010
    Messages : 3
    Points : 6
    Points
    6

    Par défaut

    (ceci dit, n'oublies pas alors de nous envoyer ton prof par ici qu'on lui passe un savon, il y en a marre de devoir reprendre la formation C++ from scratch dans le monde industriel)
    Malheureusement l'école en question étale son cursus de C++ sur 48H, dont la moitié est dédiée à l'étude d'UML (oui, ça fait partie du même cursus). 24h de formation sur le C++, ils semblent visiblement estimer que c'est plus que suffisant pour le langage. D'autant que le support de cours en lui-même comporte le même genre d'erreurs (il commence par un module complet sur les différences entre le C, et le C++).

    Cependant, on ne peut en vouloir qu'à moitié au professeur, car le développement, ce n'est pas son métier. Le problème c'est qu'on ne s'improvise par professeur C++ et on évite de rédiger des cours sur le sujet si l'on est soit-même pas à l'aise avec le langage. Mais visiblement, ce n'est pas un état d'esprit que l'école semble partager.

    Bref saitron, je te conseille également soit de faire une version totalement différente du projet (je comprends pas pourquoi on incite à tuer la réflexion d'un étudiant en imposant une implémentation), soit, comme les autres te l'ont conseillé, à corriger les erreurs les plus grossières que comprend le cahier des charges.
    Étant donné que tu as une soutenance à préparer, tu pourras expliquer les raisons de ton choix à ton examinateur. Si par malheur il ne veut rien savoir et met une note que tu ne mérites pas car tu n'as pas respecté le cahier des charges, malgré tes explications, je me ferai une joie de lui expliquer le pourquoi de sa débilité

    Également, si ça peut t'aider, tu peux te baser sur une implémentation graphique que j'ai réalisée avec un ami, 4mi. La version graphique te montre les déplacements successifs des fourmis ainsi que la rotation des différentes cases.

  11. #11
    Invité régulier
    Homme Profil pro
    Inscrit en
    décembre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : décembre 2012
    Messages : 11
    Points : 5
    Points
    5

    Par défaut

    Octal, tu as vraiment compris la problématique de la situtation. De plus on a vu toutes les notions de C++ que vous m'aviez proposé y compris le std::vector, je devrais donc m'en renseigner avant de m'en servir.
    (Oui, je sais si on veut vraiment faire de l'informatique on ne doit pas attendre que le prof nous donne le tout, il faut qu'on cherche par nous même).

    J'ai fait une méthode manuelle (en mettant plusieurs conditions) qui contient la logique des déplacements des 7 premières fourmis j'ai essayé d'en déduire une logique à partir de cette dernière mais en vain tout ce que j'ai réussi à avoir de logique:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    	for (int di = 1; di <= 4; di++) // Les directions
    	{
    		for(int i=0; i<largeur; i++)
    		{
    			for (int j=0; j<hauteur; j++)
    			{
    				if (tab[posX][posY].get_d() == di && tab[posX-i][posY].get_o() == false /* Je plante ici je ne sais pas quoi mettre dans les conditions. */)
    				{
                                           // set occupe à true
    				}
    			}
    		}
    	}
    Je tiens vraiment à vous remercier de m'avoir éclairci les choses. Les remarques de 3DArchi sont bien claires à présent. Ensuite je ne veux vraiment pas déborder des consignes du cahier de charge par peur que je sois pénaliser pour ça (Ma première note en UML est moyenne.), de plus je n'aurait vraiment pas le temps de tout reprendre du début avec une nouvelle conception et tout, c'est pour cela que je vais essayer de continuer sur la même conception et avoir déjà un minimum rendu pour la soutenance.
    Bon après ce n'est pas grave, j'ai déjà une petite base de déplacement qui me permet de continuer mon projet.

    Merci à vous.

  12. #12
    Membre Expert
    Avatar de mitkl
    Homme Profil pro Timothée Bernard
    Étudiant
    Inscrit en
    février 2010
    Messages
    364
    Détails du profil
    Informations personnelles :
    Nom : Homme Timothée Bernard
    Âge : 23
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : février 2010
    Messages : 364
    Points : 1 088
    Points
    1 088

    Par défaut

    Ton algorithme n'est pas bon, si je devais simplifier le problème :
    - La fourmilière a un trou.
    - Les fourmis sortent par ce trou.
    - Une fourmi ne peut occuper qu'une case.
    - Quand une fourmi cherche une case libre, elle suit des directions précises, elle va d'abord au Nord, puis à l'Est, puis au Sud, puis à l'Ouest.
    - On répète ce processus par N.

    La base de ton algorithme c'est donc le trou, le reste de ton algorithme c'est trouver comment tourner autour de ce trou en suivant les directions Nord-Est-Sud-Ouest jusqu'à trouver une case libre pour y installer une fourmi.

    Donc si je devais résumer ça en pseudo-pseudo-code je commencerai déjà par une condition du type:

    Code :
    1
    2
    3
    4
    5
    TANT QUE une case libre n'est pas trouvé
     
      POUR directions de Nord à Ouest :
        SI case libre ALORS on arrête les boucles et on retourne les coordonnées
        SINON on monte d'une case au nord et on répète le même chemin
    Bien sûr l'implémentation est libre et comme tout le monde en algorithmique il y a des optimisations à faire mais dans un premier temps, garde à l'esprit de faire quelque chose de simple, essaie déjà avec le pseudo-code que je t'ai donné de récupérer des positions de cases libres autour d'une sortie. Et si cela marche, le reste (passer un cran dessus et répéter les directions) devrait suivre.
    Si vous ne savez toujours pas ce qu’est la récursivité, relisez cette phrase.

    Mon blog sur la programmation et l'informatique !

  13. #13
    Membre Expert
    Avatar de white_tentacle
    Inscrit en
    novembre 2008
    Messages
    1 292
    Détails du profil
    Informations forums :
    Inscription : novembre 2008
    Messages : 1 292
    Points : 1 999
    Points
    1 999

    Par défaut

    Attention, le pseudo-code décrit par mitkl ne répond pas à l’énoncé (ce n’est pas ça la logique de déplacement des fourmis). Par contre, la démarche est la bonne : c’est ce qu’il faut faire avant de commencer à coder. Je te laisse donc corriguer ce que mitkl a écrit.

    Sinon, concernant les erreurs de conception dans le cahier des charges, certes elles existent, certes tu peux les corriger (mais auquel cas, il faut que tu puisses expliquer ton choix, sinon ça pourrait être mal perçu par un examinateur « remis en cause »), mais je pense que ce qui est évalué ici c’est l’algorithme lui-même : focalise-toi dessus en premier.

  14. #14
    Expert Confirmé Avatar de jabbounet
    Homme Profil pro frederic frances
    Consultant informatique
    Inscrit en
    juin 2009
    Messages
    1 911
    Détails du profil
    Informations personnelles :
    Nom : Homme frederic frances
    Âge : 39

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : juin 2009
    Messages : 1 911
    Points : 2 968
    Points
    2 968

    Par défaut

    Citation Envoyé par white_tentacle Voir le message
    Sinon, concernant les erreurs de conception dans le cahier des charges, certes elles existent, certes tu peux les corriger (mais auquel cas, il faut que tu puisses expliquer ton choix, sinon ça pourrait être mal perçu par un examinateur « remis en cause »), mais je pense que ce qui est évalué ici c’est l’algorithme lui-même : focalise-toi dessus en premier.
    C'est là ou il faudra être diplomate surtout si le prof n'aime pas être remis en question. suggère des améliorations (positif) plutôt que d'indiquer des erreurs (négatif)...

    n'hésite pas a t'appuyer sur des livres tel que
    http://www.amazon.com/Coding-Standar.../dp/0321113586
    les prof aiment bien ça en général.


    il existe aussi en version française, par exemple pour l'opérateur++ cité plus haut
    j'ai le chapitre suivant "Préservez la sémantique naturelle des opérateurs surchargés" dans la version que j'ai chez moi.

  15. #15
    Invité de passage
    Inscrit en
    mars 2012
    Messages
    1
    Détails du profil
    Informations forums :
    Inscription : mars 2012
    Messages : 1
    Points : 0
    Points
    0

    Par défaut

    Revoit tous tes cours , réfléchit un peu , et arrete de copier le ficher excel de poitier, ta un pdf très bien expliqué.

  16. #16
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    juin 2012
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : juin 2012
    Messages : 852
    Points : 1 740
    Points
    1 740

    Par défaut

    Citation Envoyé par koala01 Voir le message
    Soit, mais je n'utiliserais pas un pointeur de pointeur pour ce faire...

    J'utiliserais un std::vector<int> que je déclarerais comme ayant 9*15 éléments (pour le constructeur par défaut) ou, si tu préfères, hauteur * largeur éléments
    un vector< vector<int> > est préférable ici je pense pour éviter le déplacement de pas mal d'éléments dans le vector lors du redimensionnement de la grille.

    Sinon quelque chose qui n'a pas été dit jusque la : il y à 2 méthodes pour trouver la position des fourmis
    * Dérouler l'algo normalement jusqu'a trouver une case libre pour chaque fourmis
    * Calculer la position des 20/30 premières fourmis et en déduire une fonction mathématique qui donnera la position a partir du numéro de fourmis (l'algo semble assez simple ici pour réussir a extraire une fonction, mais ça peut poser quelques problèmes lorsque des fourmis sont présentes jusqu'aux bords de la grille -> pas facile à prendre en compte)

  17. #17
    Modérateur
    Avatar de koala01
    Profil pro Philippe Dunski
    Inscrit en
    octobre 2004
    Messages
    9 756
    Détails du profil
    Informations personnelles :
    Nom : Philippe Dunski
    Âge : 42

    Informations forums :
    Inscription : octobre 2004
    Messages : 9 756
    Points : 17 265
    Points
    17 265

    Par défaut

    Citation Envoyé par Iradrille Voir le message
    un vector< vector<int> > est préférable ici je pense pour éviter le déplacement de pas mal d'éléments dans le vector lors du redimensionnement de la grille.
    Je comprends ton raisonnement, mais je peux t'assurer d'expérience que les collections de collections de donnée sont rarement ce qui se fait de plus efficace ni de plus facile à manipuler

    Si encore on partait du principe de redimensionnements "à tout va" et en quasi permanence, je reverrais peut être mon jugement, mais ici, on peut se dire qu'il reste malgré tout suffisamment marginal pour qu'il ne soit pas trop nécessaire de s'en inquiéter dans un premier temps
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  18. #18
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    juin 2012
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : juin 2012
    Messages : 852
    Points : 1 740
    Points
    1 740

    Par défaut

    Niveau efficacité on est d'accord, il n'y aura probablement pas assez de redimensionnement pour combler le temps perdu par l'utilisation d'un vector de vector (données non contiguës en mémoire)

    Je proposais ça pour la facilité d'utilisation (-> redimensionnement simple de la grille)

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •