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. #81
    Membre du Club 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
    Points : 52
    Points
    52
    Par défaut
    Hello!

    Ok, après avoir lu ton explication, j'ai mieux compris ma synthaxe du premier exo et je l'ai amélioré.

    Voilà le début de l'exo suivant, j'ai réussi à faire la fonction qui créé une main des 5 premières cartes du deck et dans l'ordre croissant:

    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
    #include <iostream>
    #include <utility>
    #include <array>
    #include <numeric>
    #include <algorithm>
    #include <random>
    #include <string>
     
    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>;
     
    Carte& operator++(Carte& p) //Ajoute un operateur ++ pour la fonction std::iota qui est appelé dans la fonction "creationDeck"
    {
    	++p.first;
    	++p.second;
    	return p;
    }
     
    auto creationDeck() //Creation d'un array de 52 emplacements qui contient chacun une paire de deux unsigned int
    {
    	Deck tab;
    	std::iota(std::begin(tab), std::end(tab), Carte());
    	std::transform(std::begin(tab), std::end(tab), std::begin(tab), [](Carte c)
    	{
    		c.first %= nbCarteParSigne;
    		c.second %= nbCouleur;
    		return c;
    	});
    	std::sort(std::begin(tab), std::end(tab));
    	return tab;
    }
     
    void melangerCarte(Deck &tab) //Fonction de mélange aleatoire
    {
    	std::random_device random;
     
    	std::shuffle(std::begin(tab), std::end(tab), random);
    }
     
    void couperCarte(Deck &tab) //Fonction qui coupe les carte en deux
    {
    	std::rotate(tab.begin(), tab.begin() + 27, tab.end());
    }
     
    void afficherCarte(Carte c) //Fonction qui affiche le nom d'une carte
    {
    	static std::array<std::string, nbCarteParSigne> numero = { "Deux","Trois","Quatre","Cinq","Six","Sept","Huit","Neuf","Dix","Valet","Dame","Roi","As" };
    	static std::array<std::string, nbCouleur> couleur = { "coeur","carreau","pique","trefle" };
     
    	std::cout << numero[c.first] << " de " << couleur[c.second] << std::endl;
    }
     
    std::array<Carte, nbCarteMain> creationMainAvecTri(Deck tab)
    {
    	std::array<Carte, nbCarteMain> tab1;
    	std::copy_n(tab.begin(), 5, tab1.begin());
    	std::sort(tab1.begin(), tab1.end(), [](const auto &a,const auto &b)
    	{
    		return a.first < b.first;
    	});
     
    	return tab1;
    }
     
    int main()
    {
    	auto jeuDeCarte = creationDeck(); //Crétion du jeu de carte dans un array en appelant la fonction "creationDeck"
    	melangerCarte(jeuDeCarte); //Melange les cartes aléatoirement en appelant la fonction "melangerCarte"
    	couperCarte(jeuDeCarte); //Coupe le jeu de carte au milieu en appelant la fonction "couperCarte"
     
    	auto main = creationMainAvecTri(jeuDeCarte); //Création d'une main des 5 cartes du debut du tableau "jeuDeCarte"
     
    	std::for_each(std::begin(main), std::end(main), [](Carte c) { std::cout << '(' << c.first << ',' << c.second << ") "; });
     
    	return 0;
    }
    Pour la fonction std::all_of, depuis ce matin je cherche à la faire fonctionner mais j'y arrive pas.. J'arrive pas trop à savoir comment
    gérer ca dans la lambda. J'arrive avec une condition "if" à faire ce que tu demande mais pas avec std::all_of

    J'ai du mal a lire les lambdas aussi, je comprend pas trop comment les arguments des lambda sont initialisé. Avec les fonction standard,
    lors de l'appel de la fonction on les marque entre les parenthèses mais dans les lambdas on ne le fait nul part, du coup j'ai un peu de mal

  2. #82
    Membre chevronné

    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
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Very good! Et bravo pour ta persévérance!

    Une petite suggestion, maintenant que tu as une fonction pour afficher une carte, tu devrais l'utiliser dans ta boucle for_each

    Pour la fonction std::all_of, depuis ce matin je cherche à la faire fonctionner mais j'y arrive pas.. J'arrive pas trop à savoir comment
    gérer ca dans la lambda. J'arrive avec une condition "if" à faire ce que tu demande mais pas avec std::all_of

    J'ai du mal a lire les lambdas aussi, je comprend pas trop comment les arguments des lambda sont initialisé. Avec les fonction standard,
    lors de l'appel de la fonction on les marque entre les parenthèses mais dans les lambdas on ne le fait nul part, du coup j'ai un peu de mal
    Je suis d'accord, il faut s'habituer un peu. Tu as trois composants dans une fonction lambda:
    1) le composant "capture du contexte"
    2) le composant arguments
    3) le corps de la fonction

    1. capture du contexte: c'est un point très important et très puissant des fonctions lambda: tu peux "capturer" des variables qui ne sont pas définies dans la fonction lambda mais dans la fonction où elle est appelée. Voilà comment on pourrait réécrire la fonction std::iota, par exemple:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // signature simplifiée
    using Iterator = std::vector<unsigned>::iterator; // notre iota ne fonctionnera que pour un std::vector<unsigned>
    void iota(Iterator first, Iterator last, unsigned init) {
      std::for_each(first, last, [&init](auto& u) { u = init++; }); //[&init] : on a pris une référence sur init, qui est extérieur à la fonction lambda, et qui sera pourtant incrémenté par la fonction lambda
    }
    Indice: ce genre de capture est utile pour rechercher si la main contient une couleur (toutes les cartes de la même couleur) ou une suite.

    2) arguments: tu as deux possibilités:
    tu peux écrire les arguments exactement comme pour une fonction normale:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    std::for_each(first, last, [&init](unsigned& u) { u = init++; });
    tu peux demander au compilateur d'inférer les types à ta place en utilisant auto

    3) le corps de la fonction ne diffère pas tellement d'une fonction normale. Il y a certains cas où on ne peut pas utiliser une lambda, mais ne t'en préoccupe pas pour le moment.

    Si tu n'arrives pas à utiliser l'algorithme, écris ta fonction sans. L'intérêt de l'algorithme est qu'il est plus concis, écrit par des développeurs hyper pointus, et qu'on voit directement le sens de ce qui est fait, tandis qu'il faut le reconstituer quand on voit une boucle. Si l'algorithme t'empêche d'avancer, avance à ta façon. J'ai écrit une petite correction, tu pourras comparer ton code avec à la fin.

  3. #83
    Membre du Club 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
    Points : 52
    Points
    52
    Par défaut
    J'ai trouvé pour la couleur avec std::all_of! Enfin je pense.. ^^ Par contre je pensais avoir trouvé pour la suite mais ca ne marche pas...

    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
    82
    83
    84
    85
    86
    87
    88
    89
    #include <iostream>
    #include <utility>
    #include <array>
    #include <numeric>
    #include <algorithm>
    #include <random>
    #include <string>
     
    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>;
     
    Carte& operator++(Carte& p) //Ajoute un operateur ++ pour la fonction std::iota qui est appelé dans la fonction "creationDeck"
    {
    	++p.first;
    	++p.second;
    	return p;
    }
     
    auto creationDeck() //Creation d'un array de 52 emplacements qui contient chacun une paire de deux unsigned int
    {
    	Deck tab;
    	std::iota(std::begin(tab), std::end(tab), Carte());
    	std::transform(std::begin(tab), std::end(tab), std::begin(tab), [](Carte c)
    	{
    		c.first %= nbCarteParSigne;
    		c.second %= nbCouleur;
    		return c;
    	});
    	std::sort(std::begin(tab), std::end(tab));
    	return tab;
    }
     
    void melangerCarte(Deck &tab) //Fonction de mélange aleatoire
    {
    	std::random_device random;
     
    	std::shuffle(std::begin(tab), std::end(tab), random);
    }
     
    void couperCarte(Deck &tab) //Fonction qui coupe les carte en deux
    {
    	std::rotate(tab.begin(), tab.begin() + 27, tab.end());
    }
     
    void afficherCarte(Carte c) //Fonction qui affiche le nom d'une carte
    {
    	static std::array<std::string, nbCarteParSigne> numero = { "Deux","Trois","Quatre","Cinq","Six","Sept","Huit","Neuf","Dix","Valet","Dame","Roi","As" };
    	static std::array<std::string, nbCouleur> couleur = { "coeur","carreau","pique","trefle" };
     
    	std::cout << numero[c.first] << " de " << couleur[c.second] << std::endl;
    }
     
    std::array<Carte, nbCarteMain> creationMainAvecTri(Deck tab) //Fonction qui créé une main de 5 carte en ordre croissant et qui detecte si il y a une couleur ou une suite
    {
    	std::array<Carte, nbCarteMain> tab1;
    	std::copy_n(tab.begin(), 5, tab1.begin());
    	std::sort(tab1.begin(), tab1.end(), [](const auto &a,const auto &b)
    	{
    		return a.first < b.first;
    	});
     
    	if (std::all_of(tab1.cbegin(), tab1.cend(), [tab1](Carte c) { return c.second == tab1[0].second; }))
    	{
    		std::cout << "Vous avez une couleur!" << std::endl << std::endl;
    	}
     
    	else if (std::all_of(tab1.cbegin(), tab1.cend(), [tab1](Carte c) { auto x = tab1[0].first; return c.first == x++; }))
    	{
    		std::cout << "Vous avez une suite!" << std::endl << std::endl;
    	}
    	return tab1;
    }
     
    int main()
    {
    	auto jeuDeCarte = creationDeck(); //Crétion du jeu de carte dans un array en appelant la fonction "creationDeck"
    	//melangerCarte(jeuDeCarte); //Melange les cartes aléatoirement en appelant la fonction "melangerCarte"
    	//couperCarte(jeuDeCarte); //Coupe le jeu de carte au milieu en appelant la fonction "couperCarte"
     
    	auto main = creationMainAvecTri(jeuDeCarte); //Création d'une main des 5 cartes du debut du tableau "jeuDeCarte" puis la tri et detecte si il y a une suite et/ou une couleur
     
    	std::for_each(std::begin(main), std::end(main), [](Carte c) {afficherCarte(c);});
     
    	return 0;
    }

    Et je pense avoir compris pour les lambdas, a voir si sur les prochain exo ca marche! En parlant des prochaines étapes,
    j'ai besoin de détail sur la consigne: "Ecrire une fonction qui divise la main en un vecteur de mains où les cartes sont identiques:"

  4. #84
    Membre chevronné

    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
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Yes c'est bon pour la couleur!! Pour la suite tu y es presque! Le problème c'est x est initialisé à tab1[0].first à chaque fois que la fonction lambda est appelée. Il faut que tu trouves un moyen d'initialiser une seule fois x (indice: en dehors de la lambda c'est mieux...). Je te mets un extrait de la correction en fin de message, pour que tu puisses comparer quand tu seras satisfait de la solution.

    j'ai besoin de détail sur la consigne: "Ecrire une fonction qui divise la main en un vecteur de mains où les cartes sont identiques:"
    Là tu as déjà pu déterminer s'il y avait une suite et/ou une couleur. Maintenant il faut déterminer l'existence d'autres figures: paires, brelans, carrés, etc. Ces figures ont en commun qu'elles sont constituées de groupes de cartes identiques: carré = 1 groupe de 4 cartes identiques, full = 1 groupe de trois cartes identiques + 1 groupe de deux cartes identiques, etc.
    Donc l'idée c'est de séparer la main de 5 cartes en groupes de cartes identiques. Par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Hand h = { {0,1}, {0,2}, {1,1}, {1,2}, {9,3} }; // la main de départ
    std::vector<Hand> result = { { {0,1}, {0,2} }, { {1,1}, {1,2} }, { {9,3} } }; // le vecteur d'arrivée
    Est-ce que c'est plus clair?

    /////////// SPOILER ////////////////

    Voici un extrait de la correction, à regarder quand tu le juges opportun:

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        std::sort(std::begin(hand), std::end(hand), [](auto&& a, auto&& b) { return a.first > b.first; });
        auto straight_flush_score = 0u;
        if ( std::all_of(std::begin(hand)+1, std::end(hand), [=](auto&& c) { return c.second == std::begin(hand)->second; }) ) {
            straight_flush_score += 8;
        }
        auto first = hand.begin()->first;
        if ( std::all_of(std::begin(hand)+1, std::end(hand), [&first](auto&& c) { return c.first == --first; }) ) {
            straight_flush_score += 7;
        }

  5. #85
    Membre du Club 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
    Points : 52
    Points
    52
    Par défaut
    Ok donc si je met la variable x en dehors, je la capture en contexte! C'est bien ça? J'ai passé mon array en vector pour mieux aller avec l'exo d’après, c'est pas bête ou inutile? ^^

    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
    std::vector<Carte> creationMainAvecTri(Deck tab) //Fonction qui créé une main de 5 carte en ordre croissant et qui detecte si il y a une couleur ou une suite
    {
     
    	std::vector<Carte> tab1(nbCarteMain);
    	std::copy_n(tab.begin(), 5, tab1.begin());
    	std::sort(tab1.begin(), tab1.end(), [](const auto &a,const auto &b)
    	{
    		return a.first < b.first;
    	});
     
    	auto x = tab1[0].first;
    	if (std::all_of(tab1.cbegin(), tab1.cend(), [tab1](Carte c) { return c.second == tab1[0].second; }))
    	{
    		std::cout << "Vous avez une couleur!" << std::endl << std::endl;
    	}
    	else if (std::all_of(tab1.cbegin(), tab1.cend(), [&x](Carte c) {return c.first == x++; }))
    	{
    		std::cout << "Vous avez une suite!" << std::endl << std::endl;
    	}
    	return tab1;
    }
    Si non pour l'exo d’après, pour la consigne c'est bien ce que j'avais compris du coup! Mais, je vois pas trop le rapport avec std::accumulate qui additionne
    le contenu d'un vecteur avec une valeur d'initialisation optionnelle. A moins que j'ai mal compris sa fonction..

    PS: Tu as les balise [spoiler][/spoiler ] pour cacher du texte, j'ai failli lire la solution

  6. #86
    Membre chevronné

    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
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Yes c'est bon! Mais il y a une petite erreur (cela dit j'ai fait exactement la même): pour les lambdas qui capturent la main, il faudrait une capture par référence pour éviter de la copier. En fait il y en a une autre, c'est qu'on peut avoir une couleur et une suite en même temps ("quinte flush")

    Merci pour la balise spoiler, un moment que je suis sur le forum et je ne connaissais pas son existence... Après c'était juste un bout de la solution, celui sur les couleurs et les suites (mais il y a un indice dedans sur la toute dernière question de l'exercice).

    Pour accumulate, je t'avais dit que ce n'était pas évident... Un indice: si la valeur initiale était std::vector<Hand>(), et la fonction une lambda qui déciderait soit d'ajouter une nouvelle Hand, soit d'ajouter un élément à la dernière Hand ajoutée?

  7. #87
    Membre du Club 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
    Points : 52
    Points
    52
    Par défaut
    Haha la quinte flush je l'avais ajouté cette apres midi mais comme rien ne fonctionnait, j'ai reporté... x)

    Et oue pour le accumulate, j'ai pas encore la pensé adéquate, je reste sur les définitions de base, sans réfléchir à pourvoir les transformer
    en les mélangeant à d'autre fonction etc... Y'a du boulot!! On verra demain, pause pour le cerveau ! ^^

  8. #88
    Membre du Club 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
    Points : 52
    Points
    52
    Par défaut
    Coucou! Je sors du taff à 9h du mat et je suis déjà en train de coder, c'est une drogue non? ^^

    J'ai ajouté la quinte flush et la quinte flush royale et j'ai anticipé l'attribution des points:

    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
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    #include "stdafx.h"
    #include <iostream>
    #include <utility>
    #include <array>
    #include <numeric>
    #include <algorithm>
    #include <random>
    #include <string>
    #include <vector>
     
    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>;
     
    Carte& operator++(Carte& p) //Ajoute un operateur ++ pour la fonction std::iota qui est appelé dans la fonction "creationDeck"
    {
    	++p.first;
    	++p.second;
    	return p;
    }
     
    auto creationDeck() //Creation d'un array de 52 emplacements qui contient chacun une paire de deux unsigned int
    {
    	Deck tab;
    	std::iota(std::begin(tab), std::end(tab), Carte());
    	std::transform(std::begin(tab), std::end(tab), std::begin(tab), [](Carte c)
    	{
    		c.first %= nbCarteParSigne;
    		c.second %= nbCouleur;
    		return c;
    	});
    	std::sort(std::begin(tab), std::end(tab));
    	return tab;
    }
     
    void melangerCarte(Deck &tab) //Fonction de mélange aleatoire
    {
    	std::random_device random;
     
    	std::shuffle(std::begin(tab), std::end(tab), random);
    }
     
    void couperCarte(Deck &tab) //Fonction qui coupe les carte en deux
    {
    	std::rotate(tab.begin(), tab.begin() + 27, tab.end());
    }
     
    void afficherCarte(Carte c) //Fonction qui affiche le nom d'une carte
    {
    	static std::array<std::string, nbCarteParSigne> numero = { "Deux","Trois","Quatre","Cinq","Six","Sept","Huit","Neuf","Dix","Valet","Dame","Roi","As" };
    	static std::array<std::string, nbCouleur> couleur = { "coeur","carreau","pique","trefle" };
     
    	std::cout << numero[c.first] << " de " << couleur[c.second] << std::endl;
    }
     
    Hand creationMainAvecTri(Deck tab) //Fonction qui créé une main de 5 carte en ordre croissant
    {
     
    	Hand tab1(nbCarteMain);
    	std::copy_n(tab.begin(), 5, tab1.begin());
    	std::sort(tab1.begin(), tab1.end(), [](auto &a,auto &b)
    	{
    		return a.first < b.first;
    	});
    	return tab1;
    }
     
    int scoreMain(Hand tab) // Fonction qui attribue un score en fonction de la main
    {
    	auto quinteFR = 0; // Quint flush royale
    	auto combiScore = 0; // Score final des combinaisons
    	if (std::all_of(tab.cbegin(), tab.cend(), [&tab](Carte c) { return c.second == tab[0].second; })) // Si la main contient une couleur
    	{
    		combiScore += 5;
    		quinteFR = +1;
    	}
    	auto x = tab[0].first;
    	if (std::all_of(tab.cbegin(), tab.cend(), [&x](Carte c) {return c.first == x++; })) // Si la main contient une suite
    	{
    		combiScore += 4;
    		if (quinteFR == 1) // Si les deux conditions au dessus sont True, quinte flush!
    		{
    			combiScore += 2;
    		}
    		if ((quinteFR == 1) && (tab[0].first == 8)) // Si les deux premieres conditions de la fonction sont True et que la premiere case de la main a pour valeur (8,x), quinte flush royale!
    		{
    			combiScore += 4;
    		}
    	}
     
    	std::vector<Hand> splitByRank;
     
    	return combiScore;
    }
     
    int main()
    {
    	auto jeuDeCarte = creationDeck(); //Crétion du jeu de carte dans un array en appelant la fonction "creationDeck"
    	melangerCarte(jeuDeCarte); //Melange les cartes aléatoirement en appelant la fonction "melangerCarte"
    	couperCarte(jeuDeCarte); //Coupe le jeu de carte au milieu en appelant la fonction "couperCarte"
    	auto main = creationMainAvecTri(jeuDeCarte); //Création d'une main des 5 cartes du debut du tableau "jeuDeCarte" puis la tri
     
    	/*Hand main(nbCarteMain); // Ca me sert de test pour tester si mes fonctions sont fonctionnelles
     
    	main[0] = std::make_pair(8,0);
    	main[1] = std::make_pair(9, 0);
    	main[2] = std::make_pair(10, 0);
    	main[3] = std::make_pair(11, 0);
    	main[4] = std::make_pair(12, 0);*/
     
    	std::for_each(std::begin(main), std::end(main), [](Carte c) {afficherCarte(c);});
    	std::cout << scoreMain(main) << std::endl;
     
    	return 0;
    }
    Pour la suite avec les vector + accumulate je bloque un peu car je ne comprends pas ce que tu as écris ici en rouge:

    Stendhal666 à écrit:

    Écrire une fonction qui divise la main en un vecteur de mains où les cartes sont identiques:

    std::vector<Hand> split_by_rank(const std::Hand& hand); // dans chaque Hand du vector de résultat, toutes les cartes ont le même numéro
    Je le lis comme ca: (const std::std::vector<Card>Hand& hand), tu peux me traduire la syntaxe stp?

  9. #89
    Membre chevronné

    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
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Oui c'est une drogue! mais une bonne pour l'esprit (pas forcément pour la santé si ça t'empêche de dormir).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    std::vector<Hand> split_by_rank(const std::Hand& hand);
    La fonction split_by_rank prend comme argument une référence constante sur une Hand, qui est un alias pour un std::vector<Card> -Card étant un alias pour une std::pair<unsigned, unsigned>. Elle retourne un std::vector<Hand>, c'est à dire un std::vector<std::vector<std::pair<unsigned, unsigned>>> (Ouf!).

    Ne t'obsède pas avec accumulate, tu peux faire ça à la façon qui te vient. Tu verras ma proposition dans la "correction" quand tu le voudras. Pour ma part, j'ai beaucoup appris en regardant le code des autres, on n'est pas obligé de tout redécouvrir par soi-même. Parfois même on finit par recopier un code qu'on ne comprend pas très bien (ce qui n'est pas grave si on le teste rigoureusement) et quelques temps plus tard, avec un peu plus de pratique, tout s'éclaire. C'est déjà très courageux d'étudier comme ça alors que tu travailles à des horaires décalés, ne te rajoute pas de difficulté excédentaire!

  10. #90
    Membre du Club 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
    Points : 52
    Points
    52
    Par défaut
    C'est surtout la syntaxe en faite que je pige pas ^^

    Pourquoi: std::vector<Hand> split_by_rank(const std::Hand& hand);

    au lieu de: std::vector<Hand> split_by_rank(const Hand& hand);

    C'est le std:: devant que je pige pas, si using Hand donne std::vector<Card>, c'est comme écrire std::std::vector<Card>, ca ne pose pas de problème?

  11. #91
    Membre chevronné

    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
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut


    My mistake, c toi qui as raison!

  12. #92
    Membre du Club 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
    Points : 52
    Points
    52
    Par défaut
    Forcément si c'était pas volontaire de ta part, je pouvais essayer de comprendre longtemps mdr!

    Tout est résolu, je vais pouvoir me remettre à réfléchir a tout ca demain

  13. #93
    Membre du Club 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
    Points : 52
    Points
    52
    Par défaut
    Hello!

    Franchement, depuis hier je réfléchis mais j'arrive à rien avec accumulate.. J'ai essayé sans, et c'est pas mieux, j'avais fais un code avec des boucles et conditions mais
    au bout de pas mal de ligne, je me suis rendu compte que c'était pas du tout bon comme approche x)

    Le vector de vector avec des pairs, chaud! Je bloque :/

  14. #94
    Membre chevronné

    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
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Comme on a encore du chemin à faire pour notre jeu de poker, je te propose deux pistes, à regarder quand tu le souhaites:

    Sans std::accumulate, voici ce que tu peux faire (peut-être des erreurs de frappe, à tester et corriger éventuellement):

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    std::vector<Hand> splitted_hand(1, Hand());
    for (unsigned i = 1; i < hand.size(); ++i) {
      if (hand[i].first == hand[i-1].first) { // pas besoin de split
        // donc on place à la fin de la dernière Hand de splitted_hand
        splitted_hand.back().push_back(hand[i]); // back() renvoie le dernier élément du std::vector
      }
      // sinon on rajoute une nouvelle Hand avec hand[i] comme unique élément à splitted_hand
      else splitted_hand.push_back(Hand(1, hand[i]));
    }

    Avec std::accumulate (code testé):

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    // maintenant pour les figures de type paire, brelan, full...
        // regrouper les cartes par rang dans un vector<Hand>
        auto rshand = std::accumulate(std::begin(phand), std::end(phand), std::vector<Hand>(), [](auto&& a, auto&& b) {
            if (!a.empty() && a.back().back().first == b.first) a.back().push_back(b); // un peu moche, d'accord
            else a.push_back(Hand(1,b));
            return a;
        });

  15. #95
    Membre du Club 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
    Points : 52
    Points
    52
    Par défaut
    Ta version avec std::accumulate fonctionne mais je ne la comprends pas.. C'est toujours un problème d'arguments de la lambda, je pige pas. J'ai relu tes
    post plus haut et des post sur le net pour essayer de comprendre mais ca rentre pas!

    Les arguments de la fonction lambda ils sont capturé d'où, comment? Tu mets auto a, auto b mais comment savoir ce qui vient à la place?

  16. #96
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    C'est dans la documentation de accumulate, par exemple sur cppreference.com.

    accumulate prend une fonction à deux arguments en argument, et se passe comme si elle était codée ainsi: (d'ailleurs c'est une des implémentations possibles)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    template<class InputIt, class T, class BinaryOperation>
    T accumulate(InputIt first, InputIt last, T init, BinaryOperation op) {
        for (; first != last; ++first) {
            init = op(init, *first);
        }
        return init;
    }
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  17. #97
    Membre chevronné

    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
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Une lambda dont les arguments sont introduits par le mot-clé auto est une lambda "générique": le compilateur déduit à ta place le type des arguments en regardant le type des arguments avec lesquels la lambda est appelée.

    Donc la question revient à savoir avec quels arguments la lambda est appelée dans l'algorithme accumulate. On pourrait écrire l’algorithme accumulate de la façon suivante:

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    using Iterator = std::vector<int>::iterator;
    template <typename Fn> // ne t'embarrasse pas avec ça, ce n'est pas nécessaire pour comprendre
    my_accumulate(Iterator first, Iterator last, int initial_value, Fn fonc) {
      while (first != last) { // tant que first != last
        initial_value = fonc( initial_value, *first );
        ++first;
      }
      return initial_value;
    }

    Donc si je passe une lambda générique à my_accumulate, le compilateur déduira que le son premier argument est du même type que initial_value et son second argument du même type que *first:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    my_accumulate(std::begin(int_vec), std::end(int_vec), 0, [](auto a, auto b) { return a != b; });
    // après la déduction par le compilateur ==>
    my_accumulate(std::begin(int_vec), std::end(int_vec), 0, [](int a, int b) { return a != b; }); // a est du type de initial_value, b du type de *first
    Pour l'utilisation de accumulate que je t'ai montrée pour le poker, le compilateur attribue au premier argument le type de initial_value, qui est std::vector<Hand>, et au second le type de *first, qui est Card. Du coup la fonction lambda est transformée en [](std::vector<Hand> a, Card b).

    Afin d'être parfaitement clair, voici la même chose avec une fonction normale:

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    std::vector<Hand> accu_func(std::vector<Hand> a, Card b) {
      if (!a.empty() && a.back().back() == b) {
        a.back().push_back(b);
      }
      else a.push_back(Hand(1,b));
      return a;
    }
     
    int main() {
      // ...
      auto splitted_hand = std::accumulate(std::begin(hand), std::end(hand), std::vector<Hand>(), accu_func);
      // ...
    }

  18. #98
    Membre du Club 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
    Points : 52
    Points
    52
    Par défaut
    Ok les gars! Je comprends un peu mieux, mais il va falloir le bucher ^^

    Revenons à la fonction lambda, tu as écris:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (!a.empty() && a.back().back().first == b.first) a.back().push_back(b);
    Si je comprends bien, "!a.empty()" permet de regarder dans chaque vector qui ne sont pas vide, si la dernière carte est la même que la carte b? Si oui, on ajoute une case a ce vector.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    a.push_back(Hand(1, b));
    Sinon, on crée un nouveau vector d'une case avec b en contenu.

    Ca devient quand même chaud à comprendre tout ça, désolé si je saoule mais j'ai pas envie de passer à autre chose si je pige pas bien ^^

  19. #99
    Membre chevronné

    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
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Si je comprends bien, "!a.empty()" permet de regarder dans chaque vector qui ne sont pas vide, si la dernière carte est la même que la carte b? Si oui, on ajoute une case a ce vector.
    Pas tout à fait: a.empty() se rapport uniquement à a. Si a n'a aucun élément, a.back() va poser problème, car il n'y aura pas d'élément à renvoyer. Donc on teste d'abord si a est vide; s'il n'est pas vide, alors on peut vérifier que a.back().back() est égal à b.
    Mais c'est très bien vu, tu mets le doigt sur quelque chose d'important: si on écrit if ( A && B), B ne sera évalué que si a est vrai.

    Ca devient quand même chaud à comprendre tout ça, désolé si je saoule mais j'ai pas envie de passer à autre chose si je pige pas bien
    Comme le dit bien leternel (cf sa signature): "la question la plus sotte est celle qu'on ne pose pas"

  20. #100
    Membre du Club 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
    Points : 52
    Points
    52
    Par défaut
    Avec:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (!a.empty() && a.back().back().first == b.first) a.back().push_back(b);
    Du moment qu'on crée un deuxième vecteur dans le vecteur principal, la lambda ne regarde plus la carte du premier vecteur, donc si dans la main on a 2,4,8,2,V
    la quatrième carte va pas aller a la suite du 2 du premier vecteur, nn?

    Quel casse tête!

    EDIT: Ok je viens de me rendre compte qu'on tri la main dans l'ordre croissant avant cette fonction.. Je me prends la tête sur des trucs bêtes

Discussions similaires

  1. Problème dans la page de correction d'un exercice?
    Par menoulette dans le forum Langage
    Réponses: 4
    Dernier message: 30/08/2009, 23h57
  2. Réponses: 11
    Dernier message: 04/02/2008, 20h37
  3. Correction d'un exercice en C++
    Par aniscpp dans le forum C++
    Réponses: 2
    Dernier message: 07/12/2006, 14h01
  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, 10h01

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