IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Correction de mes exercices en C++ moderne


Sujet :

C++

  1. #121
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Pourtant je fais bien un tri croissant des cartes avant de lancer le std::set_difference ! Je comprends pas très bien cppreference, surtout les implémentations type, avec les first1, first2, *first++, et j'en passe. Il doit y avoir une histoire de lambda à rajouter avec les .first et .second mais je trouve pas :/
    En effet, il faut que tu donnes à set_difference le même critère de tri que celui que tu as utilisé pour sort. Par défaut, set_difference (comme std::sort), utilises l'opérateur < entre les différents éléments. Or l'opérateur < est défini pour les paires: c'est une comparaison lexicographique sur les deux éléments... Du coup set_difference aboutit à un autre ordre que celui utilisé par sort, ce qui provoque l'erreur.

    Attention par ailleurs, inserter va ajouter des cartes à la main, il faudra traiter ça convenablement!

    Je suis en train de me demander comment gérer la pioche des cartes du deck car dans ton code, tu tires les cartes directement dans le "int main" mais pour gérer 6 joueurs + les changements de carte, n'aurait-il pas été mieux de construire le deck via un vector et déplacer les carte déjà piocher dans un autre deck qui serait la défausse? Car la c'est chaud à gérer du coup avec un iterateur pour savoir où on en est ou alors j'ai pas bien compris? ^^
    C'est une très bonne idée. Il y a différentes options, 1 vecteur pour la donne et 1 pour la défausse en est une, ou bien une paire iterateur et array. Les deux ont des avantages et des inconvénients.
    Il vaut mieux écrire a.begin() ou std::begin(a)?
    std::begin(a) est plus générique. Il peut fonctionner avec un tableau C (comme int tab[10], par exemple), ce qui n'est pas le cas du begin fonction membre. Mais les deux sont valables dans le cas d'un vecteur.

  2. #122
    Membre averti Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Par défaut
    Hello!

    J'ai réglé mon problème avec set_difference:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    	std::set_difference(main.begin(), main.end(), nCarteTab.begin(), nCarteTab.end(), std::inserter(nouvMain, nouvMain.begin()), [](auto &a, auto &b)
    	{
    		return a.first < b.first;
    	});
    J'ai modifié tout les "a.begin()" en "std::begin(a)" afin que le code soit plus propre du coup. Maintenant il me reste à régler ce problème de pioche, j'ai essayé ma solution de passer le array en vector mais.. Ca chamboule tout et le compilateur veut absolument une taille de tableau constante x)

    EDIT: J'ai créé un iterateur general:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include "stdafx.h"
    #include <iostream>
    #include <utility>
    #include <array>
    #include <numeric>
    #include <algorithm>
    #include <random>
    #include <string>
    #include <vector>
    #include <functional>
    #include <iterator>
    auto itDeck = 0;
    const auto nbCarte = 52;
    const auto nbCarteMain = 5;
    const auto nbCarteParSigne = 13;
    const auto nbCouleur = 4;
    using Carte = std::pair<unsigned, unsigned>;
    using Deck = std::array<Carte,nbCarte>;
    using Hand = std::vector<Carte>;
    Puis je l'ai ajouté dans la fonction de création de main:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Hand creationMain(Deck tab) //Fonction qui créé une main de 5 carte en ordre croissant pour le Player 1
    {
     
    	Hand tab1(nbCarteMain);
    	std::copy_n(std::begin(tab) += itDeck, nbCarteMain, std::begin(tab1));
    	itDeck += nbCarteMain;
    	std::sort(std::begin(tab1), std::end(tab1), [](auto &a,auto &b)
    	{
    		return a.first < b.first;
    	});
    	return tab1;
    }
    Puis après dans la fonction qui change les carte par choix du joueur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    Hand changeCarte(Hand& main, Deck& deck) // Demande au joueur combien de carte il veut changer, les enleve de la main et pioche autant de carte
    {
    	auto nCarte = 0;
    	Hand nCarteTab;
    	std::cout << "Combien de carte voulez vous changer?" << std::endl;
    	do
    	{
    		std::cin >> nCarte;
    		if (nCarte > 4)
    		{
    			std::cout << "Desole, 4 cartes maximum" << std::endl;
    		}
    	} while (nCarte > 4);
     
    	for (auto x = 1; x <= nCarte; x++)
    	{
    		unsigned choix = 1;
    		std::cout << "Veuillez saisir une carte:" << std::endl;
    		do
    		{
    			std::cin >> choix;
    			if (choix > 5 || choix < 1)
    			{
    				std::cout << "Vous devez entrer un chiffre entre 1 et 5." << std::endl;
    			}
    		} while(choix > 5 || choix < 1);
    		nCarteTab.push_back(main[--choix]);
    	}
    	std::sort(std::begin(nCarteTab), std::end(nCarteTab), [](auto &a, auto &b)
    	{
    		return a.first < b.first;
    	});
    	std::cout << std::endl;
    	Hand nouvMain;	
    	std::set_difference(main.begin(), main.end(), nCarteTab.begin(), nCarteTab.end(), std::inserter(nouvMain, nouvMain.begin()), [](auto &a, auto &b)
    	{
    		return a.first < b.first;
    	});
    	std::copy_n(std::begin(deck) += itDeck, nCarte, std::back_inserter(nouvMain));
    	itDeck += nCarte;
    	std::sort(std::begin(nouvMain), std::end(nouvMain), [](auto &a, auto &b)
    	{
    		return a.first < b.first;
    	});
    	return nouvMain;
    }
    Et tout fonctionne impeccable, maintenant à toi de me dire si c'est bien ou si il ne faut pas faire comme ça ^^

  3. #123
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Eh bien si ça marche...

    En fait, c'est une bonne pratique d'éviter les variables globlales (comme cet itérateur "général"). C'est une solution qui fonctionne mais qui peut poser des problèmes si le programme s'agrandit. Tu peux jeter un oeil à https://fr.wikipedia.org/wiki/Variable_globale pour comprendre les raisons.

    Néanmoins il faut quelques outils pour se passer des variables globales, les voici, c'est la leçon n° 3!

    Les objets (le sujet est d'une complexité parfois excessive, il peut y avoir qqs simplifications)
    Un des problèmes les plus ardus du développement est de bien organiser son programme. Moins il est organisé, plus il est fragile et on est rapidement confronté à l'effet papillon: un petit changement par ici provoque une tempête imprévue par là-bas. La solution est de diviser les responsabilités: chaque unité du programme a ses responsabilités; le mieux est qu'elle n'en ait qu'une. Diviser son programme en fonctions est déjà un premier pas. On peut les tester séparément, être raisonnablement certain que, s'il y a un problème, il ne vient pas de celle qui a été testée. Mais une fonction, idéalement, prend des arguments, renvoie une valeur retour, mais ne se charge pas de la gestion des données ou des ressources.

    Les objets sont une unité de programmation qui permet de mettre en pratique ce principe de division des responsabilités de façon plus large et plus flexible que la fonction. Mettons que notre programme de poker soit à peu près achevé. La fonction main va devoir gérer des choses très différentes: l'inscription des joueurs, leur argent, les cartes déjà distribuées, les mises, déterminer qui est vainqueur, mettre dehors les joueurs qui n'ont plus d'argent, afficher les résultats, etc. Si l'on veut ajouter un nouvel aspect, par exemple changer d'interface, ajouter la possibilité de tricher ou de faire des emprunts à la banque, il va falloir modifier encore la fonction main et penser à le faire partout; le programme devient rapidement indigeste ou d'une complexité excessive. L'idée derrière la programmation orientée objet, c'est d'enfermer (on dit parfois encapsuler) dans les objets la logique d'une unité du programme; le reste du programme ne dialogue qu'avec l'interface de l'objet et, si on doit modifier l'intérieur de l'objet mais qu'on peut éviter de modifier l'interface, le reste du programme peut rester inchangé. Voici un bref exemple pour ajouter la possibilité d'emprunter à la banque, en comparant (de façon un peu caricaturale) les deux façons de faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    // sans objets
    int main() {
      // ...
      // on regarde qui a assez d'argent pour assister à la partie
      if (a_de_largent(players[i])) inscrire(players[i]);
      else {
        somme_neccessaire = argent(player[i]) - enchere;
        if (accorde_pret(banque, player[i], somme_necessaire) {
          argent(player[i]) += somme_necessaire;
        }
      }
      // on doit faire pareil pour le changement de cartes, puis à chaque étape des enchères
    }
     
    // avec objets
    // 1. objet Game
    void Game::run() {
      // ...
      notifier(encheres_joueurs);
      // idem aux autres stades
    }
     
    // 2. objet Bank
    void Bank::analyser_enchere(enchere) {
      if ( ! ( solde[enchere.joueur] > enchere.montant ) ) notifier(joueur_exclus);
    }
    Les objets en C++
    Pour définir un objet en C++, on utilise le mot-clé class:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class Joueur {
      // les différents membres de Joueur: soit des variables, soit des fonctions
    }; // ne pas oublier le ;

    Les mots-clés public, private et protected servent à indiquer qui a accès aux membres de la classe
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class Joueur {
      public: // tout le monde a accès aux parties publiques d'une classe
      Joueur(std::string name); // un constructeur: c'est une fonction qui a le nom de la classe et est appelée à la création d'un objet
     
      private:
      std::string name_; // une variable privée: elle n'est accessible qu'aux fonctions définies par la classe  
     
      protected:
      int make_id(); // une fonction protégée: elle est accessible aux fonctions définies par la classe et aux fonctions définies par les classes dérivées (on verra après)
    };

    Une classe peut hériter d'une autre classe:

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class Bot : Joueur { // Bot a accès aux membres publics et protégés de Joueur
      public:
        int calculer_enchere(const Hand& h);
    };

    Pour aller plus loin: http://cpp.developpez.com/faq/cpp/?p...s-en-Cplusplus

    Exercices:
    - Avec quelques classes peut-on modéliser une partie de poker? Donner une brève description de chacune des classes et si possible une interface.
    - Lire et comprendre cet article: https://fr.wikipedia.org/wiki/Observ..._conception%29

  4. #124
    Membre averti Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Par défaut
    Salut!

    Ca va prendre du temps pour que je répond à tes question car j'ai tout lu et c'est vraiment pas simple... J'avais déjà vu un peu le système de classe (poo) et je comprends globalement à quoi elles servent mais pour les détails, c'est compliqué ^^

    Pour ta première question, qu'entends tu par interface?

  5. #125
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Programmer c'est aussi ça, heureusement ou malheureusement, comme on veut... Ce n'est pas nécessaire pour l'instant de voir les détails de la POO, tu auras le temps ensuite. L'important, là, ce n'est pas la technique mais la conception d'ensemble. Comme fonctionnalités on veut:
    - des joueurs identifiés qui restent les mêmes ou non à travers les parties
    - des parties avec des systèmes d'enchères (c'est tout de même tout l'intérêt du poker)
    - un affichage des parties

    L'interface, ce sont les membres publics.
    Grosso modo on distingue:
    1) l'implémentation: elle doit être au maximum cachée du code client pour que l'on puisse la modifier sans conséquences
    2) l'interface: c'est le visage public d'une classe, ce que le reste du code va utiliser pour faire appel à elle

  6. #126
    Membre averti Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Par défaut
    Donc l'interface c'est un peu pareil que le constructeur qui appel la classe?

    Comment le connaitre sans avoir implémenter le contenu de la classe?

    - Des joueurs identifiés qui restent les mêmes ou non à travers les parties: Une classe à sémantique d'identité?
    - Des parties avec des systèmes d'enchères: Une classe à sémantique de valeur?
    - Un affichage des parties: Une classe abstraite?

  7. #127
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Donc l'interface c'est un peu pareil que le constructeur qui appel la classe?
    l'interface, c'est l'ensemble des méthodes publiques, pas uniquement le constructeur

    Comment le connaitre sans avoir implémenter le contenu de la classe?
    La question qu'il faut se poser, c'est : que peut faire ma classe? quels services doit-elle fournir? Pour prendre un exemple bête:

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Voiture {
      public:
      Voiture(std::string immatriculation);
      void accélère();
      void freine();
     
      private:
      // peu importe pour l'instant
    };
    - Des joueurs identifiés qui restent les mêmes ou non à travers les parties: Une classe à sémantique d'identité?
    - Des parties avec des systèmes d'enchères: Une classe à sémantique de valeur?
    - Un affichage des parties: Une classe abstraite?
    Je vois que tu as bossé la FAQ
    Commence par le plus simple, tu verras ensuite pour les sémantiques et tout ça!

  8. #128
    Membre averti Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Par défaut
    Ok alors voilà comment je vois les choses:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    //Classe pour le systeme des joueurs:
     
    class Joueur
    {
    	public:
    	Joueur(std::string nomJoueur); //Défini un nom pour le joueur
    	void modifArgent(); //Modifie l'argent du joueur
    	void modifScore(); //Modifie la valeur de la main du joueur
     
    	private:
    	int argent; //Un attribut pour stocker l'argent du joueur
    	int score; //Un attribut pour stocker les points du joueur
    };
     
    //Classe pour le systeme d'enchere:
     
    class Enchere
    {
    	public:
    	void augMise; //Augmente la mise
    	void dimMise; //Diminue la mise
    	void relancer; //Relancer une mise
    	void parler; //Pour check si pas de mise
    	void passer; //Abandonner
    	void upBlind; //Augmente les blind en fonction d'un critère défini
     
    	private:
     
    	int smallBlind; //Un attribut pour définir la petite blind
    	int bigBlind; //Un attribut pour définir la grosse blind
    	int pot; //Un attribut pour stocker la somme du pot
            int mise; //Un attribut pour la mise actuelle
     
    };
     
    //Classe pour l'interface du jeu:
     
    class UI
    {
    	// Pas la moindre idée de comment ca marche ^^
    };
    Pour l'interface, je sais vraiment pas comment ca fonctionne :/

  9. #129
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Il y a des bonnes idées mais je ne vois pas comment tu pourrais faire fonctionner cela en l'état.

    Quand je parlais des fonctionnalités, ce n'était pas pour dire qu'il fallait modeler les classes dessus: juste pour décrire ce que moi, client, j'attends du développeur que j'ai engagé.

    Pour ma part, je verrais plutôt une chose comme ça:
    - 1 classe joueur, qui contient les infos d'identification: un nom, un identifiant unique, une adresse mail, des choses comme ça
    - 1 classe banque, qui tient les comptes des joueurs, qui autorise les enchères et peut accorder des prêts
    - 1 classe partie, qui gère les étapes d'une partie
    - 1 classe distributeur, qui gère la distribution des cartes
    - 1 classe interface utilisateur. Ce serait une bonne idée de faire une classe abstraite et il faudra implémenter aussi une classe concrète, dans un premier temps pour une interface console
    - utiliser le pattern Observateur peut être une bonne idée pour faire communiquer ces classes

  10. #130
    Membre averti Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Par défaut
    D'accord en faite 100% du jeu passe par les classes? Et dans le main on manipule les interfaces seulement?

    Je pensais qu'on gardait quand même des fonctions standard hors classe.

    Pour le pattern observateur, faut que je buche ce truc car c'est pas simple a comprendre le code d'exemple sur le wiki.

  11. #131
    Membre averti Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Par défaut
    Salut Stend!

    Bon j'ai lu et relu le wiki du pattern observateur/Observable, j'ai aussi lu cette page http://come-david.developpez.com/tut...ge=Observateur qui m'a l'air d'avoir un code plus vieux mais qui m'a permis d'un peu mieux comprendre.

    J'ai compris la notion du pattern, à quoi ca sert mais j'ai vraiment du mal avec le code, il y a énormément de ligne que je ne comprends pas. Alors je sais pas si tu me demande de comprendre tout ça ou juste la notion mais je pense que je n'arriverais pas plus loin juste en lisant ces pages ^^'

    J'ai beaucoup de mal avec le "*", pointeur, iterateur et aussi les "::" puis comme tout les codes d'exemple utilise en général "using namespace std" dans le code je ne sais pas où ce trouve les fonctions std.. Enfin, c'est l'embrouille dans ma tête là x)

  12. #132
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Bon, on va faire par petits bouts, je te propose, c'est vrai que ça fait un gros morceau comme ça.

    Pour résumer les épisodes précédents, on a mis au point une partie de l'algorithmique. Il nous reste quelques algorithmes (pas les plus simples, d'ailleurs, à faire) et la conception plus générale du jeu. On va réfléchir dans un premier temps aux grandes données du jeu:
    1) c'est un je pour un seul joueur (ce ne serait pas très difficile de proposer plusieurs joueurs mais le problème serait d'assurer la confidentialité des cartes affichées à l'écran)
    2) il y a d'autres joueurs, mais ils ne sont pas humains. Il peut y avoir en tout 5 joueurs par partie: 5 cartes distribuées initialement + jusqu'à 4 cartes échangées par joueur = 9; 52 / 9 = 5 (en division entière).
    3) à l'écran d'accueil, le joueur indique: ses propres données (nom) et les données de la partie: nombres d'adversaires, montants minimal et maximal des enchères, etc.

    Puis on va se concentrer déjà sur la classe joueur. Il faut qu'elle permette de gérer de façon uniforme les joueurs humains et les joueurs gérés par l'ordinateur. Donc on va d'abord concevoir une interface commune; il y aura pour certaines fonctions des implémentations différentes.

    Quelle interface commune pour la classe Joueur?
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    class Joueur {
     
      public:
      std::string name();
      void place_bet(const Hand& h, std::vector<Bet>& bets) = 0; // une fonction abstraite
      void choose_cards_to_change(const Hand& h) = 0;
     
      protected:
      Joueur(const std::string& name) : name_(name) {} // le constructeur est protégé; il ne faut pas instancier directement une classe abstraite
     
      private:
      std::string name_;
     
    };

    Ensuite il y aura des classes concrètes: une classe pour le joueur géré par un humain, une classe pour les joueurs gérés par l'ordinateur. On va s'occuper de la classe gérée par l'ordinateur.
    Pour choisir l'enchère, il y a trois paramètres: l'évaluation de la main qu'on a (on va avoir tendance à parier plus si on a une meilleure main), les enchères des autres (si les autres font des grosses enchères on va avoir tendance à supposer qu'ils ont des bonnes cartes) et un facteur "arme psychologique": la tendance à bluffer et à considérer que les autres bluffent.

    Exercice 1: (moyen difficile)
    - écrire la fonction place_bet pour un joueur géré par l'ordinateur (NB: le premier élément de bets est la somme minimale à jouer au stade de la partie atteint, les suivants les enchères des autres joueurs).

    Exercice 2: (très difficile)
    - écrire la fonction choose_cards_to_change pour un joueur géré par l'ordinateur

  13. #133
    Membre averti Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Par défaut
    Salut Stend! Merci d'être encore là ^^

    Tu t'es trompé ou c'est un "using type" ici: void place_bet(const Hand& h, std::vector<Bet>& bets)

    Je dois écrire la fonction avec uniquement comme argument la main de l'IA et la valeur des enchères des autres? Comment savoir quel case correspond à quel joueur dans le vecteur? Cette fonction est lancée avant ou après avoir changée ses cartes? Comment gérer les tours? Si je veux que l'IA se couche, comment ca se passe?

    J'ai du mal a visualiser une IA avec seulement ses deux arguments... Du moins si mais elle me parait très limité.

  14. #134
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Salut Stend! Merci d'être encore là ^^
    Avec plaisir

    Tu t'es trompé ou c'est un "using type" ici: void place_bet(const Hand& h, std::vector<Bet>& bets)
    Bet c'est pari / enchère, en anglais, à toi d'adapter comme tu le veux: soit par un using, soit en créant une classe Enchere qui contient les informations qui te semblent nécessaires (on pourrait inclure la question du changement des cartes mais ça compliquerait les choses, commençons simple peut-être? mais à toi de voir)
    Je dois écrire la fonction avec uniquement comme argument la main de l'IA et la valeur des enchères des autres? Comment savoir quel case correspond à quel joueur dans le vecteur? Cette fonction est lancée avant ou après avoir changée ses cartes? Comment gérer les tours? Si je veux que l'IA se couche, comment ca se passe?

    J'ai du mal a visualiser une IA avec seulement ses deux arguments... Du moins si mais elle me parait très limité.
    Pour ce qui est des informations données, je suis d'accord qu'elles sont limitées mais c'est un début et il y a déjà pas mal de choses à faire:
    1) normaliser les enchères des uns et des autres par rapport à l'enchère minimale (par ex: on peut transformer une enchère par le résultat enchere/enchere_minimale)
    2) faire une sorte de barème pour déduire ce qu'a un joueur en fonction de l'enchère qu'il place
    3) modéliser les possibilités de bluffer ou de détecter le bluff de qqn d'autre (pour l'instant on peut faire au hasard, mais pourquoi pas en fonction d'un trait de caractère quand on aura avancé plus?)

    N'oublie pas de bien documenter ton code et de faire qqs tests.

    Quelles seraient tes idées pour aller plus loin?

    Sinon j'ai fait un petit corrigé pour l'exercice 2, si on reste relativement basique ce n'est pas si difficile. Voilà les règles les plus basiques que je propose:
    - si on a une suite ou une couleur on garde tout
    - si on a 5 cartes différentes, on garde la plus haute et on change les quatre autres
    - si on a des figures on change les cartes isolées
    Il faudrait rajouter, je pense:
    - si on a 5 cartes différentes, mais que quatre se suivent ou que quatre sont de la même couleur, on change la carte isolée

  15. #135
    Membre averti Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Par défaut
    En fait a la base dans le vecteur bets, je voyais une enchère et un pseudo mais vu que le premier élément du tableau c'est la blind, je visualise pas trop le truc. Je pensais à:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    using Bet = std::pair<std::string,unsigned int>; // Une paire d'un pseudo et d'une enchère.
    Mais si tu me parles de classe, forcement ca parait trop facile ma première solution. Ce qui me bloque c'est que tu m'as dis: "(NB: le premier élément de bets est la somme minimale à jouer au stade de la partie atteint, les suivants les enchères des autres joueurs)."

    Du coup je vois pas comment faire une classe enchère si le premier élément n'en est pas une. Sinon une classe enchere pourrait contenir:

    -Pseudo du joueur //Pour identifié a qui appartient cet enchère
    -Son enchère //Pour connaitre la valeur actuel de sa mise
    -Un bool pour savoir si l'échange de carte a était fait
    -Un bool pour savoir si le joueur est couché
    -La valeur de la blind
    -Le nombre de tour de table déjà effectué //Pour mieux guider l'IA
    -Le montant de son argent actuel //Permet de faire une comparaison entre les joueurs, beaucoup d'argent = plus de risque prit par l'IA

  16. #136
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Il n'y a pas de trop facile qui compte; le plus facile et le plus lisible c'est le mieux.
    Je trouve tes idées pour la classe Enchère pas mal du tout.
    Maintenant il faut maintenant tenter une implémentation!

  17. #137
    Membre averti Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Par défaut
    Salut Stend, j'ai buché encore un peu les classes grâce à un wiki, j'ai appris à utiliser this-> par la même occasion sans le vouloir (bien que je ne l'ai pas utilisé tout compte fait)

    Voici ma première ébauche d’implémentation de ma classe bet, le header bet.h:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    #ifndef BET_H
    #define BET_H
     
    #include "stdafx.h"
    #include <iostream>
    #include <string>
     
    class Bet
    {
    public:
    	//Construteurs
    	Bet();
    	Bet(std::string name, unsigned int bet, unsigned int money, unsigned int bigBlind, unsigned int nbTurn, bool changeCard, bool fold);
     
    	//Mutateurs et Accesseurs
    	void setName(std::string name);				//Permet de definir le nom de la classe dans l'attribut "name_"
    	void setBet(unsigned int bet);				//Permet de definir le montant de l'enchere dans l'attribut "bet_"
    	void setMoney(unsigned int money);			//Permet de definir les gains actuel du joueur dans l'attribut "money_"
    	void setBigBlind(unsigned int bigBlind);	//Permet de definir la grosse blind actuel dans l'attribut "bigBlind_"
    	void setNbTurn(unsigned int nbTurn);		//Permet de definir le nombre de tour d'enchere actuel dans l'attribut "nbTurn_"
    	void setChangeCard(bool changeCard);		//Permet de definir si oui ou non l'echange de carte a été effectué dans l'attribut "changeCard_"
    	void setFold(bool fold);					//Permet de definir si oui ou non le joueur est couché dans l'attribut "fold_"
    	std::string getName() const;				//Permet d'obtenir le pseudo du joueur de la classe de l'attribut "name_"
    	unsigned int getBet() const;				//Permet d'obtenir la valeur de l'enchere de l'attribut "bet_"
    	unsigned int getMoney() const;				//Permet d'obtenir la valeur des gains du joueur de l'attribut "money_"
    	unsigned int getBigBlind() const;			//Permet d'obtenir la valeur de la grosse blind de l'attribut "bigBlind_"
    	unsigned int getNbTurn() const;				//Permet d'obtenir la valeur du nombre de tour actuel de l'attribut "nbTurn_"
    	bool getChangeCard() const;					//Permet d'obtenir l'information du statut "cartes échangées/pas échangées" de l'attribut "changeCard_"
    	bool getFold() const;						//Permet d'obtenir l'information du statut "couché/pas couché" de l'attribut "fold_"
     
    	//D'autre méthode à venir en fonction de l'avancée du projet
     
    private:
    	std::string name_;			//Nom du joueur à qui appartient cette classe
    	unsigned int bet_;			//Montant de l'enchere
    	unsigned int money_;		//Montant des gains actuels du joueur
    	unsigned int bigBlind_;		//Montant de la grosse bling, minimum à encherir
    	unsigned int nbTurn_;		//Nombre de tour d'enchere déjà effectué dans la partie
    	bool changeCard_;			//True si l'échange de carte a déjà été effectué
    	bool fold_;					//True si le joueur est couché
    };
    #endif
    et le fichier source bet.cpp:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    #include "stdafx.h"
    #include <cmath>
    #include <iostream>
    #include "bet.h"
     
    Bet::Bet() : name_("none"), bet_(0), money_(0), bigBlind_(0), nbTurn_(0), changeCard_(false), fold_(false)
    {}
     
    Bet::Bet(std::string name, unsigned int bet, unsigned int money, unsigned int bigBlind, unsigned int nbTurn, bool changeCard, bool fold) :
    	name_(name), bet_(bet), money_(money), bigBlind_(bigBlind), nbTurn_(nbTurn), changeCard_(changeCard), fold_(fold)
    {}
     
    void Bet::setName(std::string name)
    {
    	name_ = name;
    }
     
    void Bet::setBet(unsigned int bet)
    {
    	bet_ = bet;
    }
     
    void Bet::setMoney(unsigned int money)
    {
    	money_ = money;
    }
     
    void Bet::setBigBlind(unsigned int bigBlind)
    {
    	bigBlind_ = bigBlind;
    }
     
    void Bet::setNbTurn(unsigned int nbTurn)
    {
    	nbTurn_ = nbTurn;
    }
     
    void Bet::setChangeCard(bool changeCard)
    {
    	changeCard_ = changeCard;
    }
     
    void Bet::setFold(bool fold)
    {
    	fold_ = fold;
    }
     
    std::string Bet::getName() const
    {
    	return name_;
    }
     
    unsigned int Bet::getBet() const
    {
    	return bet_;
    }
     
    unsigned int Bet::getMoney() const
    {
    	return money_;
    }
     
    unsigned int Bet::getBigBlind() const
    {
    	return bigBlind_;
    }
     
    unsigned int Bet::getNbTurn() const
    {
    	return nbTurn_;
    }
     
    bool Bet::getChangeCard() const
    {
    	return changeCard_;
    }
     
    bool Bet::getFold() const
    {
    	return fold_;
    }
    A mon avis j'en ai peut-être trop ou pas assez mis mais je poste surtout pour déjà évaluer mon implémentation actuel, savoir ce qui est mal ou bien car il faut écrire beaucoup et je veux pas prendre de mauvaise habitude...

    Au début mes attributs et les noms des objets de ma classe dans le constructeur était les mêmes, du coup j'utilisais this->. Puis j'ai regardé de nouveau ton code d'exemple, et je me suis aperçu que ta syntaxe (ex: name, name_) évitait d'utiliser this-> alors j'ai fais la même.. ^^

  18. #138
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    J'aime bien le travail de conception autour des données des enchères (je n'avais pas pensé à tous ces paramètres à prendre en compte!).

    Pour le design, voici ce que je pense:
    - si tu donnes accès libre aux données contenues par la classe, il n'est pas nécessaire de passer par une interface de get et de set.
    Tu peux faire une simple structure:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct Bet { // struct est comme class à la différence que ses membres sont publics par défaut (private par défaut dans le cas de la classe
      std::string name;
      unsigned bet, money, turn;
      bool fold, changeCard;
    };
    - une interface get/set n'a d'intérêt que si tu ressens le besoin de valider les données reçues (par ex, si tu requiers que le nom contienne au minimum x et au maximum y caractères, tu peux le vérifier dans le set)
    - il est possible en revanche de composer le classe Enchère à partir de sous-classes, par exemple:
    1) les infos relatives à la partie: turn, fold, changeCard et peut-être money (je ne sais pas jusqu'à quel point cette info est accessible dans une partie)
    2) les infos relatives à l'enchère: bet
    3) les infos relatives au joueur: le problème si tu choisis le nom du joueur comme critère, c'est que tu verrouilles cette logique d'identifiant par nom: on pourrait être plus efficace avec une logique d'identification par un id représenté par un entier (plus rapide à comparer, moins cher à stocker). De toute façon, on aura une classe Joueur qui pourrait avoir son propre opérateur d'égalité. Donc je choisirais un pointeur ou une référence sur le joueur pour être plus flexible.

    De toute façon, on en est encore au stade du prototypage: on fait une première ébauche pour voir ce qui pourrait marcher, on pourra peaufiner les détails plus tard. Tu peux conserver ton code ou partir sur la struct toute simple et faire une tentative d'implémentation de la fonction: tu pourras modifier ta classe Bet ou la signature de la fonction si tu trouves de meilleures idées en route. La meilleure façon d'apprendre, c'est de faire des erreurs et de les corriger.

  19. #139
    Membre averti Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Par défaut
    Le truc c'est que je pense que certaine donnée devrait peut-être être ailleurs. Par exemple:

    Classe joueur avec: money et fold car c'est lié au joueur et le définir dans une classe enchere me parait pas bon.

    Classe bet avec: bet (et certaines methode qui donnerait des moyennes de plusieurs autre données, exemple: bet / bigBlind, fold(true) / nbPlayer, nbTurn, etc)

    Les données turn, changCard et bigBlind serait dans la classe qui traiterait le déroulement d'une partie car c'est lié à la partie en elle même.

    Du coup mettre tout ca dans la classe bet me parait un peu mauvais? Ne pourrait-on pas plutôt se servir de pointeur dans la classe pour faire référence à d'autre donnée dans d'autre classe par exemple? Est-ce vraiment possible de créer une classe sans creer les autres en même temps, j'ai l'impression qu'elles vont toute se lié entre elle et c'est compliqué d'en créer une seule sans voir ce qu'il y aura dans les autres.

    Faire une classe player avec un max de données qui lui est lié et des classe fille type bet qui hérite de tout ca en const vu qu'on ne veut rien modifier et ca permet aussi de lier la classe au joueur sans avoir besoin de lui mettre d'ID ou de name.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Player
    {
    .....
    };
     
    class Bet : public Player
    {
    .....
    };
    Bon après il faut l'implémenter tout ca... C'est une autre histoire ^^

  20. #140
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Du coup mettre tout ca dans la classe bet me parait un peu mauvais? Ne pourrait-on pas plutôt se servir de pointeur dans la classe pour faire référence à d'autre donnée dans d'autre classe par exemple? Est-ce vraiment possible de créer une classe sans creer les autres en même temps, j'ai l'impression qu'elles vont toute se lié entre elle et c'est compliqué d'en créer une seule sans voir ce qu'il y aura dans les autres.
    Bienvenue dans le monde merveilleux du développement. Autant on peut donner des recettes ou des bonnes pratiques incontestables pour beaucoup de choses, autant ça devient tout de suite plus sujet à discussion pour la conception.
    Le mieux, à mon avis, pour l'instant, est de se lancer, de faire un prototype dont il faudra jeter une partie ensuite (et oui, c'est connu, c'est très désagréable de jeter du code et pourtant c'est comme cela qu'on progresse...). Ne te laisse pas paralyser par les doutes, avance un peu et tu auras plus de matière pour prendre une décision ensuite!

Discussions similaires

  1. Problème dans la page de correction d'un exercice?
    Par menoulette dans le forum Langage
    Réponses: 4
    Dernier message: 31/08/2009, 00h57
  2. Réponses: 11
    Dernier message: 04/02/2008, 21h37
  3. Correction d'un exercice en C++
    Par aniscpp dans le forum C++
    Réponses: 2
    Dernier message: 07/12/2006, 15h01
  4. besoin d'une correction sur un exercice.
    Par phakso dans le forum Algorithmes et structures de données
    Réponses: 13
    Dernier message: 03/03/2006, 11h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo