Melange aleatoire

Melange aleatoire - C - Programmation

Marsh Posté le 28-12-2005 à 04:50:31    

Bonjour, :hello:  
Je voudrais savoir si quelqu'un peut m'aider. J'ai un jeu de carte complet a faire en C mais je n'arrive pas a faire un programme ou une fonction qui me permettrait un melange aleatoire d'un jeu de carte. J'ai trouvé ca http://www.cppfrance.com/codes/MEL [...] 18593.aspx mais je comprend pas tout alors si quelqu'un peut corriger, faire plus simple ou m'expliquer ca serait cool... J'hesite aussi sur la facon dont je doit m'y prendre pour representer les cartes (structure,tableau d'entier ou de charactere...) alors si quelqu'un a une bonne idée elle sera la bien venue. :??:  
 
Merci

Reply

Marsh Posté le 28-12-2005 à 04:50:31   

Reply

Marsh Posté le 28-12-2005 à 14:29:17    

les solutions proposées sur la page que tu proposes sont vraiment contestables ...
 
tu dois juste mélanger les cartes ou tu devras aussi faire un jeu avec par la suite ?

Reply

Marsh Posté le 28-12-2005 à 18:40:28    

Je dois melanger les cartes et effectivement aprés je dois faire un jeu avec. Le spider solitaire de Win XP. Mais juste avec les bases de la programmation en C. Sans interface graphique evolué.  

Reply

Marsh Posté le 28-12-2005 à 19:05:04    

pour représenter les cartes, j'imagine que tu préfèreras avoir une structure contenant les infos de la carte (valeur / couleur, éventuellement un nom pour l'affichage) afin de faciliter les traitements ultérieurs.
 
Pour le conteneur lui-même, c'est suivant ce que tu comptes en faire. Mais j'imagine que ce qui sera le plus pratique pour ton usage sera soit la liste chaînée, soit le tableau.
La liste étant plus flexible si tu veux redimensionner ton ensemble, le tableau étant plus intuitif à manipuler (et directement présent dans le langage)
 
Edit : En tout cas, il te faudra probablement un système de pile, si je me souviens bien du jeu ... Or, à partir du moment où tu as fait une pile, faire une liste n'est pas beaucoup plus compliqué

Message cité 1 fois
Message édité par theshockwave le 28-12-2005 à 19:05:53
Reply

Marsh Posté le 28-12-2005 à 21:06:26    

theshockwave a écrit :

pour représenter les cartes, j'imagine que tu préfèreras avoir une structure contenant les infos de la carte (valeur / couleur, éventuellement un nom pour l'affichage) afin de faciliter les traitements ultérieurs.
 
Pour le conteneur lui-même, c'est suivant ce que tu comptes en faire. Mais j'imagine que ce qui sera le plus pratique pour ton usage sera soit la liste chaînée, soit le tableau.
La liste étant plus flexible si tu veux redimensionner ton ensemble, le tableau étant plus intuitif à manipuler (et directement présent dans le langage)
 
Edit : En tout cas, il te faudra probablement un système de pile, si je me souviens bien du jeu ... Or, à partir du moment où tu as fait une pile, faire une liste n'est pas beaucoup plus compliqué


 
Etant donné que la liste est déjà établie (52 cartes) et qu'il n'y a aucun redimensionnement à faire, le tableau me semble le plus pratique à traiter. Au pire, si on ne doit pas utiliser toutes les cartes pour une raison x ou y, on intègre dans le conteneur un flag permettant d'invalider les cartes choisies...
 
Sinon j'ai lu l'algo présenté sur la page citée mais j'ai aucune idée sur sa valeur. Juste un truc concernant l'aléa qui a déjà été dit sur ce forum ici:
http://forum.hardware.fr/hardwaref [...] 9316-1.htm : pour choisir un nombre entre 0 et N, vaut mieux utiliser la formule "rand() * N / (RAND_MAX + 1)" car le nombre sorti est plus uniformément aléatoire qu'un simple "rand() % N" => démo ici: http://dejean.benoit.free.fr/code/rand.c.html


