Aller au contenu

[RESOLU]Mon Premier Programme (ameliorer)


Messages recommandés

Bonsoir a tous,

ayant suivi les tutos du "site du zero" autant que faire ce peut, j'en suis arrivé au TP N°1 CREATION D'UN JEU NOMBRE MYSTERE. auquel, comme recommandé, j'ai essayer d'apporter quelque amelioration.

L'objectif de ce Topic est de recueillir vos commentaire et suggestion concernant sa programmation.

l'objectif que je me suis fixé lors de l'ecriture du code source est double :

1/ ecrire un code le plus simple possible (en terme de nombre de ligne par exemple et a fonctionnalité equivalente)

2/ qu'il soit le plus sécurisé possible (avec les connaissance dont je dispose bien entendu....)

à ce propos, bien que la fonction "scanf_s" soit (censée) etre plus sécurisée que la fonction "scanf" puisqu'elle permet d'ignorer le "surplus" d'une variable auquel ont aurais donné une trop grande longueur par rapport a sont type, elle n'empeche pas de faire bugger le programme en tapant un "quote" (") au lieu d'un nombre (ou autre)....

voila tout est dit toutes vos remarques et suggestion seront les bienvenues.

voici le code source :

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

int main(int argc, char *argv[])

{

//definition des variables et constante

int MAX=0;

const int MIN=1;

long nombreMystere=0, nombre1=0;

long compteur=0;

long nouvellepartie=0;

long nombre_joueur=0;

long niveau=0;

unsigned int t = (unsigned int) time(NULL);

//Option 1 choix du nombre de joueurs

printf("\nVoulez-vous jouer seul ou a deux ?");

printf("\n\t-Pour jouer seul tapez 1\n\t-Pour jouer a plusieur tapez 2");

printf("\nVotre Choix :\t");

scanf_s("%ld",&nombre_joueur,3);

//instruction 1: si nombre de joueur <1 tirage du nombre mystere par

//randomization (fonction "srand(t)") compris entre 1 et X (fonction du niveau de difficulté)

//un compteur comptant le nombre de "coups" effectuer par le joueur

if (nombre_joueur<=1)

{

//Option 2 choix du niveau de difficultée

printf("\nChoisissez parmis nos 3 niveau de difficulte\n\t-Pour un interval compris entre 1 et 10 tapez 1\n\t-Pour un interval compris entre 1 et 100 tapez 2\n\t-Pour un interval compris entre 1 et 1000 tapez 3");

printf("\nVotre Choix :\t");

scanf_s("%ld",&niveau,4);

//attribution de la valeur correspondant au niveau de difficulté choisie à la variable MAX

if(niveau<=1)

{

MAX=10;

}

else if (niveau==2)

{

MAX=100;

}

else if (niveau>=3)

{

MAX=1000;

}

else;

srand(t);

do

{

compteur=0;

nombreMystere = (rand() % (MAX - MIN + 1)) + MIN;

do

{

printf("\ntapez le nombre mystere\t");

scanf_s("%ld",&nombre1,1000);

compteur++;

if(nombre1<nombreMystere)

{

printf("vous este en dessous");

}

else if(nombre1>nombreMystere)

{

printf("vous este au dessus");

}

else

{

printf("\nvous avez reussi votre partie en : %ld coups\n",compteur);

printf("\nvous avez gagner le droit de rejouer\n");

printf("\nPour rejouer tapez :\t 1\nPour quittez tapez :\t 0\n");

printf("\nVotre choix :\t");

//ici le joueur tape s'il veut rejoueur oui (1) ou non (0)

scanf_s("%ld",&nouvellepartie,2);

}

}

//l'instruction se repete tant que je joueur n'a pas trouver

while(nombre1!=nombreMystere);

}

while(nouvellepartie>0);

}

// ici si le nombre de joueur est egale a 2 alors :

else if (nombre_joueur==2)

do

{

printf("\nVous avez donc choisi de jouer a plusieur");

printf("\nJoueur Num 1, veuillez tapez le nombre mystere s'il vous plait :\t");

// le nombre mystere est fournis par le joueur N°1

scanf_s("%ld",&nombreMystere,1000);

compteur=0;

do

{

printf("\ntapez le nombre mystere\t");

scanf_s("%ld",&nombre1);

//je n'ai pas attribué de longueur maximum a ce scanf_s car si je lui attribue

//par exemple une valeur maximum de 1000et que le joueur 1 a attribué une valeur

//(par exemple) de 10.000 l'instruction renvoie constament qu'on est au dessus

//de la valeur (meme si ont est en dessous) et ce jusqu'a ce qu'on la trouve ....:zarb:

compteur++;

if(nombre1<nombreMystere)

{

printf("vous este en dessous");

}

else if(nombre1>nombreMystere)

{

printf("vous este au dessus");

}

else

{

printf("\nvous avez reussi votre partie en : %ld coups\n",compteur);

printf("\nvous avez gagner le droit de rejouer\n");

printf("\nPour rejouer tapez :\t 1\nPour quittez tapez :\t 0\n");

printf("\nVotre choix :\t");

scanf_s("%ld",&nouvellepartie,2);

}

}

while(nombre1!=nombreMystere);

}

while(nouvellepartie>0);

system ("pause");

return 0;

}

voila tout le code.

encore merci a tous ceux qui prendront le temps de le lire et de m'apporter aide et suggestions.

:chinois:

PS : dommage que les tabulation n'apparaissent pas sa aurait peut etre été plus simple a lire

Lien vers le commentaire
Partager sur d’autres sites

Alors, remarques d'ordre général : c'est bien. C'est propre et bien commenté, facile à lire et je t'aurais mis une note correcte. :chinois:

pour avoir une bonne note (façon de parler, hein :-D ), j'aurais aimé que tu utilises des fonctions, plutôt que de tout mettre au kilomètre dans le main. Par exemple les ihm (interface homme machines) en texte qui ne demande qu'un entier peuvent facilement se mettre dans des fonctions (par exemple un fonction choixJoueurs qui affiche les trois premiers printf, fait le scanf et renvoie la valeur).

Aussi, tu fais deux fois la même boucle (une fois à un joueur, et une fois à deux joueur), alors que ce qui change, c'est juste l'initialisation de la valeur mystère. Tu ne crois pas que tu pourrais faire une seule boucle et faire le test qui détermine la manière dont est initialisée la valeur mystère àl'intérieur de celle-ci ?

Autre chose - et je sais que c'est strictement équivalent - pourquoi tu as mis le "voulez vous rejouer ?" à l'intérieur de la boucle de découverte ? Tu ne trouve pas ça plus lisible et logique de le mettre à l'extérieur de cette boucle (mais à l'intérieur de la boucle du rejouer, évidemment) ?

