begin process at 2012 02 13 07:37:21
  Trouver un code source :
 
dans
 
Accueil > 

Tutoriels

 > 

Jeux

 > DISTRIBUER UN JEU DE CARTES

DISTRIBUER UN JEU DE CARTES


 Information sur le tutoriel

Déposé par bzrd le 16/12/2008 17:33:30
Dans la catégorie Jeux
Vu : 15 100 fois
 

Ecrire un message privé à l'auteur
Commentaire sur cette source (11)
Ajouter un commentaire et/ou une note

Note :
Aucune note

 Description

J'en ai un peu marre de voir des jeux où les cartes sont distribuées de façon totalement aléatoire mais sans garantie de non bouclage !
Si le rand() utilisé a le malheur de ne jamais passer par une valeur donnée on ne sort jamais de la boucle de distribution et dans le meilleur des cas ça peut être très long.

Voici un algorithme TRES simple, qui permet de distribuer N cartes différentes, en O(N), sans test, sans risque, ...

Cordialement

Tutorial


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
char *TabValeur[] = {"As", "2", "3", "4", "5", "6", "7", "8", "9", "10", "valet", "dame", "roi"};
char *TabCouleur[] = {"trèfle", "carreau", "coeur", "pique"};
// Définir la structure des cartes
// (on pourrait mettre des chaines directement, ou un autre système ...)
typedef struct _CARTE_ {
int valeur; // 0 à 12 pour As à Roi
int couleur; // 0 à 3 (trefle, carreau coeur et pique) !!
// On pourrait mettre un enum, mais ce n'est pas l'objet ici
} CARTE;
// Le jeu de cartes (en global pour simplifier)
CARTE Jeu[52];
int gMax; // indice de carte maximal (52 au départ)
 
// Initialisation du jeu
// En sortie, Jeu[0] vaut As de trefle, Jeu[1] 2 de trefle, ...
void InitJeu()
{
int val, coul, i;;

// on le fait très simple, OK ?
i = 0;
for (coul=0; coul<=3; coul++)
{
for (val=0; val<13; val++)
{
Jeu[i].valeur = val;
Jeu[i].couleur = coul;
i++;
}
}

/*
avec typedef struct _CARTE_ {
char carte[32];
} CARTE;

on ferait
for (i=0; i<52; i++)
sprintf(Jeu[i].carte, "%s de %s", TabValeur[i%13], TabCouleur[i/13]);
*/
}
// Distribuer Cartes
// Renvoie une carte à la fois
// En entrée, pCarte pointe sur une structure déjà allouée et en sortie on renvoie le même pointeur (si, si ! Ca peut être utile ...)
// Pas besoin de mélanger le tableau au départ, ni de vérifier qu'une carte a déjà été distribuée, ...
CARTE *Distribue(CARTE *pCarte)
{
int indice;

if (gMax)
indice = rand()%(gMax); // gMax vaut 51 au départ, puis 50, 49, ...
else
indice = 0;
// on renseigne la carte choisie, prise au hasard
*pCarte = Jeu[indice];

// On insère la dernière carte du paquet à la place !!!
Jeu[indice] = Jeu[gMax];


// ou si votre compilo n'aime pas les copies de structures
// pCarte->valeur = Jeu[indice].valeur;
// pCarte->couleur = Jeu[indice].couleur;
//
// Jeu[indice].valeur = Jeu[gMax].valeur;
// Jeu[indice].couleur = Jeu[gMax].couleur;

// une carte de moins dans le paquet
gMax--;
return pCarte;
}
 
int main(int argc, char **argv)
{
int i;
CARTE Carte;

srand(time(NULL)); // initialiser le générateur aléatoire
gMax = 51;
InitJeu();

for (i=0; i<52; i++)
{
Distribue(&Carte);
printf("%d -- %s de %s\n", i, TabValeur[Carte.valeur], TabCouleur[Carte.couleur]);
}
}
// Le tableau au cours des distributions :
// Au début on a
//
// Jeu[0] = "as de trèfle"
// Jeu[1] = "2 de trèfle"
// Jeu[2] = "3 de trèfle"
// Jeu[3] = "4 de trèfle"
// ...
// Jeu[50] = "10 de pique"
// Jeu[51] = "valet de pique"
// Jeu[52] = "dame de pique"
// Jeu[53] = "roi de pique" <<--- gMax
//
// supposons qu'on ait tiré le 3 de trèfle la première fois
// on a
// Jeu[0] = "as de trèfle"
// Jeu[1] = "2 de trèfle"
// Jeu[2] = "roi de pique" <--- remplacement -----------------------+
// Jeu[3] = "4 de trèfle" |
// ... |
// Jeu[50] = "10 de pique" |
// Jeu[51] = "valet de pique" |
// Jeu[52] = "dame de pique" <<--- gMax |
// Jeu[53] = "roi de pique" <- cette entrée n'est plus accessible --+
//
// si on tire le 10 de pique ensuite
// on a
// Jeu[0] = "as de trèfle"
// Jeu[1] = "2 de trèfle"
// Jeu[2] = "roi de pique"
// Jeu[3] = "4 de trèfle"
// ...
// Jeu[50] = "dame de pique" <--- remplacement ----------------------+
// Jeu[51] = "valet de pique" <<--- gMax |
// Jeu[52] = "dame de pique" <- cette entrée n'est plus accessible --+
// Jeu[53] = "roi de pique" <- cette entrée n'est plus accessible
//
/// ainsi de suite ...

 Historique