Message édité par Sve@r le 28-12-2005 à 21:15:45
Reply

Marsh Posté le 29-12-2005 à 01:24:12    

Bon voila en fait je vais representer une carte comme ca:
struct {
       int couleur; //(1,2,3,4)
       int valeur; //(1,2,3,4,5,6,7,8,9,10,11,12,13)
       int affichage; //(0,1)
       }carte;
C'est correct?
 
En tout il y a 10 piles de cartes et 1 pioche alors je pense que je vais faire un tableau avec un grand nombre de case pour chacun vu que de toute facon dans le jeu il y un nombre defini de 104 cartes. (2 jeu de 52 mais les couleurs dependent du niveau)
Pour le melange aleatoire je vais me pencher sur le programme dans ton lien ca m'a l'air pas mal.
 Merci


Message édité par Skullfisch le 29-12-2005 à 01:25:32
Reply

Marsh Posté le 29-12-2005 à 01:42:26    

int main()  
{  
   int nb,i,j;
     
   srand(time(NULL));  
   for(i=0;i<20;i++)  
   {  
       
     nb = rand() % 20;  
     printf("%d\n",nb);  
   
   }  
   scanf("%d",&j);
     
}  
 
Bon voila alors admettons que je range toutes mes cartes de mon jeu dans un tableau. Je vais utiliser un programme dans ce genre la pour melanger chaque case de mon tableau mais le probleme c'est qu'une valeur peut etre prise plusieurs fois, or il me faut un tirage aleatoire sans repetition. Et la il y a des repetitions. J'ai mis 20 pour que se soit plus court a verifier mais il me faut 104 valeurs entre 0 et 103 en fait si je ne me trompe pas pour un tableau.
Alors qu'est qu'il faut que je change pour que ca marche?
En fait il faudrait que j'introduise un  
do (nb = rand() % 20)
while (nb = un des nb saisis avant)
mais je sais pas comment verifier avec tous les nb saisis avant.
Une meilleur idée???

Message cité 1 fois
Message édité par Skullfisch le 29-12-2005 à 01:56:48
Reply

Marsh Posté le 29-12-2005 à 09:51:58    

tu fais X permutations aléatoires dans ton tableau


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 29-12-2005 à 13:08:25    

Skullfisch a écrit :

int main()  
{  
   int nb,i,j;
     
   srand(time(NULL));  
   for(i=0;i<20;i++)  
   {  
       
     nb = rand() % 20;  
     printf("%d\n",nb);  
   
   }  
   scanf("%d",&j);
     
}  
 
Bon voila alors admettons que je range toutes mes cartes de mon jeu dans un tableau. Je vais utiliser un programme dans ce genre la pour melanger chaque case de mon tableau mais le probleme c'est qu'une valeur peut etre prise plusieurs fois, or il me faut un tirage aleatoire sans repetition. Et la il y a des repetitions. J'ai mis 20 pour que se soit plus court a verifier mais il me faut 104 valeurs entre 0 et 103 en fait si je ne me trompe pas pour un tableau.
Alors qu'est qu'il faut que je change pour que ca marche?
En fait il faudrait que j'introduise un  
do (nb = rand() % 20)
while (nb = un des nb saisis avant)
mais je sais pas comment verifier avec tous les nb saisis avant.
Une meilleur idée???


 
L'ides de BlackGoddess est pas mal (mais "X" doit être aux alentours de "100* nb_elements" minimum).
 
Sinon pour ta culture perso, si tu veux vérifier que ton nb sorti n'a pas déjà été sorti, alors tu définis un tableau de 20 int et dès que tu as un "nb=rand()", tu vas voir si "tab[nb]" vaut "1". Si oui, alors tu recherches un nouveau "nb" sinon tu le mets à "1" et tu passes au "i" suivant. Et tu peux même te passer de ce tableau si t'intègres un flag supplémentaire style "int tire" dans ta structure "carte" que tu mets à "1" pour chaque "carte[nb]"
 