exemple :

do
{
 do
 {
//découverte
 } while(pas_decouvert);
//test voulez vous rejouer ?
} while(veut_rejouer);

Pour poster du code, il y a la balise

 qui permet de garder les espace 
Lien vers le commentaire
Partager sur d’autres sites

+1 pour les balises de code

+1 pour la division du code en fonctions (un main, c'est pas un programme), ton code serait plus propre

et +1 pour la valeur de retour sur scanf

d'ailleurs, ça s'applique à tous tes appels systèmes / libs, contrôler la valeur de retour n'est pas un luxe. Ca t'aidera au debug.

autre remarque: une boucle / instruction conditionnelle ne comportant qu'une instruction ne nécessite pas d'accolades.

avant le do while, tu init ton compteur à 0, et dedans tu l'incrémente. un for() ne serait pas de trop.

les messages (printf) pourraient être définis (#define), parceque 5 appels consécutifs à printf (même s'il bufferise), c'est pas super sexy.

enfin, si scanf te pose problème, utilise read (là, si ça marche pas, tu pourra t'en prendre qu'à toi-même). Tu rajoutes stdio pour lire un caractère !! Pas tip top niveau optimisation :D

bonne continuation :transpi:

Lien vers le commentaire
Partager sur d’autres sites

à ce propos, bien que la fonction "scanf_s" soit (censée) etre plus sécurisée que la fonction "scanf" puisqu'elle permet d'ignorer le "surplus" d'une variable auquel ont aurais donné une trop grande longueur par rapport a sont type, elle n'empeche pas de faire bugger le programme en tapant un "quote" (") au lieu d'un nombre (ou autre)....
Ça, ça ne dépend pas de ta méthode d'acquisition, mais de ton shell
Lien vers le commentaire
Partager sur d’autres sites

bonjour a tous.

tous d'abord je voulais vous remercier de m'avoir fait par de vos commentaire qui sont très instructifs.

ensuite je m'excuse de ne pas avoir repondu plus tot mais j'avoue qu'en ce moment je potasse encore pour tenter de les appliquer (en fait au moment ou j'ai envoyer le code je ne connaissait que la fonction "main").

mais depuis je me suis rattrapper (sa prend 1 seul ou 2 p ???) et je me suis ingurgité d'un coup les directive de préprocesseur, les headers, les fonctions (void et typée), les pointeurs, les tableaux et donc par conscéquence la chaine de caracteres...

et j'avoue que j'en fait encore des cauchemar la nuit (sans rire... quand je dors je reve de programme qui plante).

et c'est vraie que c'est le cas, sa plante...

en fait pour tout vous expliqué, je me suis creer un projet test dans lequel je fourre toutes les lignes de code que j'apprend et je les bidouille pour voir ce que sa donne

sauf que arriver aux chaine de carractere j'ai un truc du genre:

/*...declaration de mes variables...*/
char prenom[100];
printf("\ncomment tu t'appelle ?\n");
scanf_s("%s",&prenom);
printf("\nbonjour %s",prenom);

/* des tas d'autres printf, des fonctions (void surtout) et des for...*/

jusqu la j'ai fait comme dans le tuto.

sauf que quand je lance mon debug tout va bien jusqu'au scanf "&prenom" (en fait c normal jusque la puisque je cale chaque nouvelle instruction en debut du main avant de la decalée eventuellement plus loin)

et une fois que j'ai entrer ma chaine de caractere ...

***BAM***

tout mon programme defile d'un coup et va jusqu'au system("pause"); en fain de main en passant par toutess les fonction et en ignorant les scanf... et tout le reste comme si il se mettait à petter les plomb... :transpi:

donc la je coince.

sinon concernant vos explication j'ai a peut pret compris tout vos conseil sauf :

@ theocrite

la partie concernant le shell (je sais malheureusement a peine ce que c'est pour l'instant ) mais donc si j'ai bien compris ce dont il sagit c'est l'interpreteur de commande (en l'occurrence puisque je suis en mode console) et donc sa programmation interne qui fait que sa plante quant je renvoie un "quote" dans une variable

@mephisto

ok pour les accolade (meme si j'en met partout pour l'instant pour prendre l'habitude)

ok pour le for (logique)

par contre je comprend pas le "#define" et le probleme avec les 5 printf de suite... ou est le rapport avec le buffer ?

pas tip top toi meme :incline::incline:

@lorinc

ok pour tous et merci pour tes explication

voulez vous rejouer -> déplacer ok

utilisation des fonction et traitement en une seul boucle avec condition (+/-random)concernant le nombre de joueur -> en cours :p

à par contre j'ai pas compris le rapport avec les IHM

et puis sinon d'un point de vue plus générale, en mode 2 joueur, le probleme c'est que le joueur 2 vois le chiffre qu'à taper le joueur 1 donc pour deviner c'est pas terrible,

j'ai trouver un bricolage qui consiste a faire

printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");

mais franchement c'est pas terrible ... :transpi: .

bon

bonne nuit à tous je vais au dodot

:devil:

Lien vers le commentaire
Partager sur d’autres sites

PS :

j'ai fini par trouver la solution a mon probleme de tabelau de chaine :

/*...declaration de mes variables...*/
char prenom[100];
printf("\ncomment tu t'appelle ?\n");
scanf_s("%s",&prenom,99);   // il faut que je laisse 1 bit pour le /0
printf("\nbonjour %s",prenom);

/* des tas d'autres printf, des fonctions (void surtout) et des for...*/

jusque la sa parrait cohérent d'un point de vue de la syntaxe (si je m'exprime correctement) par contre ce que je ne comprend toujours pas c'est pourquoi mon programme pete les plombs comme sa...

Lien vers le commentaire
Partager sur d’autres sites

bonsoir a tous

alors voila j'ai commencer a retravailler mon petit code de jeu de nombre avec les conseille qui mon été founis et je vous donne donc le nouveau code sans plus tarder :

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

long random();
long jeux_a_plusieur();
void comparaison ();
void jouer();
char personne();
int score();

int main(int argc, char *argv[])
{
long replay=0;
//compteurs...
long i=0, j=0;
//la personne donne son nom
personne();
do
{
	//appel de la fonction jouer
	jouer();
	i=i+score();
	//possibilité de rejouer ou non (replay)
	printf("\npour rejouer :\ttapez 1");
	printf("\npour quittez :\ttapez 0");
	printf("\ntapez votre choix :\t");
	scanf_s("%d",&replay,2);
	j++;
	printf("\nVous avez fait %d parties\n",j);
}
while (replay!=0);

puts("SCORE");
printf("votre score est de : %d",i/j);
system ("pause");
return 0;
}

void jouer()
{
long nombre_joueur=0;
long nombre_mystere=0;
long niveau=0, niveau_convert=0;

//choix entre jouer seul ou à deux
printf("\nVoulez-vous jouer seul ou a deux ?");
printf("\n\t-Pour jouer seul tapez 1\n\t-Pour jouer a plusieur tapez 2");
printf("\nVotre Choix :\t");
scanf_s("%ld",&nombre_joueur,3);
if (nombre_joueur==1)
{
	//mode 1 joueur : choix du niveau de difficultée
	puts("choisissez le niveau de difficultee :");
	puts("pour un niveau facile	(nombre compris entre 1 et 10   :\ttapez 1");
	puts("pout un niveau moyen	 (nombre compris entre 1 et 100  :\ttapez 2");
	puts("pour un niveau difficile (nombre compris entre 1 et 1000 :\ttapez 3");
	printf("\nvotre choix :\t");
	scanf_s("%d",&niveau,3);
	switch (niveau)
	{
	case 1:
		niveau_convert=10;
		break;
	case 2:
		niveau_convert=100;
		break;
	case 3:
		niveau_convert=1000;
		break;
	default:
		puts("veuillez tapez un nombre compris entre 1 et 3");
		break;
	}

	//mode 1 joueur : appel de fonction tirage du nombre aleatoire
	nombre_mystere=random(niveau_convert);
}
else if (nombre_joueur==2)
{
	//mode 2 joueur : appel de la fonction
	nombre_mystere=jeux_a_plusieur();
}
else;
//appel de la fonction "comparaison entre nombre a trouver et nombre donné en entrée
comparaison(nombre_mystere);
}
long random(int MAX)
{
//fonction de tirage aleatoire du nombre à trouver
long nombre_xx=0;
unsigned int t = (unsigned int) time(NULL);
const int MIN=1;
srand(t);
nombre_xx = (rand() % (MAX - MIN + 1)) + MIN;
return nombre_xx;
}
long jeux_a_plusieur()
{
// fonction permettant au joueur 1 de donner le nombre à trouver
long nombre_yy=0;
printf("\njoueur 1, veuillez tapez le nombre mystere s\'il vous plait :\t");
scanf_s("%d",&nombre_yy);
return nombre_yy;
}

void comparaison (long delta1)
{
long nb_myst=0;
long w=0;
//fonction de comparaison entre nombre a trouver et nombre donné en entrée
do
{
	printf("tapez le nombre mystere:\t");
	scanf_s("%d",&nb_myst);
	w++;

	if (delta1<nb_myst)
	{
		puts("vous etes au dessus");
	}
	else if(delta1>nb_myst)
	{
		puts("vous etes en dessous");
	}
	else;

}
while (nb_myst!=delta1);
printf("bravo vous avez gagnez en %d coups", w);
score(w);
}


char personne()
{
char tableau[50]={0};
printf("\ntapez votre prenom :\t");
scanf_s("%s",tableau,49);
printf("\nbonjour %s, pour jouer, suivez les instruction suivantes\n",tableau);
return *tableau;
}
int score(int xy)
{
return xy;
}

alors voila j'ai essayer d'utiliser les fonction, les condition (switch, etc...) comme vous me l'aviez spécifier. et dans l'ensemble le resultat fonctionne

par contre, j'imagine que c'est surement du a mes lacunes, mais personnellement je trouve sa (beaucoup) plus "bordelique" qu'avant. en tout cas j'ai plus de mal a m'y retrouver.

sinon j'ai essayer de faire un scoring mais cette fonction la j'y arrive pas (en fait je pense que ma valeur i qui doit prendre celle de score se reinitialise a un moment ou un autre ???) puisque quoi qu'il arrive sa retombe toujours a 0

si vous pouvez egalement m'aider a rendre ce code plus "clair" bienvenue a vous.

merci d'avance.

Lien vers le commentaire
Partager sur d’autres sites

probleme concernant l'elaboration de la fonction "score" resolu, en fait je m'etait pris la tete pour rien.

par contre pour le reste ce topic est toujours ouvert.

merci à lorinc, mephisto au grand tyran démoniaqu ( ;) ) et à tous les autres pour votre aide passée ou futur.

Lien vers le commentaire
Partager sur d’autres sites

déjà, les define (ouai, t'aura remarqué, je titille sur de la merde, question de principes :transpi: ):

dans l'idée, si t'as une chaine statique (et à plus forte raison si elle est longue), au lieu de déclarer une variable que tu vas initialiser sur 5 lignes, ou de lancer 5 appels à printf, tu peux définir ta chaine (#define):

#define CHAINE_TOTO "mon message"

[...]

{

printf("%s\n", CHAINE_TOTO);

}

ensuite, pour ce qui est de l'utilisation des chaines, petit conseil: pour l'initialisation, pense à memset()

enfin, tu peux aussi t'amuser avec un for() mettant chaque élément à 0

également sur les chaines (mais c'est du détail qui tue): vérifier que tu n'écris pas (sur stdout) de caractères non-imprimables.

C'est une connerie, c'est souvent useless, mais l'user est un connard, et il arrivera forcément à planter son term.

(d'ailleurs, au passage: si ton term "agit bizarrement" (comment l'expliquer... c'est space, c'est tout, tu comprendra le jour ou tu fera du debug de barbare sur stdout): "stty sane" et tu valides avec control+J)

et, pour fermer la parenthèse: ne fais jamais confiance à ce que l'user a bien pu taper

et pour en ouvrir une autre: les tableaux, c'est moche, et c'est la porte ouverte aux buffer overflows

tu vas t'habituer à la mise en page ; je t'assure, c'est plus propre qu'un main de 500 lignes :)

un petit must serait de déclarer tes prototypes à part (dans un .h)

et tant qu'à faire, pour tes headers, un petit réflexe pratique:

#ifndef _MON_FICHIER_

# define _MON_FICHIER_

[le contenu de ton .h: protos, structures, ...]

#endif

quand tu en viendra à des projets de plusieurs .c, ça évitera les inclusions multiples (ce qui est déclaré une fois l'est pour de bon)

enfin, pour masquer le score de ton adversaire:

- regarde du côté d'ioctl() et de TIOCWINSZ (ou un truc du genre), en dernier argument, t'envoies l'adresse d'une structure (cf. man, ça fait trop longtemps) qu'ioctl te remplie avec diverses infos sur les dimensions de ton term

- OU system("clear") (on est un GROS_FAIGNAN ou on l'est pas ^^ )

bon courage, et bonne continuation.

Lien vers le commentaire
Partager sur d’autres sites

Pour info Méphisto, je pense qu'il développe sous Windows et que certaines de tes dernières explications lui sembleront donc sûrement relativement obscures :francais: et il aura moins de problèmes de terminaux, du coup.

Mais sinon bonnes remarques. C'est normal gros_faignant que tu trouves ça moins lisible, faut juste s'habituer :transpi:

Pour masquer le score le system("clear") me suffit moi :]

Lien vers le commentaire
Partager sur d’autres sites

salut

la creation d'un main.h c'est fait.

ok pour les define et les ifdef, sa à l'air de rendre la vie vachement plus facile ces truc là.

mais la par contre le probleme c'est que meme si j'ai commencer à y jeter un coup d'oeuil, les pointeurs, tableaux et chaine de caractere me font encore un mal de crane pas possible. et sur le site du zero ils invitent "serieusement" a bien les maitriser avant de passer a la suite. (c un vrai bordel... )

du coup je me tape les exos qu'il propose (réécrire les fonction "strcpy","strcmp","strchr", "strstr") et depuis que je m'y suis mi j'ai plus vue mon code produire quelquechose de cohérent.

vas y, dis moi comment faire du débug de barbware.

pour stdout , vu le nom que sa à, ont dirai une bibliotheque, mais d'après ce que j'ai cherché sa a l'air dispo que sur linux,...

a sinon, comme mon pseudo l'indique, j'ai bien essayer system("clear") que j'ai callé dans void jeux_a_plusieurs()

sa compile niquel mais au debogage l'exe me renvoie dans la console

'clear' n'est pas reconnue comme une commande interne ou externe valide, blablabla...

sinon j'ai aussi penser à intercaller quelques incantation vaudou... :transpi:

nan allé une :p et ont s'y remet

Lien vers le commentaire
Partager sur d’autres sites

ouai, c'est la reflection de shtong.

je me suis sans doute trop base sur unix

clear est une commande (nix).

system premet d'executer une ligne de commande.

sous winwin, l'equivalent de 'clear', c'est 'cls' (fais le remplacement)

par contre, aucune idee au sujet de l'existence d'un equivalent a ioctl() & co.

stdout, c'est ta sortie standart

quand tu fais un write(1, "b*te", 4);, un printf("b*te"); ou un fprintf(stdout, "b*te");, tu ecris sur stdout

mais comme l'as fait remarquer shtong, si tu codes sur un OS terreux (desole, c'est gratuit), les reflections sur le comportement d'un term te serviront pas a grand chose

Lien vers le commentaire
Partager sur d’autres sites

+1 pour "cls"

d'accord que c terreux, et encore plus quand t'a la version du pauvre.

mais y faut lui reconnaitre un avantage : quand t'es tout sauf un informaticien ou un geek, c'est le systeme le plus répandu, sa fonctionne tout seul, ya word, excel et tout les programme utilisé par les user lambda comme moi (ce qui ne devrais pas durée) sont compatible avec.

quand ton probleme de tout les jour c'est de faire des recherche web, de taper des rapport, d'enregistrer et de traiter des données, de faire des présentation ppt, de travailler en collab a distance, et tout ces truc la, pour sa c'est nickel, t'utilise le systeme a 10 % de ces capacité du coup temps que tu fait un minimum gaffe (comme un gosse de 10 ans pourrais le faire) sa plante jamais, et t'appuie sur un bouton et sa marche tout seul...

franchement je me vois mal prendre en main linux ou ubuntu comme un windows.

et leur service client est plutot haut point (je dis sa sans connaitre toutefois la valeur des autres...)

par contre stdout... gddout

a quoi sa sert d'ecrire dans la sortie puisque le compilateur y ecrit pour te montrer ou sa peche ???

Lien vers le commentaire
Partager sur d’autres sites

mais la par contre le probleme c'est que meme si j'ai commencer à y jeter un coup d'oeuil, les pointeurs, tableaux et chaine de caractere me font encore un mal de crane pas possible. et sur le site du zero ils invitent "serieusement" a bien les maitriser avant de passer a la suite. (c un vrai bordel... )

du coup je me tape les exos qu'il propose (réécrire les fonction "strcpy","strcmp","strchr", "strstr") et depuis que je m'y suis mi j'ai plus vue mon code produire quelquechose de cohérent.

+1 pour la maitrise des tableaux :byebye: c'est important

Lien vers le commentaire
Partager sur d’autres sites

  • 2 semaines après...

rebonjour,

voila pour en revenir a mon petit programme sur les jeux de nombre, sur lequel j'ai implenté la fonction de scoring que voici :

int score(int nb_coup)
{
static long compteur1=0;
compteur1=compteur1+nb_coup;
return compteur1;
}

cette fonction prend le nombre de tentative de "trouvaille" du nombre mystere par le joueur (fait dans la boucle de comparaison)

comme ceci

score(w); //w correspondant a un ++ à chaque tour de boucle

cette fonction score etant ensuite recupéree dans le main et divisé par le nombre j, correspondant au nombre de partie effectué, comme ceci :

printf("\nVotre moyene de score s\'eleve a : %d\n",(score()/j));

ce qui jusqu'a présent n'a posé aucun probleme. sauf que quand j'essaye d'etoffer mas fonction score en creant un fichier "scoring.c" et que j'integre dedans ladite fonction. le compilateur me renvoie une erreur comme quoi il manque des parametre a ma fonction score.

ce qui quelque part est logique.

par contre ce que je ne comprend pas c'est :

1/ pourquoi sa marche dans un cas et pas dans l'autre.

2/ a la vase j'avais mis ma variable long compteur1 en static pour que justement je puisse recuperer sa valeur dans une autre fonction. sauf que si je lui envoie un parametre dans l'appel par ma fonction main^^ je recupere plus la valeur de w.

enfin bref je sais pas si tout sa est très clair mais si besoins je peut rajouter des explication.

merci a ceux qui pourront me donner une reponse, surtout pour la question 1.

Lien vers le commentaire
Partager sur d’autres sites

un peu confus :)

poste les fichiers concernés, vérifie que tu compiles bien les deux .c

1/ s'il ne te parles que de 'paramètres manquants', peut-être est-ce une façon redmonnienne de t'indiquer que tu n'as pas précisé de prototypes.

rajoute un long score(long); dans le fichier ne comprenant pas la fonction.

et d'ailleurs, si ton score est stocké en long, tu as tout intérêt à renvoyer un long avec ta fonction.

tu peux éventuellement également prendre un long en paramètre, mais dans ton cas, ce n'est pas forcément justifié.

2/ si tu veux éviter d'incrémenter ton score avant de le récupérer, appelle score(0)

sinon, prévois dans score une série d'appelles avec des nombres négatifs (par exemple) qui te permettront de consulter / reset / faire une opération spéciale sur le compteur

Lien vers le commentaire
Partager sur d’autres sites

un peu confus :)

poste les fichiers concernés, vérifie que tu compiles bien les deux .c

2/ si tu veux éviter d'incrémenter ton score avant de le récupérer, appelle score(0)

effectivement ces conseille m'ont permis de trouver solution a mon probleme. mais pour donner quelque explication mon probleme ne venait pas que de la.

tou d'abord j'ai finis par comprendre que :

1/ je devais bien inclure scoring.h dans main.c

2/ qu'il n'etait pas utile d'inclure scoring.c ou que ce soit (moi je trouve sa bizarre mais bon sa fonctionne comme sa)

ensuite pour expliqué la cause de mes ennuis, mon objectif etait de creer une fonction scoring qui compterai le nombre de coups fait par le joueur a chaque partie et le nombre de partie effectuée et qui en ferait une moyenne sauf que probleme, je devait donc realisé une fonction que prenait en argument 2 variables provenant chacune d'une fonction différente...

mais j'ai finis par trouver une solution (grace au pointeur :D thanks for explains :D )

donc, juste pour l'histoire avant de vous donné le code source, il est 7H30 du mat, j'y suis depuis hier 18H00 et après 1 paquet de de café, sont petit frere un peut estropié, ET une mise a jour intempestive de windows qui m'oblige a réecrire se post j'arrive au bout. enfin !!!!!!!!!!!!! :-D

qu'oi qu'il en soi (je pense) que ce code est un peut plus optimisé (meme s'il est peut etre plus long que le précedent");

(critique bienvenue -methodes de travail aussi, j'en ai tester 2 ce soir, elles m'ont reappris la saveur de l'aspirine)

et en plus j'avais fait un petit schema explicatif mais je vois pas comment l'uploadé

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int nb_player();		//determine le nombre de joueur
int nb_myst(int *ptr1);	//determine le nombre de joueur selon qu'il sont 1 ou 2
int MAX();				//determine le niveau de difficultée du jeu a 1 joueur
void nb_enter(int *ptr2,int nb_xx);	 //nombre entré par le user pour trouver le nombre mystere
int comparaison (int nb_user, int nb_xx);	 //fonction de comparaison du nombre mystere au nombre user
void play_replay();		// comme sont nom l'indique


int main(int argc, char *argv[])
{
/*Pas d'appel ulterieur possible a la fonction "main" depuis les autres fonction donc je m'en sert que 
comme d'un appel unique (sa c'est surement un peut tordu...) */
play_replay();
system ("pause");
return 0;
}

void play_replay()
{
/*La fonction play_replay ne sert qu'à 2 chose :
*1- creer la boucle de jeux initiale et secondaire (rejouer)
*2- initialiser les variable (x(nb partie),y (nb coups) et z(nb coups total) qui seront transmise (x et y seulement) aux pointeur (qui permettent
* l'incrementation) dans le but de calculer le scoring...*/
int x=0, y=0, z=0, replay=0;
do
{
	/*comme préciser dans les proto, nb_enter prend en entrée : "y" et l'envoie a sont pointeur en premier argument et appel
	"nb_myst" en deuxieme argument (qui sauf erreur de ma part est traité en premier), nb_myst envoyant "x" en argument ver
	sont pointeur*/
	nb_enter(&y,nb_myst(&x));
	printf("\nbravo vous avez gagner en %d coups\nPour rejouer tapez 1\nPour quitter tapez 0\nVotre choix :\t",y);
	z=z+y;
	scanf_s("%d",&replay);
}while(replay!=0);
printf("votre moyenne de score s'eleve a %3.3f coups par partie sur %d partie\n\n",((float)z/(float)x),x);
}
int nb_player()
{
int x=0;
printf("\nVoulez-vous jouer seul ou a deux ?\n\t-Pour jouer seul tapez 1\n\t-Pour jouer a plusieur tapez 2\n\t-Pour quitter tapez 0\nVotre Choix :\t");
scanf_s("%d",&x,3);
while(x<0&&x>2)nb_player();//sorte de boucle si mauvais chiffre entrer par le user
if(x==0)
{
	system("pause");
	return 0;
	exit(0);
}
return x;
}
int nb_myst(int *ptr1)
{
int X=0, player=0,i=0;
const int MIN=1;
unsigned int t = (unsigned int) time(NULL);
srand(t);
//nb_myst etant appeler par nb_enter et appelant a sont tour nb_player, cette derniere est la premiere fonction utilisée
player=nb_player();
if(player==1)
{
	X = (rand() % (MAX() - MIN + 1)) + MIN;
}
else if(player==2)
{
	printf("\nJoueur 1, tapez le nombre mystere :\t");
	scanf_s("%d",&X);
	system("cls");
}
else exit (0);
i++;
// ptr1 correspond au pointeur de score "nombre de partie" (x) prie en entrée par nb_myst
*ptr1=*ptr1+i;
return X;
}

int MAX()
{
int niveau=0;
puts("choisissez le niveau de difficultee :");
puts("pour un niveau facile	(nombre compris entre 1 et 10   ):\ttapez 1");
puts("pout un niveau moyen	 (nombre compris entre 1 et 100  ):\ttapez 2");
puts("pour un niveau difficile (nombre compris entre 1 et 1000 ):\ttapez 3");
printf("\nvotre choix :\t");
scanf_s("%d",&niveau,3);
while(niveau<1&&niveau>3)
{
	puts("merci de tapez un nombre compris entre 1 et 3");
	scanf_s("%d",&niveau,3);
}
//le niveau n'est plus déterminé par un switch mais par une puissance de 10 (castée en int)
return (int)(1*pow(10,niveau));
}
void nb_enter(int *ptr2,int nb_xx)
{
int nb_user=0, i=0;
do
{
	printf("\nveuillez tapez le nombre mystere svp :\t");
	scanf_s("%d",&nb_user,1000);
	i++;
}while(comparaison(nb_user,nb_xx)!=1);
/*ont boucle tant que la bonne valeur n'est par retournée par comparaison et on incremente pointeur *ptr2 qui augmente
la valeur du nombre de partie "y" i(+1) dans play_replay*/
*ptr2=i;
}
int comparaison (int nb_user, int nb_xx)
{
//prend en argment nb_user et nb_xx tout deux fournis par nb_enter
int i=0, x=nb_user, y=nb_xx;
if (y<x)
{
	puts("vous etes au dessus");
}
else if(y>x)
{
	puts("vous etes en dessous");
}
//renvoie la valeur 1 si nb_user n'est ni inferieur ni superieur a nb_xx donc si le joueur a trouver
else return 1;
return 0;
}

Lien vers le commentaire
Partager sur d’autres sites

courage, c'est comme ça que ça rentre ^^

effectivement, on n'inclue pas de .c, mais on le fait avec les .h

c'est sans doute moins évident sous winwin (pardon d'en revenir là), puisque tu ne vois pas la ligne de commande qui lance la compilation.

mais, globalement, une compilation "minimaliste", c'est gcc *.c (enfin, dans le cas de ton programme, il faut également linker la libmath)

le mode de fonctionnement du compilateur (ouai, c'est la version ultra-light++) :

première étape, la traduction en langage machine.

chaque fichier .c est lu et interprété, indépendament.

les headers & prototypes qui seront évoqués dans le fichier sont chargés

les macros sont remplacés par leurs valeurs respectives

le code est traduit en langage machine (si certains protos n'ont pas été chargés, c'est mal (bouh !), certaines options de ton compilos le confirmeront)

il y a -bien sûr- d'autres traitements.

la seconde étape, c'est le "linkage", qui produit l'exécutable.

le compilateur va relier tous les objets qu'il a généré, et faire le lien entre les différentes fonctions

ayant tout en main, il peut maintenant calculer les offsets des fonctions propres à ton programme.

les appels aux différentes fonctions sont remplacés par un jmp (enfin, pas seulement) vers la fonction en question.

les .h sont donc nécessaires dans la première étape, lorsque le compilateur veut vérifier l'existence (théorique) d'une certaine fonction, quand il à besoin de remplacer une macro, quand il ne reconnait pas un type utilisé, ....

et les .c ne s'incluent pas les uns dans les autres (enfin, ça peut se faire, mais c'est super crade, et le .c est traité comme un .h, puisque son contenu ne sera pas compilé à proprement parler, mais ne servira que de "référence")

ensuite, concernant ton code:

- une petite astuce (qui ne changera rien, c'est juste de la culture :D ): quand tu fais un prototype de fonction (hors déclaration), tu peux te contenter de donner les types sans forcément nommer tes variables. exemple: pour "size_t strlen(const char *str){code}", le prototype pourrait se limiter à "size_t strlen(const char*);"

certains diront que c'est plus perturbant qu'autre chose (c'est pas faux), et si quelqu'un vient reprendre ton code, il aura peut-être du mal à s'y retrouver avec une fonction de 30 arguments. c'est donc plus une question d'esthétisme. maintenant, t'es au courant ^^

- la théorie du main:

c'est à nouveau contestable et esthétique, mais un main est un main.

c'est la fonction principale de ton programme, c'est pas mal quand elle ressemble à ça.

je m'explique:

un main ne fait rien, mais gère tout.

dans ton cas, un jeux, auquel tu peux jouer un nombre indéfini de fois.

le main ferait donc l'initialisation du jeu (bon, t'en as pas vraiment, ça concerne plus l'init des différentes structures/... nécessaires, où encore de l'interface graphique)

ensuite, une boucle lançant la partie. suivant la valeur de retour de la fonction gérant la partie, on peu alors soit en relancer une autre, soit quitter leu jeu

le main se termine par le "déchargement", lorsque tu free / nettoie tout ton bordel, avant de quitter.

mais j'ai perdu le fil. ton main est bien, vu le contenu du programme.

si je voulais parler du main, c'était avant tout pour te signaler que, pour éviter de prototyper 50 fonctions dans tes .h, tu peux aussi te contenter de déclarer les fonctions appelées avant les fonctions appelantes.

concrètement, un truc comme ça:

main()

{

play();

}

play()

{

compute_magic_number();

}

compute_magic_number()

{

}

t'oblige à prototyper play(); et compute_truc();

tandis que

compute_magic_number()

{

}

play()

{

compute_magic_number();

}

main()

{

play();

}

te permet de ne déclarer (pour ce .c) aucun des prototypes pour les fonctions déclarées dans le .c

je sais pas si je suis bien clair, je m'arrête là sur la propreté/organisation, ça devenait un pavé.

- dans nb_player, le exit(0), en dessous du return 0; ne sert à rien

- par ailleurs, c'est un peu sâle de rappeler nb_player() à chaque fois que t'as pas ce que tu veux (enfin, c'est sâle parceque tu le fais de nb_player même, et dans un cas pareille, la récursion n'est pas forcément le meilleur choix)

while(x<0&&x>2)nb_player();//sorte de boucle si mauvais chiffre entrer par le user
if(x==0)
{
	system("pause");
	return 0;
	exit(0);
}

dans un cas pareille, un switch serait plus approprié.

rapidement, ça donnerait

x = -1;

do{

switch (x)

{

case 0: return 0; break ;

case 1: break;

case 2: break;

default: [tu print ton message, tu fais ton scanf("%d", &x);

}

} while (x != 1 && x != 2)

- pour la fonction comparaison, ça me semble un bon moment pour les ternaires

if (x != y)

printf("vous êtes %s\n", x > y ? "en dessous" : "au dessus");

return x == y ? 1 : 0; // les puristes feront return ((x == y)); => si "x == y" est vrai, on a 1, autrement, on a 0;

Lien vers le commentaire
Partager sur d’autres sites

- par ailleurs, c'est un peu sâle de rappeler nb_player() à chaque fois que t'as pas ce que tu veux (enfin, c'est sâle parceque tu le fais de nb_player même, et dans un cas pareille, la récursion n'est pas forcément le meilleur choix)

ouai c vrai que j'ai fait honneur a mon pseudo pour le coup.

- pour la fonction comparaison, ça me semble un bon moment pour les ternaires

if (x != y)

printf("vous êtes %s\n", x > y ? "en dessous" : "au dessus");

return x == y ? 1 : 0; // les puristes feront return ((x == y)); => si "x == y" est vrai, on a 1, autrement, on a 0;

effectivement, sa raccourcis vachement le code, c'est vrai que je m'etait pas attarder dessus au debut par ce que dans les tuto ils parte du principe que c'est pas forcement le plus lisible donc j'ai commencer par chercher a maitriser les autres, celles la etant donc passées a la trappe (decidement :francais: ). mais, j'en prend bonne note

je m'arrête là sur la propreté/organisation, ça devenait un pavé.

alors concernant l'organisation, ou plutot les methodes de travail, en ecrivant ce code j'en ai "testé" deux, le resultat etant un mix.

d'un coté j'ai pris pour principe que mon programme avec, grosso modo 2 fonction principale :

- le random du nombre mystere

- la comparaison de ce nombre a d'autre nombre

cette facon de faire, ma logiquement conduit a ecrire ces deux fonctions en premier, et meme si je me dit que sa m'a peut etre permis de l'envisager différent (ces deux fonction etant en gros le coeur du prog, le reste n'etant que l'interaction entre le user et ces deux fonction), je me suis vite rendu compte que sa devenait vite difficile de s'i retrouver (mon premier appel de fonction dans mon main etait celui de ma fonction de comparaison - la dernière a intervenir) ce qui fonctionnait mais donnait un rendu un peut perturbant.

l'autre, celle que j'avais utilisé la première fois, ont par des première fonction qu'utilise le user et ont les ecrit de manière sequentielle.

et bien que sa me semble logique d'ecrire comme sa je suis pas convaincu que ce soit la meilleur facon. par ce que du cout, enfin c'est mon impression, ont se retrouve, comment dire, a etre grosso modo obliger d'envisager quasiment chacune des situations qui pourrait se produire si ceci ou cela, mais bon j'en sais rien.

du coup le resultat est un mix des deux. donc je me disait que de ce point de vue la, il y avait peut etre certain principe généraux applicable pour facilité la perception de la structure du code ...

Lien vers le commentaire
Partager sur d’autres sites

Archivé

Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.

×
×
  • Créer...