Spécifications - Partie 5

Gestion des matchs et mise à jour des statistiques des joueurs
Objectifs
  • Implémenter la gestion complète des matchs entre joueurs
  • Simuler les résultats et mettre à jour les statistiques des joueurs en conséquence
  • Apporter votre touche personnelle avec des fonctionnalités bonus
Ressources
  • Cours sur les structures complexes en C
  • Documentation sur les algorithmes de mélange (Fisher-Yates)
  • Références sur la manipulation de tableaux et de pointeurs
Livrables attendus avant la séance 6

Fichiers à compléter :

headers/
└── match.h              # Prototypes des fonctions de gestion des matchs
src/
├── match.c              # Implémentation des fonctions de gestion des matchs
└── main.c               # Optionnel : menu interactif pour tester les matchs
Fonctionnalités bonus

Vous avez également de rajouter des fichiers sources supplémentaires pour les fonctionnalités bonus ou les améliorations que vous souhaitez implémenter. (Ces fichiers ne sont pas fournis dans le template et ne seront pas soumis aux tests)

1 Contexte

Les matchs dans Fork Knight rassemblent plusieurs joueurs (jusqu’à 12) et déterminent un classement final. Chaque joueur voit son spicyIndex et ses statistiques mises à jour en fonction de sa performance dans le match.

Dans cette partie, vous allez :

  1. Créer une structure Match pour gérer les participants et les résultats
  2. Implémenter des fonctions pour simuler un match, afficher les résultats et mettre à jour les statistiques des joueurs

2 Structure de données

Fichier : headers/match.h

#define MATCH_MAX_PLAYERS 12

typedef struct {
    Player ** players;   // participants
    int * results;       // results[r] = index du joueur classé r (0 = vainqueur)
    int numPlayers;      // nb de joueurs (<= 12)
} Match;

results stocke des indices vers players, déjà ordonnés du 1er au dernier.

3 Fonctions à implémenter

3.1 Création d’un match

Match * createMatch();

Description :

Alloue dynamiquement un match, alloue dynamiquement le tableau players avec une capacité de MATCH_MAX_PLAYERS, initialise le champ results à NULL, et le champ numPlayers à 0. La fonction retourne un pointeur vers le match créé, ou NULL en cas d’échec d’allocation.

3.2 Libération de la mémoire d’un match

void destroyMatch(Match* match);

Description :

Libère la mémoire allouée pour un match. Ne pas libérer les joueurs dans players, seulement le tableau lui-même et le tableau results s’il n’est pas NULL. Enfin, libère la structure Match.

3.3 Ajout d’un joueur au match

void addMatchPlayers(t_queue * queue, Match * match);

Description :

Cette fonction prend en paramètre une file queue et un un pointeur match. Elle ajoute des joueurs depuis la file à match->players jusqu’à ce que la file soit vide ou que match->numPlayers atteigne MATCH_MAX_PLAYERS. Pour chaque joueur retiré de la file, le champ inQueue du joueur est mis à 0. (Utilisez la fonction dequeue() pour retirer les joueurs de la file.)

3.4 Simulation du match

void simulateMatch(Match* match);

Description :

Simuler un match revient à remplir son tableau results. Cette fonction alloue dynamiquement le tableau results de taille numPlayers puis simule le match en le remplissant avec des valeurs allant de 0 à numPlayers - 1 dans un ordre aléatoire (permutation uniforme) en utilisant l’algorithme de Fisher-Yates pour garantir une distribution uniforme.

Attention :

Il est possible que simulateMatch() soit appelé plusieurs fois sur le même match, assurez-vous de libérer la mémoire précédemment allouée pour results avant d’en allouer une nouvelle.

Indications

Algorithme de Fisher-Yates : L’algorithme de Fisher-Yates permet de générer une permutation aléatoire d’un tableau. Voici un exemple d’implémentation en C :

