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. #101
    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
    Salut!

    Pour trier le vector de vector, on peut utiliser std::sort? J'ai réussi à faire mon système de point mais il faut que j'arrive à le trier et j'ai tester
    plusieurs syntaxes mais j'ai l'impression qu'il y a un piège ^^

    J'ai essayé avec std::greater mais j'ai pas su m'en servir avec le vector et avec une lambda et un operator de supériorité et ca n'a pas fonctionné non plus.

  2. #102
    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
    1) n'oublie pas de bien regarder la référence quand tu as un doute, c'est comme ça que ça rentre...
    2) tu y verras qu'il n'y a pas d'opérateur < pour les vector
    3) et s'il y en avait un il pourrait avoir un sens différent qu'une comparaison de taille (ex: comparaison lexicographique, comme pour une string)
    4) ta lambda doit donc comparer la taille des vectors : a.size() < b.size() ...

    EDIT:

    J'en profite pour te donner la suite de l'exercice (eh oui...)

    1) Mettons que deux mains de poker aient le même score synthétique (par exemple, elles ont toutes les deux une couleur, ou une double paire); il faut alors les départager. Lorsqu'il s'agit d'une suite ou d'une couleur, on prend la carte la plus élevée de la main; lorsqu'il s'agit d'une figure formée par des cartes identiques, on prend la carte la plus élevée du groupe de cartes le plus nombreux (ex: pour un full, le rang des cartes qui forment le brelan).
    Ecrire une fonction bool compare(const Hand& a, const Hand& b); qui renvoie true si a < b, false sinon. On peut utiliser l'algorithme std::lexographical_compare.

    2) Attention, il peut arriver que deux mains soient à égalité (un exemple rare mais possible: deux quintes flush à l'as). Mettons qu'il y ait 6 joueurs autour de la table de poker. Trier les six mains dans l'ordre décroissant de score. Vérifier s'il n'y a qu'une seule main gagnante ou plusieurs à égalité (il faudra alors partager le pot). On peut utiliser l'algorithme std::partition_point ou l'algorithme find_if ou d'autres encore...

  3. #103
    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 pourtant la dessus que je suis partie et ca ne fonctionne pas, où est l'erreur?

    J'ai regardé la doc du vector et j'ai vu que < ne fonctionnait pas donc j'ai fais avec size mais ca ne tri rien :/

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    std::sort(splitByRank.begin(), splitByRank.end(), [](auto&& a, auto&&b)
    	{
    		return a.size() < b.size();
    	});

  4. #104
    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
    Montre un peu plus de code car je ne vois pas pourquoi ça ne pourrait pas marcher...

  5. #105
    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
    Tiens voila le code en entier:

    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
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    #include "stdafx.h"
    #include <iostream>
    #include <utility>
    #include <array>
    #include <numeric>
    #include <algorithm>
    #include <random>
    #include <string>
    #include <vector>
    #include <functional>
     
    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;
    		}
    	}
     
    	auto splitByRank = std::accumulate(std::begin(tab), std::end(tab), 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;
    	});
     
    	for (unsigned i = 0; i < splitByRank.size(); i++)
    		{
    			std::cout << std::endl;
    			std::cout << "sous tableau : " << i + 1 << std::endl << std::endl;
    			std::for_each(std::begin(splitByRank[i]), std::end(splitByRank[i]), [](Carte c) {afficherCarte(c); });			
    		}
     
    	std::sort(splitByRank.begin(), splitByRank.end(), [](auto&& a, auto&&b)
    	{
    		return a.size() < b.size();
    	});
     
    	for (unsigned i = 0; i < splitByRank.size(); i++)
    	{
    		if (splitByRank[0].size() == 2)
    		{
    			combiScore += 1;
    		}
    		else if (splitByRank[0].size() == 3)
    		{
    			combiScore += 3;
    			if (splitByRank[1].size() == 2)
    			{
    				combiScore += 2;
    			}
    		}
    		else if (splitByRank[0].size() == 4)
    		{
    			combiScore += 7;
    		}
    		else if (splitByRank[1].size() == 2)
    		{
    			combiScore += 1;
    		}
    		else if (splitByRank[1].size() == 3)
    		{
    			combiScore += 3;
    			if (splitByRank[0].size() == 2)
    			{
    				combiScore += 2;
    			}
    		}
    	}
     
    	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
     
    	std::cout << scoreMain(main) << std::endl;
     
    	/*std::for_each(std::begin(main), std::end(main), [](Carte c) {afficherCarte(c); });*/
     
    	return 0;
    }
    Si tu compiles plusieurs fois, tu vois que c'est aléatoire et que ca ne classe pas

  6. #106
    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
    Je n'ai pas encore eu le temps de regarder de près. Tu es conscient que tu affiches le tableau avant de l'avoir trié?

  7. #107
    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
    ... N'en parlons plus.

  8. #108
    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


    A propos de la drogue de la programmation: quand on est crevé il vaut mieux se reposer, sinon on a tendance à faire des erreurs tellement évidentes qu'on ne les voit pas.

  9. #109
    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
    Oue ca devait être la fatigue on va dire alors...

    Il y a The division qui est sorti hier, ca me permettra de switcher entre les deux mdr!

    Sinon pour en revenir à nos moutons, pour continuer l'exo sur la comparaison de deux mains, j'ai créé une deuxième fonction pour créer une deuxième
    main grâce à un iterateur, car la fonction de base prenait toujours les 5 premières cartes du deck:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Hand creationMainP2(Deck tab) //Fonction qui créé une main de 5 carte en ordre croissant pour le Player 2
    {
     
    	Hand tab1(nbCarteMain);
    	std::copy_n(tab.begin()+=5, 5, tab1.begin());
    	std::sort(tab1.begin(), tab1.end(), [](auto &a, auto &b)
    	{
    		return a.first < b.first;
    	});
    	return tab1;
    }
    Et voilà ma fonction compare:

    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
    bool compare(Hand a, Hand b) // Retourne true si a est plus petit que b
    {
    	std::sort(a.begin(), a.end(), [](auto& c, auto& d)
    	{
    		return c.first > d.first;
    	});
    	std::sort(b.begin(), b.end(), [](auto& c, auto& d)
    	{
    		return c.first > d.first;
    	});
     
    	bool c = true;
    	c = std::lexicographical_compare(a.begin(), a.end(),b.begin(), b.end());
    	return c;
    }
    Et le code entier si besoin:

    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
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    #include "stdafx.h"
    #include <iostream>
    #include <utility>
    #include <array>
    #include <numeric>
    #include <algorithm>
    #include <random>
    #include <string>
    #include <vector>
    #include <functional>
     
    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 creationMainP1(Deck tab) //Fonction qui créé une main de 5 carte en ordre croissant pour le Player 1
    {
     
    	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;
    }
     
    Hand creationMainP2(Deck tab) //Fonction qui créé une main de 5 carte en ordre croissant pour le Player 2
    {
     
    	Hand tab1(nbCarteMain);
    	std::copy_n(tab.begin()+=5, 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;
    		}
    	}
     
    	auto splitByRank = std::accumulate(std::begin(tab), std::end(tab), 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;
    	});
     
    	std::sort(splitByRank.begin(), splitByRank.end(), [](auto&& a, auto&&b)
    	{
    		return a.size() > b.size();
    	});
     
    	if (splitByRank[0].size() == 2)
    	{
    		combiScore += 1;
    		if (splitByRank[1].size() == 2)
    		{
    			combiScore += 1;
    		}
    	}
    	else if (splitByRank[0].size() == 3)
    	{
    		combiScore += 3;
    		if (splitByRank[1].size() == 2)
    		{
    			combiScore += 3;
    		}
    	}
    	else if (splitByRank[0].size() == 4)
    	{
    		combiScore += 7;
    	}
    	return combiScore;
    }
     
    bool compare(Hand a, Hand b) // Retourne true si a est plus petit que b
    {
    	std::sort(a.begin(), a.end(), [](auto& c, auto& d)
    	{
    		return c.first > d.first;
    	});
    	std::sort(b.begin(), b.end(), [](auto& c, auto& d)
    	{
    		return c.first > d.first;
    	});
     
    	bool c = true;
    	c = std::lexicographical_compare(a.begin(), a.end(),b.begin(), b.end());
    	return c;
    }
     
    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 main1 = creationMainP1(jeuDeCarte); //Création d'une main Player 1 des 5 cartes du debut du tableau "jeuDeCarte" puis la tri
    	auto main2 = creationMainP2(jeuDeCarte);//Création d'une main Player 2 des 5 cartes du debut du tableau "jeuDeCarte" puis la tri
    	bool a = compare(main1, main2);	// Compare deux mains pour savoir si la premiere est plus petite
     
    	std::cout << "Main numero 1" << std::endl << std::endl;
    	std::for_each(std::begin(main1), std::end(main1), [](Carte c) {afficherCarte(c); });
    	std::cout << std::endl;
    	std::cout << "Score: " << scoreMain(main1) << std::endl << std::endl;
    	std::cout << "Main numero 2" << std::endl << std::endl;
    	std::for_each(std::begin(main2), std::end(main2), [](Carte c) {afficherCarte(c); });
    	std::cout << std::endl;
    	std::cout << "Score: " << scoreMain(main2) << std::endl << std::endl;
     
    	std::cout << "Est-ce que la main numero 2 a la carte la plus haute? = " << std::boolalpha << a << std::endl;
     
    	return 0;
    }
    Pour le deuxième exercice, je dois créer un tableau de joueur, de score et d'argent? Je fais trois tableaux différent ou je tente le tableau 3D? ^^

  10. #110
    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
    - Pour la fonction compare, ça ne va pas. Imagine que tu aies une main (as de coeur, sept de trèfle, sept de pique, + deux autres cartes) et une autre (dame de coeur, valet de trèfle, valet de pique + deux autres cartes). En comparant lexicographiquement après un simple tri, c'est la première main qui sortira gagnante (as > dame), alors que ce devrait être la deuxième puisqu'elle a une paire de valet, alors que la paire de l'autre n'est qu'au sept.
    EDIT: il faut aussi que tu précises la fonction de comparaison dans lexicographical_compare. Pour comprendre pourquoi, regarde l'opérateur< pour les paires...

    - Pour la suite, par étape et en douceur!
    Ce que j'ai choisi pour ma "correction", c'est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<Hand> winning_hands(const std::vector<Hand>& hands);
    La fonction retourne un vecteur qui contient la ou les mains gagnantes. Mais libre à toi de choisir une autre signature si tu penses qu'elle est plus adaptée au problème.

    On viendra au jeu complet. Il faudra cependant une autre "leçon" avant la poursuite de l'exercice (si on veut faire les choses correctement). Cette première étape de travail sur le jeu était destinée à comprendre précisément l'aspect algorithmique du jeu de poker: comment générer les cartes, les mélanger/couper, les distribuer (quoiqu'il reste du travail pour plus tard, on ne distribue pas les cartes 5 par 5 il me semble), trier sa main, déterminer les figures, évaluer une main, comparer deux mains... Mais il reste beaucoup d'autres étapes si on veut faire les choses correctement (pas forcément dans l'ordre):
    • modéliser une partie / une série de parties: combien de joueurs, quand mélanger/couper, gérer les échanges de cartes, le système d'enchères, etc.
    • faire une interface: l'interface concrète n'est pas nécessairement la partie la plus difficile (du boulot pour apprivoiser une librairie graphique, cependant) mais il faut aussi articuler correctement la partie "métier" (calculs, suivi des parties, etc.) et l'affichage. Idéalement, il faut découpler au maximum les deux.
    • Si la conception est bien faite, elle est modulaire et on peut ajouter de nouveaux composants: par exemple une intelligence artificielle pour gérer le comportement des PNJ (personnages non-joueurs si tu connais un peu les jeux de rôle)
    • et puis il y a toute la question des tests. On ne l'a pas encore fait mais il faudra s'y mettre: il faut écrire des tests pour vérifier que le programme marche comme attendu; on lance les tests à chaque fois qu'on modifie un programme pour voir si les changements n'ont pas altéré son comportement.
    • il y a la question de la documentation: pour pouvoir reprendre ton code plus tard, le montrer à d'autres / le créer avec d'autres, il faut le documenter correctement.
    • enfin, mais ce n'est pas un enjeu de première importance pour une partie de poker, il y a l'optimisation, qui doit suivre une phase de profilage...

    J'oublie certainement des choses...

    Je te mets une proposition pour l'auto-correction. Si tu te poses des questions, n'hésite pas!

    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
    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
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    #include <iostream> // ostream, cout
    #include <array> // array
    #include <vector> // vector
    #include <random> // std::random_device, std::mt19937, std::normal_distribution
    #include <numeric> // iota, accumulate
    #include <algorithm> // transform, sort, shuffle, rotate, find_if
    #include <utility> // pair
     
    constexpr unsigned NB_COLORS = 4;
    constexpr unsigned NB_CARDS_BY_COLOR = 13;
    constexpr auto     NB_CARDS = NB_COLORS * NB_CARDS_BY_COLOR;
    constexpr unsigned NB_CARDS_IN_HAND = 5;
     
    constexpr std::array<const char*, 13> rank_names = { "2", "3", "4", "5", "6", "7", "8", "9", "10",
                                                         "valet", "dame", "roi", "as" };
    constexpr std::array<const char*, 4> color_names = { "coeur", "pique", "carreau", "trèfle" };
     
    using Card = std::pair<unsigned, unsigned>;
    std::ostream& operator<<(std::ostream& os, Card c) { // surcharge de l'opérateur << . Ex: std::cout << Card(0,0)
        os << rank_names[c.first] << " de " << color_names[c.second];
        return os;
    }
     
    using Deck = std::array<Card, NB_CARDS>;
    using Hand = std::vector<Card>;
     
    template < typename Cont >
        void print_cards(const Cont cs) {
        for (auto& c : cs) {
            std::cout << c << '\n';
        }
        std::cout << std::endl;
    }
    /* plus nécessaire après la modification de generate_deck
    auto& operator++(Card& c) {
        ++c.first;
        ++c.second;
        return c;
    }*/
     
    auto generate_deck() {
        Deck d;
        std::vector<unsigned> tank(52);
        std::iota(std::begin(tank), std::end(tank), 0);
        std::transform(std::begin(tank), std::end(tank), std::begin(d), [](auto&& i) { 
            return std::make_pair(i % NB_CARDS_BY_COLOR, i % NB_COLORS);
        });
        return d;
    }
     
    auto& shuffle_deck(Deck& d) {
        std::random_device rd;
        std::mt19937 g(rd());
        std::shuffle(std::begin(d), std::end(d), g);
        return d;
    }
     
    auto& cut_deck(Deck& d) {
        std::random_device rd;
        std::mt19937 g(rd());
        std::normal_distribution<> dist(d.size()/2, d.size()/10); // distribution gaussienne: on coupe en général près du milieu
        std::ptrdiff_t cut_pos = dist(g); // on précise le type car le retour de dist(g) est un double -> arrondi à l'entier en dessous
        cut_pos %= d.size();
     
        std::rotate(std::begin(d),
                    std::begin(d) + cut_pos,
                    std::end(d) );
        return d;
    }
     
    std::pair<unsigned, Hand> evaluate_hand(const Hand& h) {
        // tri décroissant d'une copie de h par rang des cartes avant de regrouper les cartes de même rang
        Hand phand = h;
        std::sort(std::begin(phand), std::end(phand), [](auto&& a, auto&& b) { return a.first > b.first; });
     
        auto straight_score = 0u;
        // on vérifie si c'est une couleur
        if (std::all_of(std::begin(phand)+1, std::end(phand), [&](auto&& c) { return c.second == std::begin(phand)->second; }))
            straight_score += 8;
        // on vérifie si c'est une suite
        auto beg = std::begin(phand)->first;
        if (std::all_of(std::begin(phand)+1, std::end(phand), [&beg](auto&& c) { return c.first == --beg; }))
            straight_score += 7;
     
        // s'il y a une couleur ou une suite, il ne peut y avoir d'autre figure, donc on retourne maintenant
        // il suffirait de retourner également le rang de la carte la plus haute pour les cas d'égalité de score
        // mais comme pour les autres figures, il faut comparer plusieurs cartes en cas d'égalité, on renvoie la main avec;
        if (straight_score != 0) return std::make_pair(straight_score, phand);
     
        // 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;
        }); 
     
        // on cherche le groupe de cartes identiques le plus nombreux
        std::sort(std::begin(rshand), std::end(rshand), [](const auto& a, const auto& b) { return a.size() > b.size(); });
        // et on déduit un score synthétique par: figure la plus nombreuse * (taille de la main - nombre de groupes de cartes)
        auto figure_score = std::begin(rshand)->size() * (NB_CARDS_IN_HAND - rshand.size());
     
        // pour les cas d'égalité de score, on retourne également la première carte de chaque groupe de carte dans un std::vector
        Hand firsts(rshand.size());
        std::transform(std::begin(rshand), std::end(rshand), std::begin(firsts), [](auto&& h) { return *std::begin(h); });        
        return std::make_pair(figure_score, firsts);
    }
     
    bool compare(const Hand& a, const Hand& b) {
        auto score_a = evaluate_hand(a);
        auto score_b = evaluate_hand(b);
        if (score_a.first < score_b.first) return true;
        if (score_a.first > score_b.first) return false;
        return std::lexicographical_compare(std::begin(score_a.second), std::end(score_a.second),
                                            std::begin(score_b.second), std::end(score_b.second),
                                            [](auto&& l, auto&& r) { return l.first < r.first; });
    }
     
    auto winners(const std::vector<Hand>& hands) {
        auto chands = hands;
        std::sort(std::begin(chands), std::end(chands), [](auto&& a, auto&& b) { return !compare(a,b); });
        auto first = *std::begin(chands);
        auto last  = std::find_if(std::begin(chands)+1, std::end(chands), [&first](auto&& c) { return compare(c, first); });
        chands.erase(last, std::end(chands));
        return chands;
    }
     
    int main() {
        auto deck = generate_deck();
        shuffle_deck(deck);
        cut_deck(deck);
     
        Hand hand1(NB_CARDS_IN_HAND), hand2(NB_CARDS_IN_HAND);
        std::copy_n(std::begin(deck), NB_CARDS_IN_HAND, std::begin(hand1));
        print_cards(hand1);
        std::cout << std::endl;
        std::copy_n(std::begin(deck)+NB_CARDS_IN_HAND, NB_CARDS_IN_HAND, std::begin(hand2));
        print_cards(hand2);
        std::cout << std::endl;
        std::cout << "Score first hand:  " << evaluate_hand(hand1).first << std::endl;
        std::cout << "Score second hand: " << evaluate_hand(hand2).first << std::endl;
        std::cout << "first hand < second hand? " << std::boolalpha << compare(hand1, hand2) << std::endl;
    }

  11. #111
    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
    The division a pris le dessus?

  12. #112
    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
    Salut!

    Haha, j'dois avouer que hier, j'ai squaté comme un porc le jeu... Coupable! Mais bon j'dois t'avouer que ca devient dur tes exos. Ce matin j'ai voulu modifier mon code mais voilà, ca vient pas. Je ne connais pas comme toi tout ces algorithmes et tout ce qu'ils peuvent faire du coup je passe souvent par des trucs fait à ma façon et qui au final ne fonctionne pas bien. Je vais sur Cppreference pour essayer de comprendre comment marche un algo mais c'est pas forcement facile a comprendre toute ces syntaxes d'exemple.

    T'es toujours obliger de me donner 85% de la réponse, je sais pas si c'est moi qui arrive pas à suivre ou toi qui va trop vite mais ca devient dur. ^^

    Après attention, je suis pas en train d'abandonner, juste en train de bien tout relire, regarder comment toi tu as fais ton code pour essayer de faire que ca rentre dans ma tête pas juste recopier des codes bêtement.

    Au début je répondais rapidement car c’était plus simple, la il faut beaucoup de réflexion à mon niveau pour sortir un code. Puis la première semaine j’étais en vacance, la avec le taff, le gosse et la femme, faut que je jongle avec tout ca! ^^

    Enfin tout ca pour dire que je suis là tkt pas! Avant de continuer, je veux juste être sur d'avoir bien tout compris de ce qui a déjà été fait!

  13. #113
    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
    Et bien bonjour à la petite famille alors! Mais j'ai bien expérimenté la chose: travail, femme et enfant on s'en sort encore, si on rajoute un jeu prenant, c'est cuit!
    Sinon c'est vrai que ce sont des exercices durs mais tu as fait déjà de gros progrès sur des choses qui te serviront souvent.

  14. #114
    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
    Salut stend! Donc j'ai amélioré mon code et je me suis aidé de ta correction quand je bloquais. Tout compile mais je pense qu'il y a une erreur même dans ton code, enfin tu vas me dire.. Je t'explique:

    Dans la pair retourné de la fonction du score, en deuxième tu as la première carte de chaque groupe de carte. Mais le problème c'est que c'est mal trié je pense, car ca prends pas en compte les carte des paires, brelan etc en prio à chaque fois. Si tu n'as pas de paire les cartes sont trié par ordre croissant, du coup ca prends pas la carte haute, et si tu as deux paires, si la première paire de "a" est inférieur à la première paire de "b", ca retourne "true" sans regarder la seconde pair du coup. Pareil pour les carte si tu n'a aucune paire

    C'est dure a expliquer... Mais il faudrait trier les premières cartes en fonction des groupes, et je n'ai pas trouvé comment faire :/

  15. #115
    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 il y a des erreurs dans mon code, je m'en suis aperçu plus tard. Mais je les avais trouvées dans la fonction winners, pas dans compare. A mon avis c'est bon, mais si tu trouves un cas où ça ne va pas, tu pourrais me le donner précisément (ex: deux paires pour lesquelles la comparaison est fausse)? Voici ce qu'il se passe selon moi:
    1) on a la main "brute", non triée: {3, 4, 9, 3, 9 }
    2) on trie la main dans l'ordre décroissant: {9, 9, 4, 3, 3 }
    3) on divise en groupes de cartes identiques: les groupes ne sont pas encore classés par taille; en revanche comme la main était triée par rang, les groupes sont triés par rang également:
    { 9, 9, 4, 3, 3,} -> { {9, 9}, {4 }, {3, 3} }
    4) on trie par ordre décroissant de taille. Comme std::sort est un tri stable, on ne modifie l'ordre intial qu'autant que nécessaire:
    { {9, 9}, {4 }, {3, 3} } -> { {9, 9}, {3, 3}, {4 } } // avec un tri instable on aurait pu obtenir : { {3, 3}, {9, 9}, {4 } } mais notre tri est stable
    5) on prend la première carte de chaque groupe:
    { {9, 9}, {3, 3}, {4 } } -> {9, 3, 4}
    Du coup si je compare lexicographiquement avec une autre main (comme je ne compare lexicographiquement que des paires dont le score est égal, je sais que les figures sont identiques, il ne faut départager que sur le rang des cartes qui forment les figures), je compare bien les cartes les plus importantes d'abord. Mettons que pour l'autre carte j'ai obtenu au final {8, 7, 4}, la seule comparaison à faire est 9 < 8 false; si j'ai obtenu {9, 8, 4}, la comparaison qui compte sera 3 < 8.
    Quel est le problème de ce raisonnement?

    Je t'envoie une version modifiée de la fonction winners en revanche:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    auto winning_hands(const std::vector<Hand>& hands) {
        auto chands = hands;
        std::sort(std::begin(chands), std::end(chands), [](auto&& a, auto&& b) { return compare(a,b); }); // !compare(a, b) <=> a >= b et n'est pas suffisant pour un ordre strict
        std::reverse(std::begin(chands), std::end(chands)); // on renverse pour obtenir un ordre décroissant
        auto first = *std::begin(chands);
        // on cherche le premier élément suivant first qui est < first
        auto last  = std::find_if(std::begin(chands)+1, std::end(chands), [&first](auto&& c) { return compare(c, first); });
        // on efface les éléments à partir du premier élément < begin
        chands.erase(last, std::end(chands));
        return chands;
    }


    Tu me diras aussi quand (et si) tu veux passer à la suite.

  16. #116
    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 eu le même raisonnement et pourtant regarde:

    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
    Main numéro 1
     
    Cinq de carreau
    Six de pique
    Huit de pique
    Valet de carreau
    Dame de pique
     
    Score: 0
     
    Main numéro 2
     
    Deux de coeur
    Cinq de pique
    Neuf de trefle
    Dix de pique
    Roi de pique
     
    Score: 0
     
    Est-ce que la main numero 2 a la carte la plus haute? = false
    Appuyez sur une touche pour continuer...
    Le roi devrait être la carte haute!

    Alors j'ai pas tester ton code ca vient peut être du miens, pour changer

    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
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    #include "stdafx.h"
    #include <iostream>
    #include <utility>
    #include <array>
    #include <numeric>
    #include <algorithm>
    #include <random>
    #include <string>
    #include <vector>
    #include <functional>
     
    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 creationMainP1(Deck tab) //Fonction qui créé une main de 5 carte en ordre croissant pour le Player 1
    {
     
    	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;
    }
     
    Hand creationMainP2(Deck tab) //Fonction qui créé une main de 5 carte en ordre croissant pour le Player 2
    {
     
    	Hand tab1(nbCarteMain);
    	std::copy_n(tab.begin()+=5, 5, tab1.begin());
    	std::sort(tab1.begin(), tab1.end(), [](auto &a, auto &b)
    	{
    		return a.first < b.first;
    	});
    	return tab1;
    }
     
    std::pair<unsigned, Hand> 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;
    		}
    	}
     
    	auto splitByRank = std::accumulate(std::begin(tab), std::end(tab), std::vector<Hand>(), [](auto&& a, auto&& b)
    	{
    		if (!a.empty() && a.back().back().first == b.first) a.back().push_back(b);
    		else a.push_back(Hand(1, b));
    		return a;
    	});
     
    	std::sort(splitByRank.begin(), splitByRank.end(), [](auto&& a, auto&&b)
    	{
    		return a.size() > b.size();
    	});
     
    	if (splitByRank[0].size() == 2)
    	{
    		combiScore += 1;
    		if (splitByRank[1].size() == 2)
    		{
    			combiScore += 1;
    		}
    	}
    	else if (splitByRank[0].size() == 3)
    	{
    		combiScore += 3;
    		if (splitByRank[1].size() == 2)
    		{
    			combiScore += 3;
    		}
    	}
    	else if (splitByRank[0].size() == 4)
    	{
    		combiScore += 7;
    	}
     
    	Hand premiereCarte(splitByRank.size());
    	std::transform(std::begin(splitByRank), std::end(splitByRank), std::begin(premiereCarte), [](auto&& a) { return *std::begin(a); });
     
    	return std::make_pair(combiScore, premiereCarte);
    }
     
    bool compare(Hand& a, Hand& b) // Retourne true si a est plus petit que b
    {
    	auto score_a = scoreMain(a);
    	auto score_b = scoreMain(b);
    	if (score_a.first < score_b.first) return true;
    	if (score_a.first > score_b.first) return false;
    	return std::lexicographical_compare(std::begin(score_a.second), std::end(score_a.second),
    		std::begin(score_b.second), std::end(score_b.second),
    		[](auto&& l, auto&& r) { return l.first < r.first; });
    }
     
    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 main1 = creationMainP1(jeuDeCarte); //Création d'une main Player 1 des 5 cartes du debut du tableau "jeuDeCarte" puis la tri
    	auto main2 = creationMainP2(jeuDeCarte);//Création d'une main Player 2 des 5 cartes du debut du tableau "jeuDeCarte" puis la tri
     
    	std::cout << "Main numero 1" << std::endl << std::endl;
    	std::for_each(std::begin(main1), std::end(main1), [](Carte c) {afficherCarte(c); });
    	std::cout << std::endl;
    	std::cout << "Score: " << scoreMain(main1).first << std::endl << std::endl;
    	std::cout << "Main numero 2" << std::endl << std::endl;
    	std::for_each(std::begin(main2), std::end(main2), [](Carte c) {afficherCarte(c); });
    	std::cout << std::endl;
    	std::cout << "Score: " << scoreMain(main2).first << std::endl << std::endl;
     
    	std::cout << "Est-ce que la main numero 2 a la carte la plus haute? = " << std::boolalpha << compare(main1,main2) << std::endl;
     
    	return 0;
    }
    Pour la suite c'est quand tu veux! Je vais certainement bloquer sur des algo déjà étudié mais comme avec ton code et le mien j'ai des exemples plus précis d'utilisation, il sont plus simple à comprendre en les réétudiant

  17. #117
    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
    Eh bien oui, tu tries la main dans l'ordre croissant quand tu la crées, et tu ne la tries plus dans la fonction score_main...

    Ok, je te balancerai la suite ce week-end!
    On commencera par une petite leçon sur les objets, par exemple:

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Player {
     
      unsigned ID;
      int money;
      std::shared_ptr<Hand> hand;
     
      public:
      // ...
    };


    EDIT:

    Côté algo il reste un exo à faire (on va faire un peu interactif pour une fois): le programme affiche une main à l'utilisateur, il lui demande quelles cartes il veut remplacer: par exemples, les cartes 1, 3 et 5. Le programme remplace les cartes demandées par de nouvelles cartes:
    1) (déjà fait): générer un paquet de cartes, et distribuer les 5 premières au joueur
    2) (déjà fait): afficher les cartes
    3) moyen: demander au joueur quelle carte il veut modifier. Vérifier si les données saisies sont valides (ce sont des entiers compris entre 1 et 5). Ne demander à l'utilisateur de ressaisir que les données fausses; ex: je veux changer les cartes 1, 3 et 6, ne demander une modification que pour la carte 6
    4) moyen difficile: remplacer les cartes rejetées par le nombre identique de cartes tirées dans la suite du paquet. On peut (mais aucune obligation) utiliser l'algorithme std::set_difference (bien lire la documentation)
    5) afficher les nouvelles cartes et le score du joueur

  18. #118
    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 niquel, j'ai ajouté un tri décroissant avant le splitByRank et tout rentre dans l'ordre

    Pour l'exo 3, je pense utiliser un vector pour stocker les choix en ajoutant chaque choix dedans et retourner ce vector à la fin de la fonction. Ca permettra de bien faire fonctionner std::set_difference, j'ai bon?

  19. #119
    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
    Ça s'annonce bien en effet!

  20. #120
    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
    Salut!
    Je bloque sur std::set_difference, tout marche sauf des qu'il y a plusieurs carte de même valeur dans la main (paire, brelan, etc), j'obtiens:

    Nom : Sans titre.png
