[C++] static bool tableau[13][4]

Résolu/Fermé
zzzer Messages postés 906 Date d'inscription dimanche 25 mai 2008 Statut Membre Dernière intervention 3 décembre 2023 - 16 sept. 2008 à 14:34
zzzer Messages postés 906 Date d'inscription dimanche 25 mai 2008 Statut Membre Dernière intervention 3 décembre 2023 - 17 sept. 2008 à 13:13
Bonjour,


J'ai une classe carte, dans laquelle j'ai un tableau statique bidimensionnel.

Etant donné qu'il est privé, j'ai fait une méthode reinitialiseTableau() qui est censée mettre toutes les valeurs du tableau à false.

Cependant, voici l'erreur qu'il me retourne lorsque j'essaye de compiler (dejaUtilisees est le nom de mon tableau) :
undefined reference to `carte::dejaUtilisees'
Voici ma classe (carte.h) :
class carte
{
    private :
        ...
        static bool dejaUtilisees[13][4]; // nombre, couleur

    public :

        ...
        static void reinitialiseTableau()
        {
            for (int i=0 ; i<13 ; i++)
                for  (int j=0 ; j<4 ; j++)
                    carte::dejaUtilisees[i][j] = false;
        }
};

Ainsi, dans mon main (main.cpp), je pensais pouvoir appeller simplement la méthode de cette façon :
carte::reinitialiseTableau();
Mais ça ne lui plaît pas...
Quelqu'un pourrait m'aider ?

Merci d'avance !

7 réponses

mamiemando Messages postés 33545 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 25 février 2025 7 829
16 sept. 2008 à 14:56
En fait je ne comprends pas pourquoi tu utilises des static et pourquoi ta classe s'appelle carte alors qu'en fait un carte_manager_t serait plus approprié.

Du coup plus besoin de static tu instancies un carte_manager_t et autant de carte_t que tu veux.

Bonne chance
-1
zzzer Messages postés 906 Date d'inscription dimanche 25 mai 2008 Statut Membre Dernière intervention 3 décembre 2023 181
16 sept. 2008 à 15:02
Je ne connais manager_t... (je suis en DUT Info et on ne nous en a jamais parlé)

En fait, je veux faire un jeu de poker, donc il faut que je sache quelle carte a déjà été utillisée ou non.
Donc si dejaUtilisees[12][1] est à true, alors la dame de coeur sera déjà sortie...

-1
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
16 sept. 2008 à 17:23
salut.
En effet, je trouve ça étrange d'utiliser des static, mais bon...
Toujours est il que ça devrait fonctionner.
Que veux tu dire par "ça ne lui plait pas" ?
-1
zzzer Messages postés 906 Date d'inscription dimanche 25 mai 2008 Statut Membre Dernière intervention 3 décembre 2023 181
16 sept. 2008 à 21:15
Eh bien, il me retourne l'erreur
undefined reference to `carte::dejaUtilisees'
lorsque j'essaye de le compiler...

-1
zzzer Messages postés 906 Date d'inscription dimanche 25 mai 2008 Statut Membre Dernière intervention 3 décembre 2023 181
16 sept. 2008 à 23:26
Eh bien, il me retourne l'erreur undefined reference to `carte::dejaUtilisees' lorsque j'essaye de le compiler...

-1
zzzer Messages postés 906 Date d'inscription dimanche 25 mai 2008 Statut Membre Dernière intervention 3 décembre 2023 181
16 sept. 2008 à 23:51
Il me retourne l'erreur undefined reference to `carte::dejaUtilisees' lorsque j'essaye de le compiler...