void fisherYatesShuffle(int * array, int n) {
    for (int i = n - 1; i > 0; i--) {
        int j = rand() % (i + 1); // indice aléatoire entre 0 et i
        // Échange array[i] et array[j]
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}

Vous pouvez testez cette fonction avec un tableau d’entier pour vérifier qu’elle génère bien des permutations aléatoires.

3.5 Mise à jour des statistiques des joueurs après un match

void updatePlayerStats(Match * match);

Description :

Cette fonction met à jour les statistiques de chaque joueur dans match->players en fonction de leur position dans match->results. Pour chaque joueur p à la position r dans results (où r est le rang, 0 pour le vainqueur, 1 pour le second, etc.) :

  • Incrémente p->numGames de 1

  • Si le joueur est le vainqueur (r == 0), incrémente p->numWins de 1, sinon incrémente p->numLosses de 1

  • Incrémente p->spicyIndex d’une valeur calculée comme suit :

    gain à la position r = (n - r - 1) * (100 / (n - 1))

Exemple Pour un match avec 5 joueurs (n=5) :

  • Rang 0 (vainqueur) : gain = (5 - 0 - 1) * (100 / (5 - 1)) = 4 * 25 = 100
  • Rang 1 : gain = (5 - 1 - 1) * (100 / (5 - 1)) = 3 * 25 = 75
  • Rang 2 : gain = (5 - 2 - 1) * (100 / (5 - 1)) = 2 * 25 = 50
  • Rang 3 : gain = (5 - 3 - 1) * (100 / (5 - 1)) = 1 * 25 = 25
  • Rang 4 : gain = (5 - 4 - 1) * (100 / (5 - 1)) = 0 * 25 = 0

3.6 Affichage des informations du match

void displayMatchInfo(const Match* match);

Description :

Affiche les joueurs participants aux match avec la fonction displayPlayerMini(), ainsi que le nombre total de joueurs. La fonction doit afficher une erreur si le match est NULL.

Format suggéré :

========================================
           MATCH INFORMATION
========================================
Participants: 12
----------------------------------------
1. [ForkMaster   | Lvl: 10 | Spicy: 1200]
2. [SpoonyKnight | Lvl: 8  | Spicy: 950]
3. [KnifeLord    | Lvl: 15 | Spicy: 1500]
4. [RustyFork | Lvl: 3  | Spicy: 600]
5. [SteelBlade | Lvl: 12 | Spicy: 1000]
========================================

3.7 Affichage des résultats du match

void displayMatchResult(const Match* match);

Description :

Affiche les résultats du match dans l’ordre du classement final, en utilisant displayPlayerMini() pour chaque joueur. La fonction doit afficher une erreur si le match ou les résultats sont NULL.

Format suggéré :

========================================
           MATCH RESULTS
========================================
1. [KnifeLord | Lvl: 15 | Spicy: 1500]  (+100)
2. [ForkMaster | Lvl: 10 | Spicy: 1200] (+75)
3. [SpoonyKnight | Lvl: 8  | Spicy: 950]  (+50)
4. [RustyFork | Lvl: 3  | Spicy: 600]  (+25)
5. [SteelBlade | Lvl: 12 | Spicy: 1000] (+0)
========================================

3.8 Simulation complète d’un match

void launchMatch(t_queue * queue);

Description :

Cette fonction combine toutes les étapes précédentes pour simuler un match complet :

  1. Crée un match avec createMatch()
  2. Ajoute des joueurs depuis la file queue avec addMatchPlayers()
  3. Affiche les informations du match avec displayMatchInfo()
  4. Simule le match avec simulateMatch()
  5. Met à jour les statistiques des joueurs avec updatePlayerStats()
  6. Affiche les résultats du match avec displayMatchResult()
  7. Libère la mémoire du match avec destroyMatch()

Elle doit gérer les erreurs d’allocation mémoire et afficher des messages appropriés.

3.9 Lancement d’un match équilibré depuis une file de priorité

void launchBalancedMatch(t_priority_queue * p_queue);

Description :

Cette fonction est similaire à launchMatch(), mais elle utilise une file de priorité p_queue pour sélectionner les joueurs. Elle doit extraire jusqu’à MATCH_MAX_PLAYERS joueurs de la file de priorité en utilisant removeHighestPriority(), puis suivre les mêmes étapes que launchMatch() pour simuler et afficher le match.

4 Intégration au menu (optionnel)

Menu possible :


16. Former un match depuis une file 
17. Former un match depuis une file de priorité

5 Améliorations possibles pour aller plus loin (bonus)

5.1 Imaginer des Matchs par équipes

  • Diviser les 12 joueurs en 2 équipes de 6
  • Simuler un résultat d’équipe
  • Distribuer les gains selon l’équipe gagnante

5.2 Modes de jeu différents

  • Solo (12 joueurs, 1 gagnant)
  • Duo (6 équipes de 2)
  • Squad (4 équipes de 3)

5.3 Historique des matchs

  • Sauvegarder tous les matchs dans un fichier
  • Statistiques globales (taux de victoire, progression, etc.)

Bravo ! Vous avez maintenant un système de matchs complet et fonctionnel. 🎮⚔️