Affichages : 209
Taille : 12,1 Ko

    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 :/

    Voilà le code:

    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
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    #include "stdafx.h"
    #include <iostream>
    #include <utility>
    #include <array>
    #include <numeric>
    #include <algorithm>
    #include <random>
    #include <string>
    #include <vector>
    #include <functional>
    #include <iterator>
    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 creationMainP1(Deck tab) //Fonction qui créé une main de 5 carte en ordre croissant pour le Player 1
    {
     
    	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;
    }
     
    Hand creationMainP2(Deck tab) //Fonction qui créé une main de 5 carte en ordre croissant pour le Player 2
    {
     
    	Hand tab1(nbCarteMain);
    	std::copy_n(tab.begin()+=5, 5, tab1.begin());
    	std::sort(tab1.begin(), tab1.end(), [](auto &a, auto &b)
    	{
    		return a.first < b.first;
    	});
    	return tab1;
    }
     
    std::pair<unsigned, Hand> 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::sort(tab.begin(), tab.end(), [](auto &a, auto &b)
    	{
    		return a.first > b.first;
    	});
     
    	auto splitByRank = std::accumulate(std::begin(tab), std::end(tab), std::vector<Hand>(), [](auto&& a, auto&& b)
    	{
    		if (!a.empty() && a.back().back().first == b.first) a.back().push_back(b);
    		else a.push_back(Hand(1, b));
    		return a;
    	});
     
    	std::sort(splitByRank.begin(), splitByRank.end(), [](auto&& a, auto&&b)
    	{
    		return a.size() > b.size();
    	});
     
    	if (splitByRank[0].size() == 2)
    	{
    		combiScore += 1;
    		if (splitByRank[1].size() == 2)
    		{
    			combiScore += 1;
    		}
    	}
    	else if (splitByRank[0].size() == 3)
    	{
    		combiScore += 3;
    		if (splitByRank[1].size() == 2)
    		{
    			combiScore += 3;
    		}
    	}
    	else if (splitByRank[0].size() == 4)
    	{
    		combiScore += 7;
    	}
     
    	Hand premiereCarte(splitByRank.size());
    	std::transform(std::begin(splitByRank), std::end(splitByRank), std::begin(premiereCarte), [](auto&& a) { return *std::begin(a); });
     
    	return std::make_pair(combiScore, premiereCarte);
    }
     
    bool compare(Hand& a, Hand& b) // Retourne true si a est plus petit que b
    {
    	auto score_a = scoreMain(a);
    	auto score_b = scoreMain(b);
    	if (score_a.first < score_b.first) return true;
    	if (score_a.first > score_b.first) return false;
    	return std::lexicographical_compare(std::begin(score_a.second), std::end(score_a.second),
    		std::begin(score_b.second), std::end(score_b.second),
    		[](auto&& l, auto&& r) { return l.first < r.first; });
    }
     
    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(nCarteTab.begin(), nCarteTab.end(), [](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()));
    	std::copy_n(deck.begin()+=10, nCarte, std::back_inserter(nouvMain));
    	std::sort(nouvMain.begin(), nouvMain.end(), [](auto &a, auto &b)
    	{
    		return a.first < b.first;
    	});
    	return nouvMain;
    }
     
    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 main1 = creationMainP1(jeuDeCarte); //Création d'une main Player 1 des 5 cartes du debut du tableau "jeuDeCarte" puis la tri
    	auto main2 = creationMainP2(jeuDeCarte);//Création d'une main Player 2 des 5 cartes du debut du tableau "jeuDeCarte" puis la tri
     
    	std::cout << "Main numero 1" << std::endl << std::endl;
    	std::for_each(std::begin(main1), std::end(main1), [](Carte c) {afficherCarte(c); });
    	std::cout << std::endl;
    	//std::cout << "Score: " << scoreMain(main1).first << std::endl << std::endl;
     
    	main1 = changeCarte(main1,jeuDeCarte);
     
    	std::cout << "Main numero 1" << std::endl << std::endl;
    	std::for_each(std::begin(main1), std::end(main1), [](Carte c) {afficherCarte(c); });
    	std::cout << std::endl;
    	//std::cout << "Score: " << scoreMain(main1).first << std::endl << std::endl;
     
    	return 0;
    }
    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? ^^

    Il vaut mieux écrire a.begin() ou std::begin(a)?

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