APPLICATION On souhaite écrire un programme qui permet à l utilisateur de jouer au jeu de cartes 21. Principe : L utilisateur reçoit une carte à la fois et après chaque carte il décide s il continue ou non. Le but est, en additionnant les points des cartes que l utilisateur a en main, d approcher le plus possible 21 sans dépasser cette valeur. Si l utilisateur dépasse 21 il a perdu, sinon c est au tour de l ordinateur de jouer. Si lorsqu il s arrête il a dépassé 21 ou a moins que l utilisateur, c est celui-ci qui a gagné, sinon c est l ordinateur qui gagne. Un as vaut soit 1 soit 14. Définition des classes : On va définir - une classe carte - une classe piledecartes - une classe joueur La classe carte doit permettre de : - créer une carte : constructeur - en connaître sa valeur : valeur - écrire ses informations (couleur et valeur) : ecrire enum couleur trefle, carreau, coeur, pique ; class carte public : carte (couleur c=trefle, int v=1) ; int valeur () return v ; void ecrire () ; private : couleur c ; int v ; ; carte::carte (couleur cc, int vv) assert (vv >= 1 && vv <= 13) ; c=cc ; v=vv ; - 27 -
Ici on utilise une fonction standard void assert (int expression) qui indique un message d erreur si l expression est false. Ne pas oublier : include <cassert> void carte::ecrire () // écrit la couleur suivie de la valeur de la carte const char *tab1 = trèfle, carreau, coeur, pique ; const char *tab2 = valet, dame, roi ; if (v==1) cout << as ; if (v<=10) cout << v ; cout << tab2 v-11 ; cout << de << tab1 c ; La classe piledecartes doit permettre de représenter aussi bien tout le jeu (52 cartes) que la pile de cartes qu a en main un joueur. Les opérations à faire sont : - créer une pile vide (=constructeur) - créer une nouvelle pile qui correspond aux 52 cartes : nouvpile - mélanger ces cartes : melanger - savoir combien de cartes il y a dans la pile : nombrecartes - prendre une carte dans la pile : prendre - mettre une carte sur la pile : mettre - connaître la carte se trouvant à la position n0 dans la pile : regarder (n0 = 1 pour le sommet de la pile) - enlever toutes les cartes de la pile : vider class piledecartes public : piledecartes () : nombre(0) void nouvpile () ; void melanger () ; int nombrecartes () return nombre ; carte prendre () ; void mettre (carte k) ; carte regarder (int no) ; void vider () nombre=0 ; - 28 -
private : carte pile 52 ; int nombre ; ; Pour mélanger les cartes, on va utiliser la fonction standard rand qui permet d obtenir des nombres aléatoires. Le processus sera initialisé avec la fonction srand à laquelle on passera en paramètre le résultat de la fonction time. Donc, ne pas oublier : include <cstdlib> include <ctime> Il nous reste 5 fonctions membres à définir : void piledecartes::nouvpile () int n=0 ; for (couleur c=trefle; c<=pique; c=couleur(c+1)) for (int v=1; v<=13; v++) pile n++ = carte(c,v) ; nombre=52 ; void piledecartes::melanger () srand (time (0)) ; for (int i=1; i<1000; i++) int n1 = rand () % nombre ; int n2 = rand () % nombre ; carte temp = pile n1 ; pile n1 = pile n2 ; pile n2 = temp ; carte piledecartes::prendre () assert (nombre>0) ; return pile --nombre ; - 29 -
void piledecartes::mettre (carte k) assert (nombre<52) ; pile nombre++ = k ; carte piledecartes::regarder (int no) assert (no>=1 && no<=nombre) ; return pile nombre-no ; La classe joueur doit permettre de : - jouer = prendre une carte au sommet du paquet et la mettre dans la main : jouer - compter les points des cartes en main, tant pour l utilisateur que pour l ordinateur : points classe joueur public : joueur (piledecartes& paquetdecartes, bool estordi) : paquet(paquetdecartes), ordi(estordi) ; int jouer () ; private : piledecartes enmain ; piledecartes& paquet ; const bool ordi ; int points () ; ; N.B. - si chaque joueur a son propre paquet de cartes en main, le paquet dans lequel on puise est commun aux deux joueurs paquet est une référence : & - ordi est déclaré comme constant car cet attribut du joueur ne change pas - la fonction points est privée car utilisée en interne par la fonction jouer - 30 -
int joueur::points () int p=0, nbreas=0 ; // initialise le nombre de points et d as à 0 for (int i=1; i<=enmain.nombrecartes(); i++) int v=enmain.regarder (i).valeur () ; if (v==1) // c est un as p+=14 ; nbreas++ ; p+=v ; for (int j=1; j<= nbreas && p>21; j++) p-=13 ; // si on dépasse 21, on compte l as pour 1 return p ; La fonction jouer utilise le booléen continuer pour savoir si on veut une carte supplémentaire ou non : int joueur::jouer () bool continuer = true ; int p ; while (continuer) carte k= paquet.prendre () ; enmain.mettre (k) ; p=points () ; if (ordi) // c est l ordinateur qui joue cout << L ordi a pris ; k.ecrire () ; cout << endl ; if (p>=16) // l ordi décide d arrêter quand il arrive // à 16 points cout << L ordi a << p << points << endl ; continuer = false ; - 31 -
enmain.vider () ; return p ; // c est l utilisateur qui joue cout << Vous avez pris ; k.ecrire () ; cout << endl ; cout << Vous avez << p << points << endl ; if (p<21) char reponse 3 ; cout << Une carte supplémentaire? ; cin >> reponse ; continuer = reponse 0 == o ; continuer = false ; Reste la fonction principale dans laquelle on ajoutera les include nécessaires : int main () piledecartes paquet ; joueur vous (paquet, false) ; joueur moi (paquet, true) ; char reponse 3 ; bool continuer = true ; cout << Bonjour! << endl ; while (continuer) cout << Un nouveau jeu? << endl ; cin >> reponse ; continuer = reponse 0 == o ; if (continuer) paquet.nouvpile () ; paquet.melanger () ; int p1=vous.jouer () ; if (p1>21) cout << Vous avez perdu! << endl ; - 32 -
return 0 ; if (p1==21) cout << Vous avez gagné! << endl ; // l ordinateur doit jouer int p2=moi.jouer () ; if (p2<=21 && p2>=p1) cout << Vous avez perdu! << endl ; cout << Vous avez gagné! << endl ; Exercice : donner un exemple de ce que ce programme imprimerait à l exécution. - 33 -