PS: Il est plus lisible de nommer ses structures "s_qqchose". On s'y retrouve mieux ensuite quand il faut trouver des noms pour les variables...

Message cité 1 fois
Message édité par Sve@r le 29-12-2005 à 13:14:50
Reply

Marsh Posté le 29-12-2005 à 13:38:12    

google : shuffle

Reply

Marsh Posté le 29-12-2005 à 13:38:12   

Reply

Marsh Posté le 29-12-2005 à 14:16:10    

Sve@r a écrit :

tu définis un tableau de 20 int et dès que tu as un "nb=rand()", tu vas voir si "tab[nb]" vaut "1". Si oui, alors tu recherches un nouveau "nb" sinon tu le mets à "1" et tu passes au "i" suivant. Et tu peux même te passer de ce tableau si t'intègres un flag supplémentaire style "int tire" dans ta structure "carte" que tu mets à "1" pour chaque "carte[nb]"


et c'est comme ca qu'on se retrouve avec un tirage de cartes qui prend des plombes parce que lorsqu'il ne reste plus que quelques éléments, il faut faire des centaines de tirages pour tomber dessus :o
c'est sur qu'avec un tableau, le coup des permutations est ce qui semble le plus tentant. Avec un autre structure de données, on a moyen de faire des mélanges un peu plus "jolis" (moyennant la construction d'une deuxième structure et le vidage de la première)

Reply

Marsh Posté le 29-12-2005 à 14:54:50    

Moi, j'ai un truc simple à proposer...
 
Tu crée une structure avec deux fields :
- float
- carte
 
Tu remplis un tableau de 52 lignes avec, en mettant tes cartes dans l'ordre dans le field.
 
Tu génères 52 nombres aléatoires avec la fonction rand() et tu les met dans le field float des structures de ton array.
 
Puis tu fais un quicksort sur ce nombre afin de trier les cartes dans un ordre aléatoire.
 
Ca me semble suffisament aléatoire pour un jeu de carte, et pas loin de ce qu'on peut faire de plus rapide (52 nombres aléatoires générés, et un seul tri simple dans un tableau sans trou ni doublon)

Message cité 1 fois
Message édité par Arjuna le 29-12-2005 à 14:56:40
Reply

Marsh Posté le 29-12-2005 à 14:58:33    

Quand je lis vos post, je trouve que vous avez l'esprit bien tordu pour un résultat plutôt pas convainquant :D

Reply

Marsh Posté le 29-12-2005 à 15:07:14    

Arjuna a écrit :

Quand je lis vos post, je trouve que vous avez l'esprit bien tordu pour un résultat plutôt pas convainquant :D


 
J'aime bien ta solution, mais j'avoue que j'aurais préféré ne pas avoir à l'admettre publiquement :o
 
:whistle:
Edit : cependant, je ne vois pas pourquoi tu veux que le champ supplémentaire soit un float plutôt qu'un entier


Message édité par theshockwave le 29-12-2005 à 15:07:45
Reply

Marsh Posté le 29-12-2005 à 15:33:23    

parceque rand retourne un float et que j'imagine qu'un tri sur des float ça reste plus rapide qu'un cast en int puis un tri sur des int, mais je peux me tromper ;)


Message édité par Arjuna le 29-12-2005 à 15:33:30
Reply

Marsh Posté le 29-12-2005 à 15:57:04    

en C, rand retourne un int :o

Reply

Marsh Posté le 29-12-2005 à 16:59:58    

Une idée d'algo de mélange d'un tableau "sur place" , le principe est d'avancer dans le tableau, avec la partie de tab[0] à tab[i] mélangée, et la partie de tab[i+1] à tab[51] pas encore mélangée dans laquelle on pioche une carte qu'on met à la fin de la partie mélangée.

Code :
  1. for (i=0;i<51;i++)
  2.  {
  3.     /* On choisit un entier au pif entre i et 51; */
  4.     randval = (rand() % (52-i)) + i;
  5.     /* On permute tab[i] et tab[randval] */
  6.     tmp = tab[i];
  7.     tab[i] = tab[randval];
  8.     tab[randval] = tmp;
  9.  }


PS : jvient d'improviser donc c'est ptêtre tout foireux, mais si jme trompe pas, ca fait kkchose ne necessitant pas de tri et avec un minimum de rand, quand à la qualité du mélange, d'instinct je dirait correct vu qu'on prends consécutivement une carte au hasard dans les triées, en pratique je garanti rien.
PS² : evidement le modulo dans le rand() c'est histoire de faire un code lisible, à remplacer par le truc a base de division si necessaire. ( encore que pour un jeu de carte je me demande si la qualité du rand est si importante ... )
 
[edit]
Testé et corrigé le % doit être 52 et pas 51 dans le code, sinon la dernière carte n'est jamais mélangée.
Donc visiblement ca fonctionne, si un expert du random peut donner son avis sur la qualité du mélange je dis pas non cela dit.


Message édité par 0x90 le 29-12-2005 à 17:13:58

---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
Reply

Marsh Posté le 29-12-2005 à 23:05:48    

Bon j'ai pas encore testé mais j'ai fais un melange comm ca:
 
   int a,b,temp,compt,k;
   compt=0;
     
   srand(time(NULL));
     
   do {
      a = rand() % 104;  
      do {  
         b = rand() % 104;
         }
      while (b==a);
           
      /*tabjeu [temp] = tabjeu [a]
      tabjeu [a] = tabjeu [b]
      tabjeu [b] = tabjeu [temp]*/
   
      compt = compt+1;
      }
   while (compt<100);
       
   scanf("%d",&k);
   }  
 