17 décembre 2008 09:59:37 :
Comme on me l'a justement fait remarquer, un jeu normal contient 52 cartes et pas 54 ! J'aurais dû mettre un #define ...
17 décembre 2008 10:04:23 :
Comme on me l'a justement faite remarque, un jeu de cartes normal comprend 52 cartes et pas 54 ! J'aurais dû mettre un #define ... J'espère que la modification va être prise en compte, sinon pour remplacez les 54 par 52 et ça fonctionnera !
16 mars 2009 10:17:03 :
Corrections de bugs (au niveau des indices surtout !) Désolé.

Commentaires

Commentaire de Pistol_Pete le 16/12/2008 19:17:50

Salut
Un jeu de carte ce n'est pas 52 cartes? Si tu en met 54, il faut gérer les 2 jokers...

A+

Commentaire de bzrd le 17/12/2008 09:54:38

Oups !
Tu as tout à fait raison. C'est parce que j'ai tapé ça très vite après avoir vu un n-ième programme de distribution ...
Je vais corriger de suite ...

Peite note complémentaire : cet algo si simple je l'ai réalisé la première fois qu'en TP je devais distribuer des cartes ... il y a 25 ans !

Commentaire de linker2008 le 09/02/2009 19:33:36

excellent travail ,tu peut l'ameliorer

Commentaire de lui88 le 17/03/2009 18:13:47

excellent ;)

Commentaire de juju12 le 08/05/2009 20:28:38

Problème tout de même :
la distribution des cartes n'est absolument pas uniforme.
Si l'on part du principe que l'initialisation du générateur aléatoire est entièrement corrélée au paramètre de srand(), soit un entier 32 bits, on obtient exactement 2^32 tirages possibles... à comparer avec les 52! façons de classifier un jeu de cartes...(52! ~ 2^1000)
ça peut être problématique si la quinte flush est dans les tirages non effectués...

Commentaire de bzrd le 11/05/2009 14:17:16

Effectivement, ça peut être un problème !
Néanmoins les algorithmes qu'on rencontre habituellement (et que je dénonce ici) font la même chose puisqu'ils sont tous basés sur srand/rand.

D'un autre côté le but ici n'est pas de trouver la solution parfaite au problème de distribution aléatoire mais bien de trouver un algorithme pour la distribution qui soit rapide et sûr.

Rien ne t'empêche de remplacer les fonctions rand et srand par des fonctions propres (avec des valeurs sur 1024 bits minimum), mais tu n'auras toujours pas la garantie que tu couvres tous les cas.
Il y a bien 25 ans que j'ai plus lu les bouquins de Knuth sur l'art de la programmation (notamment des générateurs aléatoires) et je ne saurai pas te répondre sur le fond ...

Une remarque encore : en général on distribue un jeu entre N joueurs et au bout du compte ce qui est intéressant ce sont les cartes qu'ils ont en main, pas leur ordre de distribution, donc dans la majorité des cas on a moins de 52! distributions (je dis bien "dans la majorité des cas").

Ta question, tout à fait pertinente je le répète, en entraine une autre : les casinos en ligne utilisent quel algorithme de distribution ?

Cordialement.

Commentaire de lectpe le 21/05/2009 19:47:31

Bonjour à tous.

Moi je n'ai pas procédé ainsi pour la distribution des cartes :
d'abord j'ai initialisé un tableau contenant toutes les cartes,
je l'ai ensuite mélangé de façon aléatoire,
et enfin distribué les cartes : les 26 premières au joueur, les 26 restantes à l'ordinateur.

Cordialement, Grégory.

Commentaire de Debiars le 12/11/2009 11:35:49

Bravo Lectre, c'est la manière la plus simple et efficace de procéder.
De plus, en affectant à RandSeed une valeur, le numéro du jeu par exemmple, on a la possibilité de le rejouer avec les mêmes cartes...

Cordialement, un delphiste qui s'ennuie

Commentaire de 007Julien le 24/03/2011 20:49:38


Comment se fait-il que les joueurs acceptent de jouer avec des cartes neuves ? Je doute que les mélanges opérés à la main, même longuement prolongés, recouvrent les 52! façons de classer un jeu...

Par ailleurs, le phénomène évoqué n'interdit pas l'uniformité de la loi de probabilité d'un tirage parmi N valeurs. Ce tirage opéré avec un %N sur RAND_MAX est uniforme à très peu de choses près.

Commentaire de bzrd le 25/03/2011 10:00:52

Bonjour,
Qu'on joue avec un jeu neuf (au départ trié) mélangé ou un jeu ancien ne change rien ! Un jeu ancien n'est jamais qu'un jeu neuf "longuement mélangé" ...
En ce qui concerne la probabilité d'un tirage, je ne suis pas d'accord : il y a 2^32 façons d'initaliser le générateur (pseudo)aléatoire, soit 4.3*10^9 et 52! ou 8*10^67 classements différents, donc on ne peut avoir qu'une infime partie des tirages !
En réalité il n'y a pas tout à fait 52! tirages, en effet si on distribue un jeu entre 4 personnes, il y a 52!/(13! * 39!) mains différentes (6.3*10^11), soit quand même 150 fois plus que de tirages aléatoires.
Enfin étant magicien amateur, si je devais jouer avec un vrai jeu, je préférerais un jeu neuf correctement mélangé qu'un vieux, qui est plus facile à marquer ou à "trafiquer" ...

Commentaire de 007Julien le 25/03/2011 10:37:47

J'ai bien compris le raisonnement, mais il convient de ne pas tout confondre...

Les joueurs qui pratiquent avec un jeu neuf ne jouent qu'avec un nombre réduit de distributions mais cela ne change, fort heureusement, ni les probabilités d'obtenir telle ou telle distribution, ni l'uniformité de leur loi de probabilité.

Et puis, il est facile de remédier au défaut dénoncé en repartant non pas du jeu trié, mais du jeu précédemment distribué.

 Ajouter un commentaire




Nos sponsors


Sondage...

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,062 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales