Bonjour, j'ai réaliser ce TP et après avoir reçu les remarques de mes correcteurs, j'essaye d'optimiser mon code afin de prendre de bonnes habitudes.
J'ai rencontré 2 problèmes lors de cet exercices le premier provient de la fonction 'rand' qui ne permet pas d'obtenir un 'int' supérieur à 32727, et j'ai aussi remarqué que le résultat de ce 'rand' restait toujours dans la même fourchette lors de mes test les résultats tournaient entre 19 000 et 20 000.
La deuxième question que je me pose lors de chaque nouvelle partie je recharge le dictionnaire en faisant appel à une fonction. Hors si j'ai bien compris lorsque la fonction est lue mon 'vector' mots est effacer de la mémoire. Que vaut t'il mieux faire garder en mémoire ce 'vector' ou l'effacer lorsque j'en ai plus besoin pour le reste du programme.
J'ai utiliser aussi le 'namespace std' pour être sur la même longueur d'onde que le cours sinon j'ai lu qu'il est préférable d'utiliser 'std::' .
Voici mon code, je vous remercie d'avance pour vos conseils.
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <fstream>
#include <vector>
using namespace std;
string melangerLettres(string mot)
{
string melange;
int position(0);
//Tant qu'on a pas extrait toutes les lettres du mot
while (mot.size() != 0)
{
//On choisi un numéro de lettre au hasard dans le mot
position = rand() % mot.size();
//On ajjoute la lettre dans le mot mélangé
melange += mot[position];
//On retire cette lettre du mot mystère
//Pour ne pas la prendre une deuxième fois
mot.erase(position, 1);
}
//On renvoie le mot mélangé
return melange;
}
char rejouer(char ouiNon)
{
// boucle tant que la lettre tapée n'est pas "o" ou "n".
do
{
cout << "Voulez vous rejouer O/N ?" << endl << endl;
cin >> ouiNon;
if (ouiNon == 'o')
{
cout << "Nouvelle partie !" << endl << endl;
}
else if (ouiNon == 'n')
{
cout << "Fin du jeu !" << endl << endl;
}
else
{
cout << "Erreur veuillez taper \"o\" ou \"n\" !" << endl << endl;
}
} while (ouiNon != 'n' && ouiNon != 'o');
return ouiNon;
}
void pause()
{
cout << "Apuyez sur la touche Entree pour quitter ..." << endl;
cin.ignore();
cin.get();
}
//ouverture du dictionnaire et choix du mot
string motAleatoire(string mot)
{
vector<string> mots;
int aleatoire;
ifstream dico("dico.txt");
if (dico)
{
while (dico >> mot)
{
mots.push_back(mot);
aleatoire = rand() % mots.size();
mot = mots[aleatoire];
}
}
//si le dictionnaire est corrompu ou manquant fermeture du programme
else
{
cout << "Erreur impossible de lire le dictionnaire" << endl;
pause();
exit(EXIT_FAILURE);
}
return mot;
}
int main()
{
// Initialisation des nombres aléatoires
srand(time(0));
char ouiNon('a');
//Message de bienvenue
cout << "Trouvez le mot MYSTERE moins de 5 tentatives" << endl << endl;
cout << "Bonne chance !!!" << endl << endl;
do
{
string motMystere, motMelange, motUtilisateur;
int compteur(0);
//On cree le mot mystere
motMystere = motAleatoire(motMystere);
//On récupère le mot avec les lettres mélangées dans motMelange
motMelange = melangerLettres(motMystere);
// On commence à compter les essais .
compteur++;
//On demande à l'utilisateur quel est le mot mystère
do
{
cout << endl << "Essai " << compteur << "/5" << endl << endl;
cout << endl << "Quel est ce mot ? " << motMelange << endl;
//l'utilisateur entre un mot
std::cin >> motUtilisateur;
if (motUtilisateur == motMystere)
{
cout << "Vous avez gagne en " << compteur << " coups."<< endl;
//On appelle la fonction gagne
}
else
{
cout << "Ce n'est pas le mot !" << endl << endl;
//On ajoute +1 au compteur d'essais
compteur++;
//si le compteur arrive à 5 c'est perdu.
if (compteur > 5)
{
cout << "Vous avez Perdu le Mot mystere est " << motMystere << endl << endl;
//fin du jeu
ouiNon = rejouer(ouiNon);
}
}
} while (motUtilisateur != motMystere);
//On recommence tant qu'il n'a pas trouvé
} while (ouiNon == 'o');
pause();
return 0;
}
Changes de cours. Il apprend un sacré paquet d'âneries à ne pas faire, en plus de montrer des exemples de code buggés et d'être obsolète (quelques recherches sur le forum t'en diront plus). Prends plutôt le tutoriel disponible sur Zeste de Savoir. Ou encore le cours de C++ de @gbdivers, même s'il est encore en écriture il ne contient pas ce genre de bavures (et si tu as des problèmes de compréhension sur une partie et que ce n'est pas à cause d'un manque d'étude du cours,tu peux poster ici). Si tu préfères un cours déjà complet, tourne toi vers le C++ Primer de Lippman dans sa dernière édition (en anglais), il sera un poil moins à jour mais c'est un bon cours.
Quelques remarques concernant ton code :
ne met pas de commentaires s'ils sont inutiles (tous ici). Le bon commentaire, c'est celui qui n'est pas écrit parce que le code est clair et n'en nécessite pas,
ta fonction de choix aleatoire est très bizarre (l'entrée ne sert à rien, tu changes le mot à chaque tour sans aucune raison),
tu relis ton fichier chaque fois que tu as besoin d'un mot, c'est très inefficace, charges tout dans un vector et conserve ce vector pour y piocher des mots,
dans ton mélange, tu récupères la position dans un entier, mais le type des index est std::size_t (et pour mélanger, il existe std::shuffle).
Ton problème vient d'une limitation intrinsèque à rand(). Cette fonction renvoie comprise entre RAND_MIN et RAND_MAX qui s'avèrent souvent être SHORT_MIN et SHORT_MAX. Soit de petites valeurs. Utilise les fonctionnalités de C++ comme proposé plus haut.
J'ai retardé au maximum la déclaration des variables.
je ne ferais plus
int unInt;
//du code
unInt = 10;
mais plutôt
//du code
int unInt = 10;
Pour les fonctions j'avais peur d'en faire de trop et je n'ai pas osé je vais continuer d'expérimenter et en créer de nouvelles.
Effectivement je crée un nouveau mot mystère a chaque tour vu que j'appelais ma fonction 'motAleatoire' dans une boucle 'do while' et ça n'avait rien à faire là. Je dois créer une fonction séparée qui stocke le dictionnaire dans un 'vector'.
Je ne suis qu'au début de mon apprentissage et je fait le maximum pour me remettre en question et prendre les bonnes habitudes grâce à tes conseils et avec tous les liens que tu m'a donné j'ai de quoi faire merci encore.
Pour les fonctions j'avais peur d'en faire de trop et je n'ai pas osé je vais continuer d'expérimenter et en créer de nouvelles.
Il est vrai que l'on se demande parfois si on ne fait pas "trop" de fonctions...
Mais, l'un dans l'autre, si chaque fonction que l'on peut créer ne prend qu'une et une seule responsabilité, nous ne pourrons jamais qu'arriver à un point où il n'y aura que "juste assez" de fonctions
Il ne faut pas essayer de "partager" la responsabilité d'une fonction, ce qui mènerait effectivement à en avoir trop. Mais il s'agit surtout de veiller à ce que chaque fonction ne fasse que "ce qu'elle est sensée faire":
Si tu veux, dans l'ordre,
extraire les différents mots que tu trouve dans un fichier
choisir un (unique) mot parmi ceux que tu as extraits en (1)
mélanger les lettres qui composent le mot que tu as choisi
poser différentes questions à différents moments à l'utilisateur
suivre une logique particulière qui mette les réponses de l'utilisateur en rapport avec le mot choisi en (2) et mélangé en (3)
recommencer en (2), pour que l'utilisateur puisse faire plusieurs partie
mettre le tout "en musique" pour obtenir une application exécutable
tu te retrouve directement avec plus de sept responsabilités distinctes (car tu devras compter au moins deux responsabilités distinctes pour chaque question que tu veux poser à l'utilisateur : une pour l'afficher, et l'autre pour ... récupérer sa réponse).
Alors, bien sur, il est sans doute possible de réutiliser certaines des responsabilités décrites en (4), parce qu'il n'y a que quelques détails qui changent (on dit qu'on "factorise" le code ), mais le compte effectué ici est relativement juste
Pour chacune de ces responsabilité, il faudra prévoir une fonction particulière, en sachant:
que le (7) correspondra à la fonction principale "main"
que le (7) et le (5) vont -- de toute évidence -- faire visiblement "prendre en charge" ... "toute la logique" qui permet de faire appel à des responsabilités plus précises
Mais, au final, la création d'une application n'est jamais qu'un jeu de légo : on commence par créer des "petites briques" basiques (les fonctions les plus simples), que l'on pourra assembler entre elles pour obtenir des "pans de murs" (des fonctions plus complexes), qui seront -- eux aussi -- assemblés entre eux pour obtenir les murs (des fonctions encore plus complexes), que nous pourons utiliser pour construire des tours, des douves, des bâtiments divers et variés et des remparts (des fonctions de plus en plus complexes) que nous pourrons regrouper pour construire ... notre zoli chateau-fort / notre zolie ville fortifiée (notre application).
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
Le do ->while(motUtilisateur != motMystere); il faut ajouter le compteur <= 5 dans la condition genre (motUtilisateur != motMystere) || (compteur <= 5)
Le do ->while(motUtilisateur != motMystere); il faut ajouter le compteur <= 5 dans la condition genre (motUtilisateur != motMystere) || (compteur <= 5)
Oui j'ai vu que lorsque je perds la partie je ne sorts pas de la boucle et le compteur continue j'ai essayé cette solution
} while (motUtilisateur != motMystere || compteur <= 5);
mais ça ne marche pas il ne prend pas en compte le deuxième argument et je reste coincé dans la boucle
Pour palier à ce problème j'ai utilisé un bool du grenre
bool fini(false);
//On demande à l'utilisateur quel est le mot mystère
do
{
std::cout << std::endl << "Essai " << compteur << "/5" << std::endl << std::endl;
std::cout << std::endl << "Quel est ce mot ? " << motMelange << std::endl;
//l'utilisateur entre un mot
std::cin >> motUtilisateur;
if (motUtilisateur == motMystere)
{
std::cout << "Vous avez gagne en " << compteur << " coups."<< std::endl;
//On appelle la fonction gagne
ouiNon = rejouer(ouiNon);
fini = true;
}
else
{
std::cout << "Ce n'est pas le mot !" << std::endl << std::endl;
//On ajoute +1 au compteur d'essais
compteur++;
//si le compteur arrive à 5 c'est perdu.
if (compteur > 5)
{
std::cout << "Vous avez Perdu le Mot mystere est " << motMystere << std::endl << std::endl;
//fin du jeu
ouiNon = rejouer(ouiNon);
fini = true;
}
}
} while (fini == false);
J'ai utilisé cette méthode mais je ne comprends pas pourquoi lorsque j'utilise deux conditions je n'arrive pas à sortir de ma boucle.
- Edité par Jean-LouisGustine 30 octobre 2018 à 10:14:26
Les conditions dans les boucles, quelles qu'elles soient, indiquent ce qui doit être respecter pour RETOURNER dans la boucle.
Si tu veux QUITTER la boucle si mot == mot mystère OU si compteur == 5, la condition pour RETOURNER dans la boucle devient quoi?
- Edité par koala01 30 octobre 2018 à 10:18:04
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
Le do ->while(motUtilisateur != motMystere); il faut ajouter le compteur <= 5 dans la condition genre (motUtilisateur != motMystere) || (compteur <= 5) c'est mieux optimiser?? non ??
Et, là, tu décides de rentrer dans la boucle si le motUtilisateur est différent de motMyster OU si compteur <= 5 ...
Or, les deux conditions doivent être remplies pour que l'on puisse rentrer dans la boucle: dés que l'une d'elle n'est plus remplie, il faut quitter la boucle!
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
C'est du standard, c'est lisible, c'est évolutif, c'est ce qu'on attend généralement d'un développeur
Maintenant on te dit que le tableau est paginé par 64 valeurs ( si j'ai bien compris ), et bien voici l'optimisation proposée par godbolt (le main est de moi donc sûrement pas optimisé)
#include <iostream>
#include <cstring>
// Compile with -O3 -march=native to see autovectorization
// assumes input is aligned on 64-byte boundary and that
// length is a multiple of 64.
int somme_totale(int* input, int length) {
// Alignment hints supported on GCC 4.7+ and any compiler
// supporting the appropriate builtin (clang 3.6+).
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
#if __GNUC__ > 4 \
|| (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) \
|| __has_builtin(__builtin_assume_aligned)
input = static_cast<int*>(__builtin_assume_aligned(input, 64));
#endif
#if _MSC_VER
__assume((length & 63) == 0);
#else
if (length & 63) __builtin_unreachable();
#endif
int sum = 0;
for (int i = 0; i < length; ++i) {
sum += input[i];
}
return sum;
}
int main()
{
static const size_t TABSIZE = 64;
int tab[TABSIZE];
for(size_t i=0; i<TABSIZE; ++i)
tab[i] = 1;
std::cout << somme_totale(tab, TABSIZE) << std::endl;
return 0;
}
Que c'est laid, et la syntaxe lourde xP et pourtant plus rapide, plus léger, plus optimisé, que ma version utilisant du standard
- Edité par romantik 30 octobre 2018 à 14:57:35
Dream on, Dream on, Dream until your dream comes true
Tiens juste pour te montrer qu'il y a pas de règle. Ton code optimisé par GCC, j'ai juste remplacé l'affichage par un return pour ne pas s'encombrer du code d'affichage qui est illisible.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C
git is great because Linus did it, mercurial is better because he didn't.
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C