- Implémenter une file d’attente (queue) pour gérer les joueurs en attente de match
- Utiliser une liste chaînée pour stocker dynamiquement les joueurs
- Intégrer la file au système de matchmaking existant
- Cours sur les listes chaînées et les structures auto-référencées
- Documentation sur les files (FIFO : First In, First Out)
- Références sur la gestion de la mémoire avec les listes chaînées
Voici les nouveaux fichiers à completer :
headers/
└── list-utils.h # Déjà créé : prototypes des fonctions de file
src/
├── list-utils.c # À compléter : implémentation des fonctions de file
└── main.c # Optionnel : menu interactif pour tester la file
1 Contexte
Dans un système de matchmaking réel, les joueurs ne rejoignent pas tous en même temps. Ils arrivent progressivement et doivent attendre qu’un nombre suffisant de joueurs soit disponible pour former un match.
Une file d’attente (ou queue en anglais) est parfaite pour ce cas :
- FIFO : First In, First Out (premier arrivé, premier servi)
- Les joueurs rejoignent par la queue (arrière)
- Les joueurs sont retirés par la tête (avant)
Dans cette partie, vous allez :
- Créer une structure de liste chaînée pour représenter la file
- Implémenter les opérations de base :
enqueue(ajouter) etdequeue(retirer) - Intégrer cette file au système de matchmaking
2 Structures de données définies dans list-utils.h
2.1 Structure t_cell (celle de la liste chaînée)
typedef struct s_cell {
Player * value; // On stocker l'adresse du joueur
struct s_cell * next; // Pointeur vers la cellule suivante
} t_cell;2.2 Structure t_queue (file qui utilise les cellules)
typedef struct s_queue {
t_cell * head; // Pointeur vers le premier élément
t_cell * tail; // Pointeur vers le dernier élément
} t_queue;La file d’attente est en réalité une liste chaînée de type head-tail où chaque cellule stockant un joueur rejoint la file en fin de liste et sort de la file en début de liste.
3 Fonctions à implémenter
Certaines des fonctions ont déjà été présentées en cours, il vous suffit de les adapter à ce contexte.
3.1 Création d’une cellule
t_cell* createCell(Player* player);Description :
Alloue dynamiquement une nouvelle cellule dont le champ value est initialisé avec le pointeur player et next à NULL. Retourne un pointeur vers la cellule créée ou NULL en cas d’échec d’allocation.
3.2 Libération d’une cellule
void destroyCell(t_cell* cell);Description :
Libère la mémoire allouée pour la cellule pointée par cell. Ne libère PAS le joueur contenu dans la cellule. Ne fait rien si cell est NULL.
- Cette fonction ne libère que la cellule, pas le
Player *qu’elle contient - Le joueur sera libéré ailleurs (dans le tableau principal ou après utilisation)
3.3 Création d’une file vide
t_queue * createQueue();Description :
Alloue dynamiquement une nouvelle file et l’initialise comme une file vide c’est à dire une file dont les champs head et tail sont initialisés à NULL. Retourne un pointeur vers la file créée ou NULL en cas d’échec d’allocation.
3.4 Vérification si la file est vide
int isQueueEmpty(t_queue* queue);Description :
Vérifie si la file queue est vide. Retourne 1 si vide, 0 sinon.
3.5 Ajout d’un joueur à la file
void enqueue(t_queue * queue, Player * player);Description :
Ajoute le joueur player à la fin de la file queue. Cette fonction crée donc une nouvelle cellule dont le champ value est initialisé avec player puis l’ajoute à la fin de la liste chaînée. Elle met à jour le champ tail de la file en conséquence et met à jour le champ inQueue du joueur à 1.
Si la file est vide, la nouvelle cellule devient à la fois head et tail
3.6 Retrait d’un joueur de la file
Player * dequeue(t_queue* queue);Description :
Retire et retourne le premier joueur de la file. Sauvegarde le pointeur du joueur, avance head, libère la cellule avec free() et marque player->inQueue = 0. Retourne le pointeur vers le joueur retiré ou NULL si la file est vide.
- Toujours vérifier que la file n’est pas vide avant de retirer
- Faire attention au cas où la file ne contient qu’une seule cellule
- Ne pas oublier de marquer
player->inQueue = 0 - Libérer la cellule mais PAS le joueur
3.7 Affichage de la file
void displayQueue(t_queue* queue);Description :
Affiche tous les joueurs dans la file (du premier au dernier) avec displayPlayerMini(). Affiche un en-tête et le nombre total de joueurs.
Format suggéré :
======= File d'attente =======
1. [Player1 | Lvl: 10 | SI: 1200]
2. [Player2 | Lvl: 8 | SI: 950]
Total: 2 joueurs en attente
==============================
3.8 Retrait de la cellule de tête (fonction auxiliaire)
t_cell * removeHead(t_queue * queue);Description :
Cette fonction est utile pour la libération de la file d’attende. Elle retire et retourne la première cellule de la file (sans libérer sa mémoire). Marque player->inQueue = 0. Retourne la cellule retirée ou NULL si la file est vide.
3.9 Destruction de la file
void destroyQueue(t_queue * queue);Description :
Libère toute la mémoire de la file (les cellules ET la structure de file, mais PAS les joueurs). Utilise removeHead() et destroyCell() pour vider la file puis libère toute la mémoire allouée pour queue.
5 Débogage courant
| Problème courant | Cause possible |
|---|---|
Segmentation fault lors de dequeue |
Tentative de retrait sur une file vide |
tail pointe vers une cellule supprimée |
Oubli de mettre tail à NULL quand on retire le dernier élément |
| Joueur ajouté 2 fois | Pas de vérification de inQueue |
| Affichage incorrect de la file | Mauvaise mise à jour des pointeurs head et tail |
| Fuite mémoire | Oubli de libérer les cellules lors de la destruction de la file |