4 réponses
silversloche
Messages postés
39
Date d'inscription
dimanche 28 juin 2015
Statut
Membre
Dernière intervention
20 mars 2016
2
20 mars 2016 à 04:12
20 mars 2016 à 04:12
non, ton codage est (pour la premiere fois), parfait !
--
--
silversloche
Messages postés
39
Date d'inscription
dimanche 28 juin 2015
Statut
Membre
Dernière intervention
20 mars 2016
2
20 mars 2016 à 12:37
20 mars 2016 à 12:37
non cest comme sa que demineur marche
--
--
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 842
20 mars 2016 à 13:35
20 mars 2016 à 13:35
Bonjour,
Voici mes remarques sur le code (non exhaustif) :
Il manque les commentaires (à ne pas négliger, ça fait partie du code).
Eviter les variables globales. Dans ton cas, il suffit de les faire passer en argument.
void jouer(), int verifier(), ...
Le bon prototype d'une fonction sans argument est : type nomFonction(void). Sinon, la fonction n'est pas correctement définie.
int afficher()
Il manque un return dans ta fonction.
Dans ton code, tu parles des nombres -36, 88, etc. Ce n'est pas parlant. Je te conseille d'utiliser enum pour gagner en lisibilité. Ou à défaut, d'utiliser une constante.
system("cls");
Non portable. D'une manière générale, sauf si cela est pour faire un programme très simple (mais pourquoi utiliser le C dans cas...), on évite system(). Comme il n'existe pas de manière portable, le mieux est de déporter cette fonction dans un module spécifique. Sur Windows, il faut plutôt faire appel aux API pour effacer l'écran.
#include<conio.h>
Non portable...
coordonnees pointsDevoiles[100]={0,0};
Ce n'est pas bon ça. Normalement, ça fait un warning. Il faut définir chacune des lignes. Ou alors, faire une boucle for.
Concernant, les scanf(). Attention, cela n'est pas sécurisé. Imagine ce qu'il se passe si l'utilisateur tape autre chose que ce qui est attendu. Il faut donc contrôler le retour.
srand(time(NULL));
A n'appeler qu'une seule fois dans tout ton programme. Sinon, tu perds en aléa. Dans ton cas, à chaque fois que tu rejoues, tu rappelles ce code.
Cdlt,
Voici mes remarques sur le code (non exhaustif) :
Il manque les commentaires (à ne pas négliger, ça fait partie du code).
Eviter les variables globales. Dans ton cas, il suffit de les faire passer en argument.
void jouer(), int verifier(), ...
Le bon prototype d'une fonction sans argument est : type nomFonction(void). Sinon, la fonction n'est pas correctement définie.
int afficher()
Il manque un return dans ta fonction.
Dans ton code, tu parles des nombres -36, 88, etc. Ce n'est pas parlant. Je te conseille d'utiliser enum pour gagner en lisibilité. Ou à défaut, d'utiliser une constante.
system("cls");
Non portable. D'une manière générale, sauf si cela est pour faire un programme très simple (mais pourquoi utiliser le C dans cas...), on évite system(). Comme il n'existe pas de manière portable, le mieux est de déporter cette fonction dans un module spécifique. Sur Windows, il faut plutôt faire appel aux API pour effacer l'écran.
#include<conio.h>
Non portable...
coordonnees pointsDevoiles[100]={0,0};
Ce n'est pas bon ça. Normalement, ça fait un warning. Il faut définir chacune des lignes. Ou alors, faire une boucle for.
Concernant, les scanf(). Attention, cela n'est pas sécurisé. Imagine ce qu'il se passe si l'utilisateur tape autre chose que ce qui est attendu. Il faut donc contrôler le retour.
srand(time(NULL));
A n'appeler qu'une seule fois dans tout ton programme. Sinon, tu perds en aléa. Dans ton cas, à chaque fois que tu rejoues, tu rappelles ce code.
Cdlt,
Ok merci, mais, je ne suis qu'un debutant .....
1 - Par quoi je pourrais remplacer scanf ?
2 - Et aussi, comment pourrais-je utiliser l'API pour effacer l'écran ?
J'ai mis volontairement des variables globales parce que la plupart des fonctions on en besoin, j'ai commencer, au tout début, par les faire passer en argument, mais c'était trop long et ça devenait trop compliqué
En quoi les variables globales poseraient-elles problème ?
1 - Par quoi je pourrais remplacer scanf ?
2 - Et aussi, comment pourrais-je utiliser l'API pour effacer l'écran ?
J'ai mis volontairement des variables globales parce que la plupart des fonctions on en besoin, j'ai commencer, au tout début, par les faire passer en argument, mais c'était trop long et ça devenait trop compliqué
En quoi les variables globales poseraient-elles problème ?
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 842
20 mars 2016 à 18:16
20 mars 2016 à 18:16
Ton code est très bien si tu débutes.
Maintenant, mes remarques visent à améliorer ton code et ton niveau ;-).
Pour scanf(), le plus simple est d'utiliser fgets() pour lire une chaîne de caractère et de convertir en nombre avec strtol().
Pour effacer l'écran : https://c.developpez.com/faq/?page=Gestion-du-clavier-et-de-l-ecran-en-mode-console#Comment-effacer-l-ecran
Pour les variables globales, c'est déconseillé pour plusieurs raisons :
1/ on ne sait pas qui accède à cette variable : pas bon si tu souhaites sécuriser ton programme, mauvaise lisibilité
2/cela peut poser problème par la suite si tu souhaites utiliser des thread, faire de la récursivité, etc.
Bref, c'est un mauvais réflexe.
Maintenant, mes remarques visent à améliorer ton code et ton niveau ;-).
Pour scanf(), le plus simple est d'utiliser fgets() pour lire une chaîne de caractère et de convertir en nombre avec strtol().
Pour effacer l'écran : https://c.developpez.com/faq/?page=Gestion-du-clavier-et-de-l-ecran-en-mode-console#Comment-effacer-l-ecran
Pour les variables globales, c'est déconseillé pour plusieurs raisons :
1/ on ne sait pas qui accède à cette variable : pas bon si tu souhaites sécuriser ton programme, mauvaise lisibilité
2/cela peut poser problème par la suite si tu souhaites utiliser des thread, faire de la récursivité, etc.
Bref, c'est un mauvais réflexe.
Salut
Je l'ai essayé, mais ça marche pas, il me signale que les types ne sont pas reconnus
Et comment utilisetons strtol() ? je n'ai pas trouvé beaucoup de documentation sur elle.
#include <windows.h>
void windows_clear_screen(void)
{
HANDLE hConsole;
CONSOLE_CONS_BUFFER_INFO Info;
DWORD NbOctetsEcrits; /* Requis par FillConsoleOutputCharacter */
COORD Debut = {0, 0};
/* STD_OUTPUT_HANDLE fait référence a la sortie standard du programme qui est par défaut la console */
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
/* Lit les infos sur le buffer de l'écran */
GetConsoleScreenBufferInfo(hConsole, &Info);
/* Remplit l'écran avec le caractère espace */
FillConsoleOutputCharacter(hConsole, ' ', Info.dwSize.X*Info.dwSize.Y, Debut, &NbOctetsEcrits);
/* Remet le curseur au début de l'écran */
SetConsoleCursorPosition(hConsole, Debut);
}
Je l'ai essayé, mais ça marche pas, il me signale que les types ne sont pas reconnus
Et comment utilisetons strtol() ? je n'ai pas trouvé beaucoup de documentation sur elle.
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 842
20 mars 2016 à 23:56
20 mars 2016 à 23:56
Bizarre, il y a une erreur sur leur site.
Remplace CONSOLE_... par CONSOLE_SCREEN_BUFFER_INFO
Ca devrait être mieux.
Pour strtol(), il y a un exemple sur le man : http://manpagesfr.free.fr/man/man3/strtol.3.html
Remplace CONSOLE_... par CONSOLE_SCREEN_BUFFER_INFO
Ca devrait être mieux.
Pour strtol(), il y a un exemple sur le man : http://manpagesfr.free.fr/man/man3/strtol.3.html
Re-salut
Pour ce qui est de strtol(), c'est bon j'ai réglé le problème, voilà le code final, merci à tous :
Pour ce qui est ds variables globales, je peux pas m'en passer, parce que c'est compliqué de faire tout passer en arguments, et la fonction jouer s’appelle elle même, ça pose problème dans ce cas ....
Ya pas un moyen pour limiter l'acces au variables ?
Pour ce qui est de strtol(), c'est bon j'ai réglé le problème, voilà le code final, merci à tous :
#include<stdio.h> #include<stdlib.h> #include<string.h> #include <windows.h> #include<time.h> #define XMAX 20 #define YMAX 20 typedef enum { CASE=-36,VIDE=0,ZERO=48,MINE=88,ACTIF=1,INACTIF=0 }etat; int nombreDeMines=10, longueur=10, largeur=10, mines[XMAX][YMAX]; char grille[XMAX][YMAX], affichage[XMAX][YMAX]; typedef struct { int x; int y; }coordonnees; void windowsClearScreen(void) { HANDLE hConsole; CONSOLE_SCREEN_BUFFER_INFO Info; DWORD NbOctetsEcrits; COORD Debut = {0, 0}; hConsole = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo(hConsole, &Info); FillConsoleOutputCharacter(hConsole, ' ', Info.dwSize.X*Info.dwSize.Y, Debut, &NbOctetsEcrits); SetConsoleCursorPosition(hConsole, Debut); } void cleanStdin(void) { int c; do { c = getchar(); } while (c != '\n' && c != EOF); } int lireNombre(void) { int n; char entree[256], *p; fgets(entree, sizeof(entree), stdin); if((p=strchr(entree,'\n'))!=NULL) *p ='\0'; else cleanStdin(); n=strtol(entree, &p, 10); if(*p=='\0') return n; } int comparer(int val, int tab[], int max) { int i, cpt=0; for(i=0;i<max;i++) { if(tab[i]==val) cpt++; } return cpt; } void initialiserMines(void) { int i, temp; for(i=0;i<XMAX*YMAX;i++) { affichage[i/YMAX][i%YMAX]=CASE; grille[i/YMAX][i%YMAX]=ZERO; mines[i/YMAX][i%YMAX]=INACTIF; } for(i=0;i<nombreDeMines;i++) { do { temp=rand()%(longueur*largeur); } while(mines[temp/largeur][temp%largeur]==ACTIF); mines[temp/largeur][temp%largeur]=ACTIF; } } void initialiserGrille(void) { int i, k; for(i=0;i<longueur*largeur;i++) { if(mines[i/largeur][i%largeur]==INACTIF) { for(k=0;k<9;k++) if( ( ((i/largeur)-1+(k/3)>=0) && ((i/largeur)-1+(k/3)<longueur) ) && ( ((i%largeur)-1+(k%3)>=0) && ((i%largeur)-1+(k%3)<largeur) ) ) grille[i/largeur][i%largeur]+=mines[(i/largeur)-1+(k/3)][(i%largeur)-1+(k%3)]; } else { grille[i/largeur][i%largeur]=MINE; } } } void afficher(void) { int i, j, k, cpt; printf("\n \t"); for(j=0;j<largeur;j++) printf("%3d", j); j=0; printf("\n\n\n\n"); for(i=0;i<longueur*largeur;i++) { if(i%largeur==0) { printf(" %2d\t", j); j++; } cpt=0; for(k=0;k<9;k++) if( ( ((i/largeur)-1+(k/3)>=0) && ((i/largeur)-1+(k/3)<longueur) ) && ( ((i%largeur)-1+(k%3)>=0) && ((i%largeur)-1+(k%3)<largeur) ) ) if(grille[(i/largeur)-1+(k/3)][(i%largeur)-1+(k%3)]==0) cpt++; if(grille[i/largeur][i%largeur]>47) { if(cpt!=0 && grille[i/largeur][i%largeur]!=ZERO) { affichage[i/largeur][i%largeur]=grille[i/largeur][i%largeur]; printf("%3c", affichage[i/largeur][i%largeur]); } else { printf("%3c", affichage[i/largeur][i%largeur]); } } else { affichage[i/largeur][i%largeur]=VIDE; printf("%3c", affichage[i/largeur][i%largeur]); } if(i%largeur==largeur-1) { printf("\n\n"); } } } void afficherMines(void) { int i, j; printf("\n \t"); for(j=0;j<largeur;j++) printf("%3d", j); j=0; printf("\n\n\n\n"); for(i=0;i<longueur*largeur;i++) { if(i%largeur==0) { printf(" %2d\t", j); j++; } if(affichage[i/largeur][i%largeur]==CASE) { if(grille[i/largeur][i%largeur]==MINE) printf("%3c", MINE); else printf("%3c", CASE); } else { if(affichage[i/largeur][i%largeur]>ZERO) printf("%3c", affichage[i/largeur][i%largeur]); else printf("%3c", VIDE); } if(i%largeur==largeur-1) { printf("\n\n"); } } } void devoiler(coordonnees point) { int i, temp, j=0, c=0, verif[XMAX*YMAX]={0}; coordonnees pointsDevoiles[XMAX*YMAX]; for(i=0;i<XMAX*YMAX;i++) { pointsDevoiles[XMAX*YMAX].x=0; pointsDevoiles[XMAX*YMAX].y=0; } for(i=0;i<XMAX*YMAX;i++) verif[i]=-1; if(grille[point.x][point.y]==ZERO) { do { if(j==0) { grille[point.x][point.y]=0; pointsDevoiles[j].x=point.x; pointsDevoiles[j].y=point.y; j++; } else { temp=rand()%j; point.x=pointsDevoiles[temp].x; point.y=pointsDevoiles[temp].y; } for(i=1;i<9;i+=2) if( ( ((point.x)-1+(i/3)>=0) && ((point.x)-1+(i/3)<longueur) ) && ( ((point.y)-1+(i%3)>=0) && ((point.y)-1+(i%3)<largeur) ) ) { if(grille[(point.x)-1+(i/3)][(point.y)-1+(i%3)]==ZERO) { grille[(point.x)-1+(i/3)][(point.y)-1+(i%3)]=VIDE; pointsDevoiles[j].x=(point.x)-1+(i/3); pointsDevoiles[j].y=(point.y)-1+(i%3); j++; } if(comparer((point.x*largeur+point.y),verif,c)==0) { verif[c]=point.x*largeur+point.y; c++; } } } while(c<j); } else { affichage[point.x][point.y]=grille[point.x][point.y]; } } int verifier(void) { int i, cpt=0; for(i=0;i<longueur*largeur;i++) { if(affichage[i/largeur][i%largeur]==CASE) cpt++; else if(affichage[i/largeur][i%largeur]==MINE) return 0; } return cpt; } void jouer(void) { int temp, inter, continuer=1; coordonnees point; do { printf(" ****************************************\n"); printf(" ________________DEMINEUR________________\n"); printf(" ****************************************\n\n"); printf(" 1 - Jouer\n 2 - Personnaliser\n 3 - Quitter\n\n Votre choix : "); temp=lireNombre(); while(temp>3||temp<1) { printf("\n Recommencez : "); temp=lireNombre(); } if(temp==2) { do { printf("\n\n Longueur ( >=5 et <=20, actuel : %d ) : ", longueur); inter=lireNombre(); } while(inter<5||inter>XMAX); longueur=inter; do { printf("\n\n Largeur ( >=5 et <=20, actuel : %d ) : ", largeur); inter=lireNombre(); } while(inter<5||inter>YMAX); largeur=inter; do { printf("\n\n Nombres de mines ( >=2 et <=%d , actuel : %d ) : ", longueur*largeur/2, nombreDeMines); inter=lireNombre(); } while(inter<2||inter>longueur*largeur/2); nombreDeMines=inter; } windowsClearScreen(); } while(temp==2); if(temp==1) { initialiserMines(); initialiserGrille(); afficher(); do { printf("\n\n\n\n\n Case : \n\n X : "); point.x=lireNombre(); while(point.x>=longueur) { printf(" Recommencez ( X<%d ) : ", longueur); point.x=lireNombre(); } printf(" Y : "); point.y=lireNombre(); while(point.y>=largeur) { printf(" Recommencez ( Y<%d ) : ", largeur); point.y=lireNombre(); } windowsClearScreen(); devoiler(point); afficher(); if(verifier()==nombreDeMines) { do { windowsClearScreen(); afficherMines(); printf("\n\n Vous avez gagne\n Rejouer ? (Oui : 1 / Non : 0) : "); temp=lireNombre(); } while(temp>1||temp<0); if(temp==1) { continuer=0; windowsClearScreen(); jouer(); } else { continuer=0; } } else { if(verifier()==0) { do { windowsClearScreen(); afficherMines(); printf("\n\n Vous avez perdu\n Rejouer ? (Oui : 1 / Non : 0) : "); temp=lireNombre(); } while(temp>1||temp<0); if(temp==1) { continuer=0; windowsClearScreen(); jouer(); } else { continuer=0; } } else { continuer=1; } } } while(continuer); } } int main(void) { srand(time(NULL)); jouer(); return 0; }
Pour ce qui est ds variables globales, je peux pas m'en passer, parce que c'est compliqué de faire tout passer en arguments, et la fonction jouer s’appelle elle même, ça pose problème dans ce cas ....
Ya pas un moyen pour limiter l'acces au variables ?
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
1 092
Modifié par [Dal] le 22/03/2016 à 16:25
Modifié par [Dal] le 22/03/2016 à 16:25
Une manière de limiter la portée de tes variables est de les utiliser comme variables globales statiques.
Cela est possible si tu construis ton code de façon modulaire, en divisant le programme en couples de .c et .h et en précédant la déclaration de ces variables globales du spécificateur "static". Dans le cas de variables déclarées de dehors d'une fonction, la portée de ces variables sera alors limitée aux fonctions relevant de cette même unité de compilation.
Dal
Cela est possible si tu construis ton code de façon modulaire, en divisant le programme en couples de .c et .h et en précédant la déclaration de ces variables globales du spécificateur "static". Dans le cas de variables déclarées de dehors d'une fonction, la portée de ces variables sera alors limitée aux fonctions relevant de cette même unité de compilation.
Dal
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 842
22 mars 2016 à 22:13
22 mars 2016 à 22:13
Pour ce qui est ds variables globales, je peux pas m'en passer, parce que c'est compliqué de faire tout passer en arguments, et la fonction jouer s’appelle elle même, ça pose problème dans ce cas ....
C'est peut-être un peu fastidieux, et encore pas tant que ça, mais c'est pourtant une bonne habitude à prendre. Au pire, s'il y a vraiment trop de variable, il y a certainement de l'élagage à faire (structure, ...).
Pour la fonction jouer qui s'appelle elle-même, ce n'est pas un problème. Ca fonctionne très bien ainsi/
Maintenant, c'est toi qui codes ;-). Sinon, tu as static comme précisé par [Dal]
C'est peut-être un peu fastidieux, et encore pas tant que ça, mais c'est pourtant une bonne habitude à prendre. Au pire, s'il y a vraiment trop de variable, il y a certainement de l'élagage à faire (structure, ...).
Pour la fonction jouer qui s'appelle elle-même, ce n'est pas un problème. Ca fonctionne très bien ainsi/
Maintenant, c'est toi qui codes ;-). Sinon, tu as static comme précisé par [Dal]
Modifié par LittDev le 20/03/2016 à 11:58
OK merci
J'ai surtout galérer avec algo qui dévoile les cases, la ou des fois il faut dévoiler tous les zéros contigus ainsi que leur pourtour
Alors pour devoiler le groupe de cases, il commence par dévoiler la case sélectionné par l'utilisateur, puis il vois si il n'y a pas de zéros au 4 coins de la case, si oui, il va les devoiler, et les prendre en considération, et puis il va choisir au hasard une case parmi les cases qu'il a dévoilé, il vérifie s'y il n'y a pas de zéros autour, si oui, il continue de la même manière, il re-selectionne une case au hasard parmi celles qu'il a activées et ...........
Il n'y aurait pas un algo plus simple que ça ?