"Changer taille tableau de chaine de caractère en C"
loki9678
-
loki9678 -
loki9678 -
Bonjour,
je souhaite réaliser une pioche aléatoire de 16 cartes.
Cependant étant donné que il ne faut pas tirer deux fois la même carte j'ai procédé ainsi.
je crée donc deux tableau de chaine de caractère de "16 ligne et 10 colonnes".
Je crée une boucle while dans laquelle :
Je tire un nombre aléatoire compris entre 0 et 31 et j'associe le nombre à une case du tableau 1.
J'affiche la carte tirée a l'écran pour informer l'utilisateur.
Ensuite je copie la carte tirée avec strcpy dans le tableau 2.
Puis je supprime la carte avec memmove.
Le problème étant que lors du premier tirage la carte se copie bien dans le tableau 2. Cependant dans le tableau 1 il y'a une carte qui se duplique. Cette carte étant à chaque fois la carte tirée+3.
Voici un exemple de ce qui est affiché:
Pour piocher entrez 0:
0
La carte choisi est : carte 10
///--------------------------------------------Tableau1--------------------------------------//
carte 1
carte 2
carte 3
carte 4
carte 5
carte 6
carte 7
carte 8
carte 9
carte 11
carte 12
carte 13 ///Ici le 13 se duplique
carte 13
carte 14
carte 15
carte 16
carte 17
carte 18
carte 19
carte 20
carte 21
carte 22
carte 23
carte 24
carte 25
carte 26
carte 27
carte 28
carte 29
carte 30
carte 31
carte 32
//-------------------------------------------tableau2--------------------------------------//
carte 10
Le second tableau me permet de changer de pioche quand la première est vide pour ne pas tirer plusieurs fois la même carte.
Pour remédier à ce problème je souhaitait baisser la taille du tableau à chaque tirage pour empêcher une duplication.
Sauriez vous comment remédier à ce problème soit en redimensionnant le tableau soit d'une autre manière?
Merci d'avance.
je souhaite réaliser une pioche aléatoire de 16 cartes.
Cependant étant donné que il ne faut pas tirer deux fois la même carte j'ai procédé ainsi.
je crée donc deux tableau de chaine de caractère de "16 ligne et 10 colonnes".
Je crée une boucle while dans laquelle :
Je tire un nombre aléatoire compris entre 0 et 31 et j'associe le nombre à une case du tableau 1.
J'affiche la carte tirée a l'écran pour informer l'utilisateur.
Ensuite je copie la carte tirée avec strcpy dans le tableau 2.
Puis je supprime la carte avec memmove.
Le problème étant que lors du premier tirage la carte se copie bien dans le tableau 2. Cependant dans le tableau 1 il y'a une carte qui se duplique. Cette carte étant à chaque fois la carte tirée+3.
Voici un exemple de ce qui est affiché:
Pour piocher entrez 0:
0
La carte choisi est : carte 10
///--------------------------------------------Tableau1--------------------------------------//
carte 1
carte 2
carte 3
carte 4
carte 5
carte 6
carte 7
carte 8
carte 9
carte 11
carte 12
carte 13 ///Ici le 13 se duplique
carte 13
carte 14
carte 15
carte 16
carte 17
carte 18
carte 19
carte 20
carte 21
carte 22
carte 23
carte 24
carte 25
carte 26
carte 27
carte 28
carte 29
carte 30
carte 31
carte 32
//-------------------------------------------tableau2--------------------------------------//
carte 10
Le second tableau me permet de changer de pioche quand la première est vide pour ne pas tirer plusieurs fois la même carte.
Pour remédier à ce problème je souhaitait baisser la taille du tableau à chaque tirage pour empêcher une duplication.
Sauriez vous comment remédier à ce problème soit en redimensionnant le tableau soit d'une autre manière?
Merci d'avance.
A voir également:
- "Changer taille tableau de chaine de caractère en C"
- Changer dns - Guide
- Comment réduire la taille d'un fichier - Guide
- Tableau word - Guide
- Caractère ascii - Guide
- Caractère spéciaux - Guide
4 réponses
yg_be
Messages postés
23541
Date d'inscription
Statut
Contributeur
Dernière intervention
Ambassadeur
1 584
bonjour,
peux-tu partager la source de ton programme?
merci d'utiliser les balises de code: https://codes-sources.commentcamarche.net/faq/11288-les-balises-de-code
Pour empêcher une duplication, ne suffit-il pas de réduire le choix au moment de tirer un nombre aléatoire?
Je suis surpris que la carte tirée ne se mette pas au début du tableau 2: est-ce intentionnel?
peux-tu partager la source de ton programme?
merci d'utiliser les balises de code: https://codes-sources.commentcamarche.net/faq/11288-les-balises-de-code
Pour empêcher une duplication, ne suffit-il pas de réduire le choix au moment de tirer un nombre aléatoire?
Je suis surpris que la carte tirée ne se mette pas au début du tableau 2: est-ce intentionnel?
Bonjour,
Ta méthode n'est pas la plus simple.
En tout cas, il semble que ton
Ta méthode n'est pas la plus simple.
En tout cas, il semble que ton
memmove()n'a pas les bons paramètres.
Salut loki9678,
Comme le dit Dalfab, ta méthode est compliquée... en fait, c'est une usine à gaz :-)
Pour mélanger tes cartes et les tirer une à une, fais comme avec un vrai paquet de cartes :
1. tu mélanges le paquet : fais un shuffle du tableau de 16 éléments, ton tableau contient maintenant tes cartes dans un ordre aléatoire
2. la carte du dessus est : carte_courante = 0
3. tu prends la carte du dessus : tableau[carte_courante]
4. tu incrémentes carte_courante tant qu'il y a des cartes restant à tirer et tu boucles sur 3
Tu fais tout ceci avec un seul tableau et sans avoir à décaler quoi que ce soit ou faire quoi que ce soit d'autre qu'incrémenter l'index après avoir mélangé le contenu du tableau.
Pour faire un bon shuffle renseigne toi sur le mélange Fisher-Yates. Outre la méthode de mélange, tu peux aussi envisager d'utiliser un générateur de nombres aléatoires plus performant que rand() si tu veux un mélange évitant les biais de la fonction standard.
Dal
Comme le dit Dalfab, ta méthode est compliquée... en fait, c'est une usine à gaz :-)
Pour mélanger tes cartes et les tirer une à une, fais comme avec un vrai paquet de cartes :
1. tu mélanges le paquet : fais un shuffle du tableau de 16 éléments, ton tableau contient maintenant tes cartes dans un ordre aléatoire
2. la carte du dessus est : carte_courante = 0
3. tu prends la carte du dessus : tableau[carte_courante]
4. tu incrémentes carte_courante tant qu'il y a des cartes restant à tirer et tu boucles sur 3
Tu fais tout ceci avec un seul tableau et sans avoir à décaler quoi que ce soit ou faire quoi que ce soit d'autre qu'incrémenter l'index après avoir mélangé le contenu du tableau.
Pour faire un bon shuffle renseigne toi sur le mélange Fisher-Yates. Outre la méthode de mélange, tu peux aussi envisager d'utiliser un générateur de nombres aléatoires plus performant que rand() si tu veux un mélange évitant les biais de la fonction standard.
Dal
Bonjour Dal,
Merci de votre réponse.
Si j'ai bien compris vous me conseillez de créer un tableau de 16 cartes. Ensuite de mélanger ce tableau avec un shuffle que je devrais potentiellement faire avec la méthode de Fisher-Yates. Et ensuite de tirer les cartes 1 par 1 et dans l'ordre du nouveau tableau mélangé ? Peut-être avec une boucle for je pense
Loki9678
Merci de votre réponse.
Si j'ai bien compris vous me conseillez de créer un tableau de 16 cartes. Ensuite de mélanger ce tableau avec un shuffle que je devrais potentiellement faire avec la méthode de Fisher-Yates. Et ensuite de tirer les cartes 1 par 1 et dans l'ordre du nouveau tableau mélangé ? Peut-être avec une boucle for je pense
Loki9678
J'ai essayé alors la méthode de Fisher-Yates cependant je crois que le fait que mon tableau soit composé de chaine de caractère empêche le bon fonctionnement du programme.
Voici le nouveau code:
Et voici ce qui ce passe quand j'essaye d'afficher la pioche mélangée:
carte 1
carte 2
carte 3
carte 4
carte 5
carte 6
carte 7
carte 8
carte 9
carte 10
carte 11
carte 12
carte 13
carte 14
carte 15
carte 16
Entrez 0 pour piocher:
0
Process returned -1073741819 (0xC0000005) execution time : 7.086 s
Press any key to continue.
Sauriez vous quelle est l'erreur? Sans vouloir pomper votre temps :)
Merci
Voici le nouveau code:
int main() { int nombreAuSort1, entree,i,j; char tampon[10]; char pioche1[16][10] = {"carte 1","carte 2","carte 3","carte 4","carte 5","carte 6","carte 7","carte 8", "carte 9","carte 10","carte 11","carte 12","carte 13","carte 14","carte 15","carte 16" }; srand(time(NULL)); while(pioche1[6]!='\0') { for(i=0; i<16; i++) { printf("%s\n",pioche1[i]); } printf("Entrez 0 pour piocher:\n"); scanf("%d",&entree); while(entree!=0) { getchar(); printf("Entrez 0 pour piocher(vous n'avez pas selectionne 0):\n"); scanf("%d",&entree); } if(entree==0) { for(i=15; i>=0; i--) { j=rand()%(i); strcpy(tampon[0],pioche1[i]); strcpy(pioche1[i],pioche1[j]); strcpy(pioche1[j],tampon[0]); } printf("Votre carte est :%s", pioche1[0]); for(i=0; i<16; i++) { printf("%s\n",pioche1[i]); printf("%s\n",pioche1[i]); } } } }
Et voici ce qui ce passe quand j'essaye d'afficher la pioche mélangée:
carte 1
carte 2
carte 3
carte 4
carte 5
carte 6
carte 7
carte 8
carte 9
carte 10
carte 11
carte 12
carte 13
carte 14
carte 15
carte 16
Entrez 0 pour piocher:
0
Process returned -1073741819 (0xC0000005) execution time : 7.086 s
Press any key to continue.
Sauriez vous quelle est l'erreur? Sans vouloir pomper votre temps :)
Merci
- tu dois mélanger ton tableau de chaînes avant de faire tes "tirages"
- un "tirage" est ensuite le passage d'un indice à un autre du tableau, tu n'utilises plus rand()
- la partie du code en lignes 26 à 32 qui semble faire le mélange ne suit pas exactement l'algorithme :
Pour mélanger un tableau a de n éléments (indicés de 0 à n-1), l'algorithme est le suivant.
Pour i allant de n − 1 à 1 faire :
j ← entier aléatoire entre 0 et i
échanger a[j] et a[i]
https://fr.wikipedia.org/wiki/M%C3%A9lange_de_Fisher-Yates
Je vais voir si je peux te faire un exemple simplifié.
Voilà un exemple fonctionnel :
Dal
Edit : correction de la boucle for pour traiter la dernière permutation
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> int main(void) { char tampon[10]; char pioche[16][10] = { "carte 1","carte 2","carte 3","carte 4", "carte 5","carte 6","carte 7","carte 8", "carte 9","carte 10","carte 11","carte 12", "carte 13","carte 14","carte 15","carte 16" }; srand(time(NULL)); /* mélange de Fisher-Yates de la pioche * cf. https://fr.wikipedia.org/wiki/M%C3%A9lange_de_Fisher-Yates */ for (int i = 15; i > 0; i--) { int j = rand() % i; strcpy(tampon, pioche[i]); strcpy(pioche[i], pioche[j]); strcpy(pioche[j], tampon); } /* tirage de cartes */ int carte_courante = 0; while (1) { printf("Tapez n'importe qu'elle touche pour piocher " "(ou 'q' pour quitter)\n"); int ch = getchar(); if (ch == 'q') break; printf("Tirage n°%d - vous avez pioché : %s\n", carte_courante + 1, pioche[carte_courante]); carte_courante++; if (carte_courante > 15) { printf("Vous avez tiré toutes les cartes du paquet\n"); break; } } return 0; }
Dal
Edit : correction de la boucle for pour traiter la dernière permutation
Si tu tapes juste Entrée, tu ne devrais pas voir cela.
C'est effectivement "normal", car si tu tapes un caractère (autre que 'q' qui fait sortir de la boucle) et Entrée, tu as en fait tapé 2 char qui sont consommés successivement par 2 appels à getchar() ... et si tu tapes "toto, titi et tata + Entrée" parce que tu es un rebelle tu auras tapé 19 char et cela fera autant de tirages.
Tu pourrais modifier le code pour purger stdin avant de boucler pour éviter ce genre de choses.
Tu peux modifier cet exemple comme tu veux, mais c'est un peu bizarre de demander à quelqu'un de taper 0 pour faire quelque chose.
C'est juste un exemple rapide. La gestion de la saisie ou intéraction avec l'utilisateur au clavier en C n'est pas quelque chose de trivial si tu veux faire quelque chose de robuste.
C'est effectivement "normal", car si tu tapes un caractère (autre que 'q' qui fait sortir de la boucle) et Entrée, tu as en fait tapé 2 char qui sont consommés successivement par 2 appels à getchar() ... et si tu tapes "toto, titi et tata + Entrée" parce que tu es un rebelle tu auras tapé 19 char et cela fera autant de tirages.
Tu pourrais modifier le code pour purger stdin avant de boucler pour éviter ce genre de choses.
Tu peux modifier cet exemple comme tu veux, mais c'est un peu bizarre de demander à quelqu'un de taper 0 pour faire quelque chose.
C'est juste un exemple rapide. La gestion de la saisie ou intéraction avec l'utilisateur au clavier en C n'est pas quelque chose de trivial si tu veux faire quelque chose de robuste.
Merci beaucoup.
J'ai enfin compris et je vais juste essayer de faire en sorte que la carte tirée se place à la "fin du paquet".
Enfaite je fais un UNO dans lequel il y a un tirage de carte donc j'ai choisi temporairement la touche 0 pour tirer mais je la changerais plus tard.
Et durant le jeu avec une certaine condition il pourra tirer dans la pioche et donc je devrais afficher quelque chose qui lui permettra de tirer. Je trouvais cela plus facile.
J'ai enfin compris et je vais juste essayer de faire en sorte que la carte tirée se place à la "fin du paquet".
Enfaite je fais un UNO dans lequel il y a un tirage de carte donc j'ai choisi temporairement la touche 0 pour tirer mais je la changerais plus tard.
Et durant le jeu avec une certaine condition il pourra tirer dans la pioche et donc je devrais afficher quelque chose qui lui permettra de tirer. Je trouvais cela plus facile.
Voici mon code:
Je l'ai un peu modifié depuis hier et comme ca il affiche plus de double. Cependant étant donné que avec la fonction memmove je "décale" les nombres dans le tableau ce dernier affiche donc des cases vides et mon programmes tire du vide a partir de quelques tirages.
Et le fait que la carte ne se mettent pas au début du tableau n'est pas réellement intentionnel je lui ai juste affecté la même place dans le tableau 2. Mais l'ordre importe peu étant donné que c'est une pioche.
1) en ligne 22, tu continues à piocher parmi les 16 premières cartes, au lieu de tenir compte du nombre de cartes restantes.
2) en ligne 28, tu décales beaucoup trop de cartes.