Melange aleatoire - C - Programmation
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 ?
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é.
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é
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. |
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
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
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???
Marsh Posté le 29-12-2005 à 09:51:58
tu fais X permutations aléatoires dans ton tableau
Marsh Posté le 29-12-2005 à 13:08:25
Skullfisch a écrit : int main() |
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...
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
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)
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)
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
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 |
J'aime bien ta solution, mais j'avoue que j'aurais préféré ne pas avoir à l'admettre publiquement
Edit : cependant, je ne vois pas pourquoi tu veux que le champ supplémentaire soit un float plutôt qu'un entier
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
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 :
|
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.
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).
Marsh Posté le 29-12-2005 à 23:19:13
k, lol.
Marsh Posté le 29-12-2005 à 23:32:03
Arjuna a écrit : Moi, j'ai un truc simple à proposer... |
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) ???
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.
Marsh Posté le 30-12-2005 à 01:59:44
T'as un peu regardé ce que j'ai fait ou même pas ?
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;
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
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?
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
Marsh Posté le 30-12-2005 à 12:48:39
Sve@r a écrit : "rand() % x" c'est moyennement aléatoire |
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.
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
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"
Marsh Posté le 30-12-2005 à 14:31:35
Sve@r a écrit : |
Ouais mais c'est frustrant de voir un programme freezer ... jusqu'a ce qu'on bouge la souris
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 |
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 !!!
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 !!! |
Ah ouais, forcément le code devient vachement plus puissant qu'un rand()
( et au fait, t'as /dev/urandom )
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
Marsh Posté le 28-12-2005 à 04:50:31
Bonjour,
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