1
0

8 Commits

Author SHA1 Message Date
9aeb08ec7d Actualiser Readme.MD 2024-10-26 18:37:16 +02:00
d5cfc6041c Merge pull request 'ajout-difficulte' (#4) from ajout-difficulte into master
Reviewed-on: dariusy/TD3_DEV51_Qualite_Algo#4
2024-10-26 18:26:22 +02:00
TheSinay
c49ca7d7d1 fix 2024-10-24 15:49:13 +02:00
227f77d89d Actualiser pendu.c 2024-10-24 15:44:59 +02:00
TheSinay
11f44821bf a essayer 2024-10-24 15:30:23 +02:00
0a95de499b Merge pull request 'HugoD' (#2) from HugoD into master
Reviewed-on: dariusy/TD3_DEV51_Qualite_Algo#2
Reviewed-by: Yanis DARIUS <yanis.darius@etu.u-pec.fr>
2024-10-15 12:05:49 +02:00
3cd2277c5d Readme 2024-10-15 11:36:53 +02:00
48cccb4f17 Ajout chrono et score 2024-10-15 11:30:46 +02:00
7 changed files with 215 additions and 185 deletions

6
.vscode/launch.json vendored
View File

@@ -1,7 +1,7 @@
{ {
// Utilisez IntelliSense pour en savoir plus sur les attributs possibles. // Use IntelliSense to learn about possible attributes.
// Pointez pour afficher la description des attributs existants. // Hover to view descriptions of existing attributes.
// Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387 // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0", "version": "0.2.0",
"configurations": [] "configurations": []
} }

View File

@@ -1,7 +0,0 @@
{
"files.associations": {
"algorithm": "c",
"format": "c",
"cstdlib": "c"
}
}

24
.vscode/tasks.json vendored
View File

@@ -2,7 +2,7 @@
"tasks": [ "tasks": [
{ {
"type": "cppbuild", "type": "cppbuild",
"label": "C/C++: gcc générer le fichier actif", "label": "C/C++: gcc build active file",
"command": "/usr/bin/gcc", "command": "/usr/bin/gcc",
"args": [ "args": [
"-fdiagnostics-color=always", "-fdiagnostics-color=always",
@@ -17,11 +17,31 @@
"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
}, },
"detail": "Tâche générée par le débogueur." "detail": "Task generated by Debugger."
} }
], ],
"version": "2.0.0" "version": "2.0.0"

63
Readme.MD Normal file
View File

@@ -0,0 +1,63 @@
# Rapport de TP : Jeu du Pendu en C
## Fonctionnalités et Défis
### 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 lunicité 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 sintè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 quil 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.

View File

@@ -1,3 +0,0 @@
ex2 les functionnalité ont etait codé la mienne ne functionne pas pour l instant on passe
la creation de pull request

BIN
pendu

Binary file not shown.

297
pendu.c
View File

@@ -2,33 +2,22 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <unistd.h>
#include <signal.h>
#include <ctype.h>
#define MAX_WORDS 14 #define MAX_WORDS 14
#define MAX_TRIES 6 #define MAX_TRIES 6
#define MAX_WORDS_LENGTH 50
const char *words[MAX_WORDS] = { const char *words[MAX_WORDS] = {
"programmation", "programmation", "ordinateur", "langage", "jeu",
"ordinateur", "algorithmique", "fontainebleau", "koala",
"langage", "anticonstitutionnellement", "code", "canard",
"jeu", "gyroscope", "periclitation", "susurrer",
"algorithmique",
"fontainebleau",
"koala",
"anticonstitutionnellement",
"code",
"canard",
"gyroscope",
"periclitation",
"susurrer",
"eclesiastique" "eclesiastique"
}; };
// Prototypes des fonctions // Fonction pour afficher le pendu
char** selecte_words(int word_length, int* size);
char** word_merge(int word_length, int* size2);
char** merge_string_arrays(char** array1, char** array2, int size1, int size2);
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;
@@ -41,184 +30,152 @@ void display_hangman(int tries) {
} }
} }
int ask_word_length() { // Fonction pour gérer le signal d'alarme
int word_length; void alarm_handler(int sig) {
printf("\nTrop tard ! Vous avez dépassé les 30 secondes.\n");
printf("Veuillez entrer la longueur du mot souhaitée (entier positif) : "); exit(1);
while (scanf("%d", &word_length) != 1 || word_length <= 0) {
printf("Entrée invalide. Veuillez entrer un entier positif : ");
while (getchar() != '\n'); // vider le buffer
}
return word_length;
} }
char* difficult(int word_length) { // Fonction pour filtrer les mots selon la taille maximale
int size1 = 0, size2 = 0; int filter_words(const char *filtered_words[], int max_word_length) {
int count = 0;
char** selected_words = selecte_words(word_length, &size1);
if (selected_words == NULL) {
printf("Erreur lors de la sélection des mots\n");
return NULL;
}
char** merged_words = word_merge(word_length, &size2);
if (merged_words == NULL) {
printf("Erreur lors de la fusion des mots\n");
return NULL;
}
char** final_words = merge_string_arrays(selected_words, merged_words, size1, size2);
// Libérer la mémoire des tableaux intermédiaires
for (int i = 0; i < size1; i++) free(selected_words[i]);
for (int i = 0; i < size2; i++) free(merged_words[i]);
free(selected_words);
free(merged_words);
if (final_words == NULL) {
printf("Erreur lors de la fusion finale des mots\n");
return NULL;
}
// Sélectionner un mot aléatoire
char* chosen_word = final_words[rand() % (size1 + size2)];
// Libérer la mémoire du tableau final_words après avoir choisi un mot
for (int i = 0; i < size1 + size2; i++) {
free(final_words[i]);
}
free(final_words);
return chosen_word;
}
char** merge_string_arrays(char** array1, char** array2, int size1, int size2) {
int merged_size = size1 + size2;
char** merged_array = (char**)malloc(merged_size * sizeof(char*));
if (merged_array == NULL) {
printf("Erreur d'allocation de mémoire\n");
return NULL;
}
for (int i = 0; i < size1; i++) {
merged_array[i] = (char*)malloc((strlen(array1[i]) + 1) * sizeof(char));
if (merged_array[i] == NULL) {
printf("Erreur d'allocation de mémoire pour array1[%d]\n", i);
return NULL;
}
strcpy(merged_array[i], array1[i]);
}
for (int i = 0; i < size2; i++) {
merged_array[size1 + i] = (char*)malloc((strlen(array2[i]) + 1) * sizeof(char));
if (merged_array[size1 + i] == NULL) {
printf("Erreur d'allocation de mémoire pour array2[%d]\n", i);
return NULL;
}
strcpy(merged_array[size1 + i], array2[i]);
}
return merged_array;
}
char** selecte_words(int word_length, int* size) {
char** word_Selected = (char**)malloc(MAX_WORDS * sizeof(char*));
if (word_Selected == NULL) {
printf("Erreur d'allocation de mémoire\n");
return NULL;
}
*size = 0; // initialiser la taille à 0
for (int i = 0; i < MAX_WORDS && words[i][0] != '\0'; i++) {
if (strlen(words[i]) == word_length) {
word_Selected[*size] = (char*)malloc((strlen(words[i]) + 1) * sizeof(char));
if (word_Selected[*size] == NULL) {
printf("Erreur d'allocation de mémoire pour le mot sélectionné\n");
return NULL;
}
strcpy(word_Selected[*size], words[i]);
(*size)++;
}
}
return word_Selected;
}
char** word_merge(int word_length, int* size2) {
int max_combinations = MAX_WORDS * MAX_WORDS;
char** word_combinations = (char**)malloc(max_combinations * sizeof(char*));
if (word_combinations == NULL) {
printf("Erreur d'allocation de mémoire pour les combinaisons\n");
return NULL;
}
*size2 = 0;
for (int i = 0; i < MAX_WORDS; i++) { for (int i = 0; i < MAX_WORDS; i++) {
for (int j = 0; j < MAX_WORDS; j++) { if (strlen(words[i]) <= max_word_length) {
if (i != j && (strlen(words[i]) + strlen(words[j]) == word_length - 1)) { filtered_words[count++] = words[i];
word_combinations[*size2] = (char*)malloc((strlen(words[i]) + strlen(words[j]) + 2) * sizeof(char)); // +2 pour l'espace et '\0' }
if (word_combinations[*size2] == NULL) { }
printf("Erreur d'allocation de mémoire pour une combinaison\n"); return count;
return NULL; }
}
snprintf(word_combinations[*size2], strlen(words[i]) + strlen(words[j]) + 2, "%s %s", words[i], words[j]); // Fonction pour choisir plusieurs mots uniques aléatoirement
(*size2)++; void choose_random_words(const char *filtered_words[], int num_filtered_words, char *result, int max_length) {
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 word_combinations; return found;
} }
int main() { // Fonction principale pour jouer une partie
srand(time(NULL)); int play_game(const char *word, int word_length) {
char guessed[word_length + 1];
int tries = 0;
int guessed_correctly = 0;
int score = 0;
int word_length = ask_word_length(); initialize_guessed_word(guessed, word, word_length);
const char* word = difficult(word_length);
printf("le mot est :%s",word);
if (word == NULL) {
printf("Erreur : aucun mot disponible avec cette longueur.\n");
return 1;
}
int word_len = strlen(word); while (tries < MAX_TRIES && guessed_correctly < word_length) {
char guessed[word_len + 1];
int tries = 0, guessed_correctly = 0;
for (int i = 0; i < word_len; i++) guessed[i] = '_';
guessed[word_len] = '\0';
while (tries < MAX_TRIES && guessed_correctly < word_len) {
printf("\nMot à deviner : %s\n", guessed); printf("\nMot à deviner : %s\n", guessed);
display_hangman(tries); display_hangman(tries);
char guess; char guess;
printf("Entrez une lettre : ");
scanf(" %c", &guess);
int found = 0; alarm(30);
for (int i = 0; i < word_len; i++) { printf("Entrez une lettre (ou '1' pour quitter) : ");
if (word[i] == guess && guessed[i] == '_') { scanf(" %c", &guess);
guessed[i] = guess; alarm(0);
guessed_correctly++;
found = 1; if (guess == '1') {
} printf("Vous avez quitté le jeu. À bientôt !\n");
return 0;
} }
if (!isalpha(guess)) {
printf("Veuillez entrer une lettre valide.\n");
continue;
}
guess = tolower(guess);
int found = handle_guess(guess, word, guessed, word_length, &score);
if (!found) { if (!found) {
tries++; tries++;
score -= 200; // Malus pour une mauvaise réponse
} else {
guessed_correctly += found;
} }
} }
if (guessed_correctly == word_len) { 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);
if (tries < 3) {
score += 500;
}
} else { } else {
printf("Désolé, vous avez perdu. Le mot était : %s\n", word); printf("Désolé, vous avez perdu. Le mot était : %s\n", word);
display_hangman(MAX_TRIES); display_hangman(MAX_TRIES);
} }
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;
printf("Voulez-vous jouer à nouveau ? (o/n) : ");
scanf(" %c", &play_again);
if (tolower(play_again) != 'o') {
break;
}
}
return 0; return 0;
} }