-1
zzzer Messages postés 906 Date d'inscription dimanche 25 mai 2008 Statut Membre Dernière intervention 3 décembre 2023 181
17 sept. 2008 à 07:32
Ça ne lui plaît pas car il ne passe pas à la compilation (erreur undefined reference to `carte::dejaUtilisees').

-1
mamiemando Messages postés 33545 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 25 février 2025 7 829
16 sept. 2008 à 21:39
Je ne connais manager_t...

Encore heureux c'est moi qui te suggère un nom plus cohérent avec ce que fait la classe. Ici tu ne décris pas une carte, tu décris un objet qui gère un jeu de carte.

Ensuite bien de nommer ses types avec un suffixe distinctif (genre "_t"). En particulier, ça permet d'écrire "plop_t plop". On peut ainsi déduire le type à partir du nom de la variable. C'est mieux que de mettre un nom bidon (comme "plop p"). Enfin ça c'est un conseil de programmation.

Ensuite je maintiens que tu n'as aucune vraie bonne raison de faire des statics ici. Enfin tu peux le faire mais c'est une mauvaise structure de code je trouve. Je te propose d'utiliser plutôt une std::map pour gérer tes cartes.
#include <map>
#include <set>
#include <string>
#include <ostream>
#include <iostream>

typedef std::string couleur_t;
typedef std::string rang_t;
typedef std::set<couleur_t> couleurs_t;
typedef std::set<rang_t> rangs_t;

class carte_t{
	protected:
		rang_t rang;
		couleur_t couleur;
	public:
		carte_t(const rang_t & rang0,const couleur_t & couleur0):
			rang(rang0),couleur(couleur0)
		{}

		inline rang_t get_rang() const{
			return rang;
		}

		inline couleur_t get_couleur() const{
			return couleur;
		}
};

inline bool operator <(const carte_t & x,const carte_t & y){
	return x.get_rang() < y.get_rang() ||
		(x.get_rang() == y.get_rang() && x.get_couleur() < y.get_couleur());
}

inline bool operator==(const carte_t & x,const carte_t & y){
	return x.get_rang() == y.get_rang() && x.get_couleur() == y.get_couleur();
}
inline std::ostream & operator<<(std::ostream & out,const carte_t & c){
	out << c.get_rang() << " de " << c.get_couleur();
	return out;
}

class manager_t{
	public:
		typedef std::map<carte_t,bool> etat_t;
	protected:
		etat_t etat;
		couleurs_t couleurs;
		rangs_t rangs;
	public:
		manager_t(
			const couleurs_t & couleurs0,
			const rangs_t & rangs0
		):
			couleurs(couleurs0),
			rangs(rangs0)
		{
			init_manager();
		}

		inline void init_manager(){
			std::set<couleur_t>::const_iterator
				couleurs_it (couleurs.begin()),
				couleurs_end(couleurs.end());
			for(;couleurs_it!=couleurs_end;++couleurs_it){
				std::set<rang_t>::const_iterator
					rangs_it (rangs.begin()),
					rangs_end(rangs.end());
				for(;rangs_it!=rangs_end;++rangs_it){
					carte_t c(*rangs_it,*couleurs_it);
					etat[c] = false;
				}
			}
		}

		inline void set_etat(const carte_t & c,bool state) {
			etat_t::iterator fit(etat.find(c));
			if (fit == etat.end()) throw; // cette carte n'existe pas
			etat[c] = state;
		}

		inline bool get_etat(const carte_t & c) const{
			etat_t::const_iterator fit(etat.find(c));
			if (fit != etat.end()) throw; // cette carte n'existe pas
			return fit->second;
		}

		inline const couleurs_t & get_couleurs() const{
			return couleurs;
		}

		inline const rangs_t & get_rangs() const{
			return rangs;
		}

		inline const etat_t & get_etat() const{
			return etat;
		}
};

inline std::ostream & operator <<(std::ostream & out,const manager_t & m){
	const manager_t::etat_t & etat = m.get_etat();
	manager_t::etat_t::const_iterator
		etat_it (etat.begin()),
		etat_end(etat.end());
	for(;etat_it!=etat_end;++etat_it){
		out << etat_it->first << '\t' << (etat_it->second ? "true" : "false") << std::endl;
	}
	return out;
}

int main(){
	couleurs_t couleurs;
	couleurs.insert("pique");
	couleurs.insert("coeur");
	couleurs.insert("carreau");
	couleurs.insert("trèfle");

	rangs_t rangs;
	rangs.insert("as");
	rangs.insert("2");
	rangs.insert("3");
	//...

	manager_t m(couleurs,rangs);
	std::cout << m;

	std::cout << "************" << std::endl;
	m.set_etat(carte_t("as","coeur"),true);
	std::cout << m;

	return 0;
}
ce qui donne :
2 de carreau    false
2 de coeur      false
2 de pique      false
2 de trèfle     false
3 de carreau    false
3 de coeur      false
3 de pique      false
3 de trèfle     false
as de carreau   false
as de coeur     false
as de pique     false
as de trèfle    false
************
2 de carreau    false
2 de coeur      false
2 de pique      false
2 de trèfle     false
3 de carreau    false
3 de coeur      false
3 de pique      false
3 de trèfle     false
as de carreau   false
as de coeur     true
as de pique     false
as de trèfle    false

L'avantage de ce code c'est que tu peux facilement créer un jeu de tarot, de 32 cartes, de 52 cartes, etc...

Bonne chance
-1
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
17 sept. 2008 à 08:57
Certes, ce n'est pas le plus élegant efficace etc. mais la question demeure, pourquoi n'arrive t'il pas à compiler ?
Je ne vois pas où est la faute.
-1

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
17 sept. 2008 à 09:04
après essai, j'ai le même problème que toi.
il semble que le fait de mettre le mot clé static fait que la déclaration de ton tableau n'alloue pas de mémoire. Il faut donc déclarer/créer ton tableau en dehors de la classe en ajoutant la ligne :
bool carte::dejaUtilisees[13][4];
Je pense que comme une variable statique est propre à la classe et non à l'objet (ce qui reviens à une variable globale) elle n'occupe pas de place mémoire dans chaque objet, il semble donc logique de la déclarer en dehors de la classe.
-1
mamiemando Messages postés 33545 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 25 février 2025 7 829
17 sept. 2008 à 10:12
En fait c'est expliqué ici :
https://cpp.developpez.com/faq/cpp/?page=Les-donnees-et-fonctions-membres-statiques

(comment initialiser une variable statique, pourquoi tu as une erreur de linkage etc...)

Bonne lecture
-1
zzzer Messages postés 906 Date d'inscription dimanche 25 mai 2008 Statut Membre Dernière intervention 3 décembre 2023 181
17 sept. 2008 à 10:47
J'ai déjà cherché à résoudre mon problème avec cette page, mais je n'y parviens pas...
Ils initialisent leur membre static dans le fichier .cpp, je n'en ai pas.
J'ai tenté de faire un static int plutôt qu'un tableau static. J'ai réussi à l'initialiser en plaçant l'initialisation en dehors de la classe, dans le fichier .h.
Mais quand je mets un for dans ce même fichier, cela ne passe pas à la compilation...

-1
mamiemando Messages postés 33545 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 25 février 2025 7 829
17 sept. 2008 à 11:21
Ben oui c'est normal. Une boucle for c'est dans une fonction. Il faudrait par exemple initialiser ta variable via une fonction, comme tu as voulu faire, mais tu as bien vu que ce n'était pas possible, c'est dit en toute lettre dans le lien que je t'ai donné.

C'est la raison pour laquelle je t'ai dit que l'approche par variable statique n'était pas bonne et que je t'ai proposé une méthode alternative. En gros ça ne sert à rien de s'acharner avec un tableau static car tu ne pourras jamais l'initialiser, car tu te prendras systématiquement une erreur de linkage.
-1
zzzer Messages postés 906 Date d'inscription dimanche 25 mai 2008 Statut Membre Dernière intervention 3 décembre 2023 181
17 sept. 2008 à 13:13
Arf, ok, merci, je vais voir avec ce que tu as mis alors...

-1