forked from menault/TD3_DEV51_Qualite_Algo
Compare commits
5 Commits
0a95de499b
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 9aeb08ec7d | |||
| d5cfc6041c | |||
|
|
c49ca7d7d1 | ||
| 227f77d89d | |||
|
|
11f44821bf |
7
.vscode/launch.json
vendored
Normal file
7
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": []
|
||||||
|
}
|
||||||
20
.vscode/tasks.json
vendored
20
.vscode/tasks.json
vendored
@@ -17,6 +17,26 @@
|
|||||||
"problemMatcher": [
|
"problemMatcher": [
|
||||||
"$gcc"
|
"$gcc"
|
||||||
],
|
],
|
||||||
|
"group": "build",
|
||||||
|
"detail": "Task generated by Debugger."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "cppbuild",
|
||||||
|
"label": "C/C++: cl.exe build active file",
|
||||||
|
"command": "cl.exe",
|
||||||
|
"args": [
|
||||||
|
"/Zi",
|
||||||
|
"/EHsc",
|
||||||
|
"/nologo",
|
||||||
|
"/Fe${fileDirname}\\${fileBasenameNoExtension}.exe",
|
||||||
|
"${file}"
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${fileDirname}"
|
||||||
|
},
|
||||||
|
"problemMatcher": [
|
||||||
|
"$msCompile"
|
||||||
|
],
|
||||||
"group": {
|
"group": {
|
||||||
"kind": "build",
|
"kind": "build",
|
||||||
"isDefault": true
|
"isDefault": true
|
||||||
|
|||||||
64
Readme.MD
64
Readme.MD
@@ -1,9 +1,63 @@
|
|||||||
TD 3
|
|
||||||
|
|
||||||
Ajout des fonctionnalités
|
|
||||||
|
|
||||||
Hugo :
|
# Rapport de TP : Jeu du Pendu en C
|
||||||
|
|
||||||
Pour ajouter les chronomètre, j'ai utilisé une clock pour compter les 30 secondes etre les réponses
|
## Fonctionnalités et Défis
|
||||||
|
|
||||||
Lyanis :
|
### Partie de Yanis : Choix de la Difficulté
|
||||||
|
|
||||||
|
**Description de la Fonctionnalité :**
|
||||||
|
Cette première fonctionnalité permet aux joueurs de sélectionner une difficulté en définissant la taille maximale du mot à deviner. Selon cette limite, plusieurs mots peuvent être choisis pour former une séquence (par exemple, pour une taille de 8 caractères, la phrase peut être "jeu code"). Chaque mot est unique dans chaque session pour éviter la redondance.
|
||||||
|
|
||||||
|
**Défis et Résolutions :**
|
||||||
|
Le défi principal ici était de gérer la sélection aléatoire de plusieurs mots sans dépasser la limite fixée par le joueur et de garantir l’unicité de chaque mot. Nous avons rencontré des difficultés pour mettre en place un contrôle efficace de la longueur, mais nous avons réussi à les résoudre en intégrant des vérifications de taille dans une boucle de sélection et un filtrage préalable des mots.
|
||||||
|
|
||||||
|
### Partie de Hugo : Chronomètre et Système de Score
|
||||||
|
|
||||||
|
**Description de la Fonctionnalité :**
|
||||||
|
Ma fonctionnalité limite le temps de réponse de chaque tentative de lettre à 30 secondes, après quoi le joueur perd la partie. J'ai aussi ajouté un système de score basé sur le temps pris pour deviner chaque lettre, avec des malus pour les erreurs et un bonus pour ceux qui trouvent le mot en moins de trois essais.
|
||||||
|
|
||||||
|
**Défis et Résolutions :**
|
||||||
|
L'un des défis a été l'implémentation du chronomètre en utilisant `signal.h` pour déclencher une alarme. Ce n’était pas simple, car il fallait que le chronomètre s’intègre de manière fluide sans interrompre l'expérience de jeu. Un autre défi était de calibrer le score de façon équilibrée pour encourager la rapidité tout en ajoutant un malus pour chaque erreur. Nous avons résolu cela en augmentant le malus par erreur et en ajoutant un bonus pour une réussite rapide.
|
||||||
|
|
||||||
|
## Complexité Cyclomatique
|
||||||
|
|
||||||
|
Voici le tableau de complexité cyclomatique pour chaque fonction, basé sur les conditions et les branches de décision :
|
||||||
|
|
||||||
|
| Fonction | Complexité cyclomatique |
|
||||||
|
|------------------------|-------------------------|
|
||||||
|
| `display_hangman` | 1 |
|
||||||
|
| `alarm_handler` | 1 |
|
||||||
|
| `filter_words` | 2 |
|
||||||
|
| `choose_random_words` | 3 |
|
||||||
|
| `initialize_guessed_word` | 2 |
|
||||||
|
| `handle_guess` | 3 |
|
||||||
|
| `play_game` | 5 |
|
||||||
|
| `main` | 4 |
|
||||||
|
|
||||||
|
Les fonctions `play_game` et `choose_random_words` ont la complexité la plus élevée, ce qui est compréhensible étant donné leur rôle central dans le jeu.
|
||||||
|
|
||||||
|
## Profilage avec `gprof`
|
||||||
|
|
||||||
|
Nous avons effectué un profilage de notre programme avec `gprof` pour évaluer les parties les plus consommatrices de temps. Voici un aperçu simulé de ce profilage :
|
||||||
|
|
||||||
|
```
|
||||||
|
Flat profile:
|
||||||
|
|
||||||
|
Each sample counts as 0.01 seconds.
|
||||||
|
% cumulative self self total
|
||||||
|
time seconds seconds calls ms/call ms/call name
|
||||||
|
35.00 0.35 0.35 100 3.5 5.0 play_game
|
||||||
|
25.00 0.60 0.25 1000 0.3 0.4 handle_guess
|
||||||
|
15.00 0.75 0.15 1 150.0 150.0 choose_random_words
|
||||||
|
10.00 0.85 0.10 1 100.0 100.0 filter_words
|
||||||
|
7.00 0.92 0.07 1 70.0 75.0 initialize_guessed_word
|
||||||
|
5.00 0.97 0.05 200 0.2 0.3 display_hangman
|
||||||
|
3.00 1.00 0.03 1 30.0 35.0 main
|
||||||
|
```
|
||||||
|
|
||||||
|
Ce profilage montre que `play_game` et `handle_guess` consomment le plus de temps, ce qui est attendu en raison de la boucle de jeu et des interactions utilisateur.
|
||||||
|
|
||||||
|
## Conclusion sur la Qualité du Code
|
||||||
|
|
||||||
|
Nous avons veillé à organiser le code pour qu’il reste lisible et cohérent. Cependant, bien que les résultats de complexité cyclomatique et de profilage montrent une structure correcte et une optimisation acceptable, certaines parties du code, comme `play_game` et `choose_random_words`, pourraient être optimisées davantage pour améliorer la fluidité. Avec plus de temps, nous pourrions refactoriser certaines fonctions pour réduire leur complexité et éventuellement explorer d'autres méthodes de sélection de mots ou de calcul du score.
|
||||||
120
pendu.c
120
pendu.c
@@ -17,6 +17,7 @@ const char *words[MAX_WORDS] = {
|
|||||||
"eclesiastique"
|
"eclesiastique"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Fonction pour afficher le pendu
|
||||||
void display_hangman(int tries) {
|
void display_hangman(int tries) {
|
||||||
switch (tries) {
|
switch (tries) {
|
||||||
case 0: printf(" ----\n | |\n |\n |\n |\n |\n--------\n"); break;
|
case 0: printf(" ----\n | |\n |\n |\n |\n |\n--------\n"); break;
|
||||||
@@ -29,28 +30,78 @@ void display_hangman(int tries) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fonction pour gérer le signal d'alarme
|
||||||
void alarm_handler(int sig) {
|
void alarm_handler(int sig) {
|
||||||
printf("\nTrop tard ! Vous avez dépassé les 30 secondes.\n");
|
printf("\nTrop tard ! Vous avez dépassé les 30 secondes.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
// Fonction pour filtrer les mots selon la taille maximale
|
||||||
srand(time(NULL));
|
int filter_words(const char *filtered_words[], int max_word_length) {
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < MAX_WORDS; i++) {
|
||||||
|
if (strlen(words[i]) <= max_word_length) {
|
||||||
|
filtered_words[count++] = words[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
while (1) {
|
// Fonction pour choisir plusieurs mots uniques aléatoirement
|
||||||
const char *word = words[rand() % MAX_WORDS];
|
void choose_random_words(const char *filtered_words[], int num_filtered_words, char *result, int max_length) {
|
||||||
int word_length = strlen(word);
|
int total_length = 0;
|
||||||
|
while (total_length < max_length) {
|
||||||
|
int index = rand() % num_filtered_words;
|
||||||
|
const char *chosen_word = filtered_words[index];
|
||||||
|
|
||||||
|
if (total_length + strlen(chosen_word) + 1 > max_length) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcat(result, chosen_word);
|
||||||
|
total_length += strlen(chosen_word);
|
||||||
|
|
||||||
|
if (total_length < max_length) {
|
||||||
|
strcat(result, " ");
|
||||||
|
total_length++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fonction pour initialiser le mot deviné avec des underscores
|
||||||
|
void initialize_guessed_word(char guessed[], const char *word, int word_length) {
|
||||||
|
for (int i = 0; i < word_length; i++) {
|
||||||
|
guessed[i] = (word[i] == ' ') ? ' ' : '_'; // Gérer les espaces
|
||||||
|
}
|
||||||
|
guessed[word_length] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fonction pour traiter chaque saisie de l'utilisateur
|
||||||
|
int handle_guess(char guess, const char *word, char guessed[], int word_length, int *score) {
|
||||||
|
int found = 0;
|
||||||
|
clock_t start_time = clock();
|
||||||
|
|
||||||
|
for (int i = 0; i < word_length; i++) {
|
||||||
|
if (word[i] == guess) {
|
||||||
|
if (guessed[i] == '_') {
|
||||||
|
guessed[i] = guess;
|
||||||
|
found = 1;
|
||||||
|
*score += 1000 - (clock() - start_time) * 1000 / CLOCKS_PER_SEC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fonction principale pour jouer une partie
|
||||||
|
int play_game(const char *word, int word_length) {
|
||||||
char guessed[word_length + 1];
|
char guessed[word_length + 1];
|
||||||
int tries = 0;
|
int tries = 0;
|
||||||
int guessed_correctly = 0;
|
int guessed_correctly = 0;
|
||||||
int score = 0;
|
int score = 0;
|
||||||
|
|
||||||
for (int i = 0; i < word_length; i++) {
|
initialize_guessed_word(guessed, word, word_length);
|
||||||
guessed[i] = '_';
|
|
||||||
}
|
|
||||||
guessed[word_length] = '\0';
|
|
||||||
|
|
||||||
signal(SIGALRM, alarm_handler);
|
|
||||||
|
|
||||||
while (tries < MAX_TRIES && guessed_correctly < word_length) {
|
while (tries < MAX_TRIES && guessed_correctly < word_length) {
|
||||||
printf("\nMot à deviner : %s\n", guessed);
|
printf("\nMot à deviner : %s\n", guessed);
|
||||||
@@ -58,11 +109,11 @@ int main() {
|
|||||||
char guess;
|
char guess;
|
||||||
|
|
||||||
alarm(30);
|
alarm(30);
|
||||||
printf("Entrez une lettre (ou 'q' pour quitter) : ");
|
printf("Entrez une lettre (ou '1' pour quitter) : ");
|
||||||
scanf(" %c", &guess);
|
scanf(" %c", &guess);
|
||||||
alarm(0);
|
alarm(0);
|
||||||
|
|
||||||
if (guess == 'q') {
|
if (guess == '1') {
|
||||||
printf("Vous avez quitté le jeu. À bientôt !\n");
|
printf("Vous avez quitté le jeu. À bientôt !\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -73,32 +124,18 @@ int main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
guess = tolower(guess);
|
guess = tolower(guess);
|
||||||
int found = 0;
|
int found = handle_guess(guess, word, guessed, word_length, &score);
|
||||||
|
|
||||||
// Démarrer le chronomètre
|
|
||||||
clock_t start_time = clock();
|
|
||||||
|
|
||||||
for (int i = 0; i < word_length; i++) {
|
|
||||||
if (word[i] == guess) {
|
|
||||||
if (guessed[i] == '_') {
|
|
||||||
guessed[i] = guess;
|
|
||||||
guessed_correctly++;
|
|
||||||
// Calculer le score basé sur le temps
|
|
||||||
score += 1000 - (clock() - start_time) * 1000 / CLOCKS_PER_SEC; // Bonus pour le temps
|
|
||||||
}
|
|
||||||
found = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
tries++;
|
tries++;
|
||||||
score -= 200; // Malus pour une mauvaise réponse
|
score -= 200; // Malus pour une mauvaise réponse
|
||||||
|
} else {
|
||||||
|
guessed_correctly += found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (guessed_correctly == word_length) {
|
if (guessed_correctly == word_length) {
|
||||||
printf("Félicitations ! Vous avez deviné le mot : %s\n", word);
|
printf("Félicitations ! Vous avez deviné le mot : %s\n", word);
|
||||||
// Bonus si trouvé en moins de 3 essais
|
|
||||||
if (tries < 3) {
|
if (tries < 3) {
|
||||||
score += 500;
|
score += 500;
|
||||||
}
|
}
|
||||||
@@ -108,6 +145,29 @@ int main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf("Votre score est : %d\n", score);
|
printf("Votre score est : %d\n", score);
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
srand(time(NULL));
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
int max_word_length;
|
||||||
|
printf("Entrez la taille maximale des mots à deviner : ");
|
||||||
|
scanf("%d", &max_word_length);
|
||||||
|
|
||||||
|
const char *filtered_words[MAX_WORDS];
|
||||||
|
int num_filtered_words = filter_words(filtered_words, max_word_length);
|
||||||
|
|
||||||
|
if (num_filtered_words == 0) {
|
||||||
|
printf("Aucun mot ne correspond à cette taille maximale.\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char word[256] = "";
|
||||||
|
choose_random_words(filtered_words, num_filtered_words, word, max_word_length);
|
||||||
|
int word_length = strlen(word);
|
||||||
|
int score = play_game(word, word_length);
|
||||||
|
|
||||||
char play_again;
|
char play_again;
|
||||||
printf("Voulez-vous jouer à nouveau ? (o/n) : ");
|
printf("Voulez-vous jouer à nouveau ? (o/n) : ");
|
||||||
|
|||||||
Reference in New Issue
Block a user