ca me fais un bon melange c'est pas grave si tout n'est pas melangé aprés je peux rajouter encore des permutations et en mettre plus de 100.
Par contre maintenant il faut que j'arrive a le faire foncctionner sur tabjeu qui est un tableau de 104 cartes. (2 jeu de 52).

Reply

Marsh Posté le 29-12-2005 à 23:19:13    

Reply

Marsh Posté le 29-12-2005 à 23:32:03    

Arjuna a écrit :

Moi, j'ai un truc simple à proposer...
 
Tu crée une structure avec deux fields :
- float
- carte
 
Tu remplis un tableau de 52 lignes avec, en mettant tes cartes dans l'ordre dans le field.
 
Tu génères 52 nombres aléatoires avec la fonction rand() et tu les met dans le field float des structures de ton array.
 
Puis tu fais un quicksort sur ce nombre afin de trier les cartes dans un ordre aléatoire.
 
Ca me semble suffisament aléatoire pour un jeu de carte, et pas loin de ce qu'on peut faire de plus rapide (52 nombres aléatoires générés, et un seul tri simple dans un tableau sans trou ni doublon)


 
Et pourquoi ne pas intégrer l'aléa directement dans la fonction qui sert à comparer 2 éléments (celle dont on passe le pointeur en 4° paramètre de qsort) ???

Reply

Marsh Posté le 30-12-2005 à 01:51:50    

Le probleme c'est qu'il y a des fonctions genre qsort que j'ai pas encore vu en cours donc j'ai pas encore le droit de les uitiliser.

Reply

Marsh Posté le 30-12-2005 à 01:59:44    

T'as un peu regardé ce que j'ai fait ou même pas ?


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
Reply

Marsh Posté le 30-12-2005 à 02:32:02    

OUi je viens de regarder. L'avantage effectivement c'est que tout est melangé et que c'est plus court.
par contre j'ai un peu de mal a comprendre la ligne la si tu peux m'expliquer:  
randval = (rand() % (52-i)) + i;

Reply

Marsh Posté le 30-12-2005 à 02:37:58    

rand() % x , c'est une valeur entre 0 et x-1.
rand() % (52-i) c'est une valeur entre 0 et 51-i
(rand() % (52-i)) + i c'est une valeur entre i et 51.
voila c'est tout [:spamafote]


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
Reply

Marsh Posté le 30-12-2005 à 03:09:28    

OK merci c cool ben je vais prendre ca.

Reply

Marsh Posté le 30-12-2005 à 03:21:04    

