Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
9aeb08ec7d | |||
d5cfc6041c | |||
|
c49ca7d7d1 | ||
227f77d89d | |||
|
11f44821bf | ||
0a95de499b | |||
3cd2277c5d | |||
48cccb4f17 |
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": []
|
||||
}
|
48
.vscode/tasks.json
vendored
Normal file
48
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"tasks": [
|
||||
{
|
||||
"type": "cppbuild",
|
||||
"label": "C/C++: gcc build active file",
|
||||
"command": "/usr/bin/gcc",
|
||||
"args": [
|
||||
"-fdiagnostics-color=always",
|
||||
"-g",
|
||||
"${file}",
|
||||
"-o",
|
||||
"${fileDirname}/${fileBasenameNoExtension}"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${fileDirname}"
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$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": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"detail": "Task generated by Debugger."
|
||||
}
|
||||
],
|
||||
"version": "2.0.0"
|
||||
}
|
63
Readme.MD
Normal file
63
Readme.MD
Normal 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 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.
|
163
pendu.c
163
pendu.c
@ -2,27 +2,22 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define MAX_WORDS 14
|
||||
#define MAX_TRIES 6
|
||||
|
||||
const char *words[MAX_WORDS] = {
|
||||
"programmation",
|
||||
"ordinateur",
|
||||
"langage",
|
||||
"jeu",
|
||||
"algorithmique",
|
||||
"fontainebleau",
|
||||
"koala",
|
||||
"anticonstitutionnellement",
|
||||
"code",
|
||||
"canard",
|
||||
"gyroscope",
|
||||
"periclitation",
|
||||
"susurrer",
|
||||
"programmation", "ordinateur", "langage", "jeu",
|
||||
"algorithmique", "fontainebleau", "koala",
|
||||
"anticonstitutionnellement", "code", "canard",
|
||||
"gyroscope", "periclitation", "susurrer",
|
||||
"eclesiastique"
|
||||
};
|
||||
|
||||
// Fonction pour afficher le pendu
|
||||
void display_hangman(int tries) {
|
||||
switch (tries) {
|
||||
case 0: printf(" ----\n | |\n |\n |\n |\n |\n--------\n"); break;
|
||||
@ -35,48 +30,152 @@ void display_hangman(int tries) {
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
srand(time(NULL));
|
||||
const char *word = words[rand() % MAX_WORDS];
|
||||
int word_length = strlen(word);
|
||||
char guessed[word_length];
|
||||
int tries = 0;
|
||||
int guessed_correctly = 0;
|
||||
// Fonction pour gérer le signal d'alarme
|
||||
void alarm_handler(int sig) {
|
||||
printf("\nTrop tard ! Vous avez dépassé les 30 secondes.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Fonction pour filtrer les mots selon la taille maximale
|
||||
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;
|
||||
}
|
||||
|
||||
// Fonction pour choisir plusieurs mots uniques aléatoirement
|
||||
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] = '_';
|
||||
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];
|
||||
int tries = 0;
|
||||
int guessed_correctly = 0;
|
||||
int score = 0;
|
||||
|
||||
initialize_guessed_word(guessed, word, word_length);
|
||||
|
||||
while (tries < MAX_TRIES && guessed_correctly < word_length) {
|
||||
printf("\nMot à deviner : %s\n", guessed);
|
||||
display_hangman(tries);
|
||||
char guess;
|
||||
printf("Entrez une lettre : ");
|
||||
scanf(" %c", &guess);
|
||||
int found = 0;
|
||||
|
||||
for (int i = 0; i < word_length; i++) {
|
||||
if (word[i] == guess) {
|
||||
if (guessed[i] == '_') {
|
||||
guessed[i] = guess;
|
||||
guessed_correctly++;
|
||||
}
|
||||
found = 1;
|
||||
}
|
||||
alarm(30);
|
||||
printf("Entrez une lettre (ou '1' pour quitter) : ");
|
||||
scanf(" %c", &guess);
|
||||
alarm(0);
|
||||
|
||||
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) {
|
||||
tries++;
|
||||
score -= 200; // Malus pour une mauvaise réponse
|
||||
} else {
|
||||
guessed_correctly += found;
|
||||
}
|
||||
}
|
||||
|
||||
if (guessed_correctly == word_length) {
|
||||
printf("Félicitations ! Vous avez deviné le mot : %s\n", word);
|
||||
if (tries < 3) {
|
||||
score += 500;
|
||||
}
|
||||
} else {
|
||||
printf("Désolé, vous avez perdu. Le mot était : %s\n", word);
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user