J'ai apporté une petite modif pour simplifier:
for (i=0;i<52;i++)  {      
    /* On choisit un entier au pif entre 0 et 51; */      
    randval = (rand() % 51);
    printf("%d : %d\n",i,randval);    
    /* On permute tab[i] et tab[randval] */      
    tmp = tab[i];      
    tab[i] = tab[randval];      
    tab[randval] = tmp;  }
     scanf("%d",&k);
}  
Comme ca on est sur que toutes les cartes sont melangées n'importe ou.
Mais est ce que ca pose probleme si i=randval?


Message édité par Skullfisch le 30-12-2005 à 03:31:11
Reply

Marsh Posté le 30-12-2005 à 11:30:04    

sinon, le shuffle c'est bieng aussi

Reply

Marsh Posté le 30-12-2005 à 12:32:33    

0x90 a écrit :

rand() % x , c'est une valeur entre 0 et x-1.


 
"rand() % x" c'est moyennement aléatoire
"rand() / (RAND_MAX + 1.0) * x" c'est un meilleur aléa => http://dejean.benoit.free.fr/code/rand.c.html

Message cité 1 fois
Message édité par Sve@r le 30-12-2005 à 12:33:53
Reply

Marsh Posté le 30-12-2005 à 12:48:39    

Sve@r a écrit :

"rand() % x" c'est moyennement aléatoire
"rand() / (RAND_MAX + 1.0) * x" c'est un meilleur aléa => http://dejean.benoit.free.fr/code/rand.c.html


 
Je sais et j'ai déja expliqué plus haut pkoi j'ai mis rand() % x
( au passage son test du rand me semble vachement foireux mais bon ... )
Et pour être précis ca dépends des plateformes, sous un linux pas trop vieux, rand est aussi bon sur les bits de poids faible que sur les bits de poids fort.


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
Reply

Marsh Posté le 30-12-2005 à 13:56:13    

0x90 a écrit :

Je sais et j'ai déja expliqué plus haut pkoi j'ai mis rand() % x


oups... désolé j'avais pas tout lu  :jap:  

0x90 a écrit :

Et pour être précis ca dépends des plateformes, sous un linux pas trop vieux, rand est aussi bon sur les bits de poids faible que sur les bits de poids fort.


Ah ben sur Linux autant aller taper directement dans "/dev/random"  :sol:  

Reply

Marsh Posté le 30-12-2005 à 14:31:35    

Sve@r a écrit :


Ah ben sur Linux autant aller taper directement dans "/dev/random"  :sol:


Ouais mais c'est frustrant de voir un programme freezer ... jusqu'a ce qu'on bouge la souris  [:0x90]  


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
Reply

Marsh Posté le 30-12-2005 à 15:45:22    

0x90 a écrit :

Ouais mais c'est frustrant de voir un programme freezer ... jusqu'a ce qu'on bouge la souris  [:0x90]


 
Mais non, on crée un processus fils avec "fork()" et le fils fait des system("find" ) en boucle infinie pour faire bouger le disque !!!  :D  :D  

Reply

Marsh Posté le 30-12-2005 à 15:49:32    

Sve@r a écrit :

Mais non, on crée un processus fils avec "fork()" et le fils fait des system("find" ) en boucle infinie pour faire bouger le disque !!!  :D  :D


 
Ah ouais, forcément le code devient vachement plus puissant qu'un rand() :o
 
( et au fait, t'as /dev/urandom :o )


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
Reply

Marsh Posté le 31-12-2005 à 01:39:47    

Skullfisch a écrit :

Le probleme c'est qu'il y a des fonctions genre qsort que j'ai pas encore vu en cours donc j'ai pas encore le droit de les uitiliser.


bah... moi j'ai parlé de qsort parceque c'est une des solutions de tri les plus simples et les plus rapides, mais fait pas t'arrêter à ça, tu peux aussi utiliser un tri à bulles ou n'importe quoi d'autre ;)

Reply

Marsh Posté le 01-01-2006 à 18:58:16    

Ah ben j'ai le même projet à faire

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed