Bientot fini manque seulement les images

This commit is contained in:
lecointre
2025-12-04 18:48:28 +01:00
parent b1fcb88c58
commit a774b48ee9
19 changed files with 85 additions and 216 deletions
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+2 -6
View File
@@ -1,12 +1,8 @@
/* src/defs.h
* Définitions des constantes globales (taille de fenêtre, cycles).
* Inclus par main.c et game_view.c.
*/
#ifndef DEFS_H
#define DEFS_H
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define REFRESH_CYCLE 50000L /* 50 ms */
#define REFRESH_CYCLE 50000L
#endif /* DEFS_H */
#endif
+6 -29
View File
@@ -1,38 +1,31 @@
/* src/game_logic.c */
#include "game_logic.h"
#include "utils.h"
#include <stdlib.h>
#include <stdio.h>
/* --- Utilitaires de positionnement --- */
/* Convertit un index 1D en coordonnées 2D */
static void index_to_coords(int index, int cols, int *r, int *c)
{
*r = index / cols;
*c = index % cols;
}
/* Trouve les indices des tuiles adjacentes à la case vide */
static int find_adjacent_indices(int idx, int rows, int cols, int *out_indices)
{
int r = idx / cols;
int c = idx % cols;
int n = 0;
if (r > 0) out_indices[n++] = (r - 1) * cols + c; /* Haut */
if (r < rows - 1) out_indices[n++] = (r + 1) * cols + c; /* Bas */
if (c > 0) out_indices[n++] = r * cols + (c - 1); /* Gauche */
if (c < cols - 1) out_indices[n++] = r * cols + (c + 1); /* Droite */
if (r > 0) out_indices[n++] = (r - 1) * cols + c;
if (r < rows - 1) out_indices[n++] = (r + 1) * cols + c;
if (c > 0) out_indices[n++] = r * cols + (c - 1);
if (c < cols - 1) out_indices[n++] = r * cols + (c + 1);
return n;
}
/* --- Fonctions publiques --- */
/* Initialise le jeu à l'état résolu et alloue la mémoire */
void game_init(game_state_t *state, int rows, int cols, tile_t **tiles)
{
int num_tiles = rows * cols;
@@ -44,7 +37,6 @@ void game_init(game_state_t *state, int rows, int cols, tile_t **tiles)
state->is_solved = 1;
state->all_tiles = tiles;
/* Allocation dynamique de la permutation (malloc) */
state->permutation = (int *)malloc(num_tiles * sizeof(int));
if (state->permutation == NULL) {
@@ -52,27 +44,22 @@ void game_init(game_state_t *state, int rows, int cols, tile_t **tiles)
return;
}
/* Remplissage à l'état résolu : IDs 0, 1, 2, ... N-2 */
for (i = 0; i < num_tiles - 1; i++) {
state->permutation[i] = i;
}
/* La dernière case est la case vide (-1) */
state->permutation[num_tiles - 1] = -1;
state->empty_index = num_tiles - 1;
}
/* Libère la mémoire allouée par game_init */
void game_free(game_state_t *state)
{
if (state->permutation != NULL) {
free(state->permutation);
state->permutation = NULL;
}
/* Note: tiles sont libérés par images_free_tiles dans main.c */
}
/* Vérifie si la tuile peut bouger (adjacence) */
int game_can_move(const game_state_t *state, int index_to_move)
{
int r_tile, c_tile;
@@ -84,14 +71,12 @@ int game_can_move(const game_state_t *state, int index_to_move)
index_to_coords(index_to_move, state->cols, &r_tile, &c_tile);
index_to_coords(state->empty_index, state->cols, &r_empty, &c_empty);
/* Test d'adjacence géographique (manhattan distance = 1) */
if (abs_val(r_tile - r_empty) + abs_val(c_tile - c_empty) == 1) {
return 1;
}
return 0;
}
/* Déplace la tuile vers la case vide si possible */
int game_move_tile(game_state_t *state, int index_to_move)
{
int temp_tile_id;
@@ -100,33 +85,27 @@ int game_move_tile(game_state_t *state, int index_to_move)
return 0;
}
/* Échange des valeurs (swap) */
temp_tile_id = state->permutation[index_to_move];
state->permutation[index_to_move] = state->permutation[state->empty_index];
state->permutation[state->empty_index] = temp_tile_id;
/* Mise à jour de la nouvelle position de la case vide */
state->empty_index = index_to_move;
/* Mise à jour des compteurs */
state->moves++;
state->is_solved = game_is_solved(state);
return 1;
}
/* Vérifie si le plateau est dans l'état résolu */
int game_is_solved(const game_state_t *state)
{
int num_tiles = state->rows * state->cols;
int i;
/* La case vide doit être en dernière position (-1) */
if (state->permutation[num_tiles - 1] != -1) {
return 0;
}
/* Toutes les autres tuiles doivent être dans l'ordre (ID = Position) */
for (i = 0; i < num_tiles - 1; i++) {
if (state->permutation[i] != i) {
return 0;
@@ -136,7 +115,6 @@ int game_is_solved(const game_state_t *state)
return 1;
}
/* Mélange garanti solvable par N mouvements aléatoires */
void game_shuffle_safe(game_state_t *state, int steps)
{
int prev_move = -1;
@@ -148,15 +126,14 @@ void game_shuffle_safe(game_state_t *state, int steps)
for (i = 0; i < steps; i++) {
n_choices = find_adjacent_indices(state->empty_index, state->rows, state->cols, choices);
/* Choisir une tuile adjacente au hasard, sans revenir en arrière immédiatement */
do {
pick_index = choices[random_int(n_choices)];
} while (n_choices > 1 && pick_index == prev_move);
/* Déplacer la tuile (utilise la logique de déplacement) */
game_move_tile(state, pick_index);
/* L'ancienne position vide est la tuile qui vient d'être déplacée (pour la prochaine itération) */
prev_move = pick_index;
}
+6 -15
View File
@@ -1,38 +1,29 @@
/* src/game_logic.h
* Définition de l'état du plateau et des prototypes pour le moteur de jeu.
*/
#ifndef GAME_LOGIC_H
#define GAME_LOGIC_H
#include "images.h" /* Nécessaire pour le type tile_t */
#include "images.h"
/* Structure de l'état complet du Taquin */
typedef struct {
int rows;
int cols;
/* Tableau 1D alloué dynamiquement pour la permutation */
int *permutation;
int empty_index; /* Position actuelle (index 1D) de la case vide */
unsigned long moves; /* Compteur de coups */
int is_solved; /* 1 si gagné */
int empty_index;
unsigned long moves;
int is_solved;
tile_t **all_tiles; /* Les tuiles découpées */
tile_t **all_tiles;
} game_state_t;
/* Prototypes des fonctions publiques */
void game_init(game_state_t *state, int rows, int cols, tile_t **tiles);
void game_free(game_state_t *state);
/* Logique de jeu */
int game_move_tile(game_state_t *state, int index_to_move);
int game_can_move(const game_state_t *state, int index_to_move);
/* Solvabilité */
int game_is_solved(const game_state_t *state);
void game_shuffle_safe(game_state_t *state, int steps);
#endif /* GAME_LOGIC_H */
#endif
+42 -37
View File
@@ -1,7 +1,3 @@
/* src/game_view.c
* Implémentation du rendu graphique du plateau et de la boucle d'interaction.
*/
#include "game_view.h"
#include <graph.h>
#include <stdio.h>
@@ -9,21 +5,16 @@
extern int _X;
extern int _Y;
#define MARGIN 50 /* Marge autour du plateau */
#define MARGIN 50
/* --- Fonctions Utilitaires Privées --- */
/* Vérifie si un clic est sur une tuile donnée */
static int is_in_tile_rect(int x_click, int y_click, int tile_x, int tile_y, int tile_w, int tile_h)
{
return (x_click >= tile_x && x_click <= tile_x + tile_w &&
y_click >= tile_y && y_click <= tile_y + tile_h);
}
/* --- Fonctions de Rendu et de Logique --- */
/* Dessine le plateau de jeu */
void game_render(const game_state_t *state)
{
int i, r, c;
@@ -32,13 +23,11 @@ void game_render(const game_state_t *state)
EffacerEcran(C_FOND);
/* On prend la taille des tuiles calculée lors du découpage */
int tile_display_w = state->all_tiles[0]->width;
int tile_display_h = state->all_tiles[0]->height;
ChoisirCouleurDessin(C_BORDURE);
/* Boucle sur toutes les cases du plateau */
for (i = 0; i < state->rows * state->cols; i++) {
int tile_id = state->permutation[i];
int x_pos, y_pos;
@@ -46,24 +35,20 @@ void game_render(const game_state_t *state)
r = i / state->cols;
c = i % state->cols;
/* Position d'affichage sur l'écran */
x_pos = MARGIN + c * tile_display_w;
y_pos = MARGIN + r * tile_display_h;
if (tile_id != -1) { /* C'est une tuile (non vide) */
if (tile_id != -1) {
tile_t *current_tile = state->all_tiles[tile_id];
/* ChargerImage(fichier, x_dst, y_dst, x_src, y_src, l, h) */
ChargerImage(current_tile->path,
x_pos, y_pos,
current_tile->src_x, current_tile->src_y,
current_tile->width, current_tile->height);
/* Dessine la bordure */
DessinerRectangle(x_pos, y_pos, tile_display_w, tile_display_h);
} else {
/* Dessine la case vide en couleur distincte (jaune) */
ChoisirCouleurDessin(CouleurParNom("yellow"));
RemplirRectangle(x_pos, y_pos, tile_display_w, tile_display_h);
ChoisirCouleurDessin(C_BORDURE);
@@ -71,20 +56,43 @@ void game_render(const game_state_t *state)
}
}
/* Affichage du compteur de coups */
if (state->all_tiles != NULL && state->all_tiles[0] != NULL) {
tile_t *sample_tile = state->all_tiles[0];
int model_size = 150;
int model_x = WINDOW_WIDTH - MARGIN - model_size;
int model_y = MARGIN;
ChoisirCouleurDessin(CouleurParNom("white"));
RemplirRectangle(model_x - 5, model_y - 5, model_size + 10, model_size + 10);
ChoisirCouleurDessin(CouleurParNom("black"));
ChargerImage(sample_tile->path,
model_x, model_y,
0, 0,
model_size, model_size);
}
char buffer[100];
sprintf(buffer, "Coups: %lu", state->moves);
EcrireTexte(MARGIN, WINDOW_HEIGHT - 30, buffer, 1);
/* Affichage de la victoire */
int btn_x = WINDOW_WIDTH - 200;
int btn_y = WINDOW_HEIGHT - 60;
ChoisirCouleurDessin(CouleurParNom("orange"));
RemplirRectangle(btn_x, btn_y, 150, 40);
ChoisirCouleurDessin(CouleurParNom("black"));
EcrireTexte(btn_x + 10, btn_y + 25, "MENU (R)", 1);
if (state->is_solved) {
ChoisirCouleurDessin(CouleurParNom("red"));
EcrireTexte(WINDOW_WIDTH / 2 - 100, WINDOW_HEIGHT / 2, "BRAVO ! PRESSEZ UNE TOUCHE.", 2);
}
}
/* Gère les entrées (clic/clavier) et la boucle principale du jeu */
void game_loop(game_state_t *state)
{
unsigned long next_update = Microsecondes() + REFRESH_CYCLE;
@@ -92,7 +100,6 @@ void game_loop(game_state_t *state)
while (go_on && !state->is_solved)
{
/* Rendu et rafraîchissement */
if (Microsecondes() > next_update)
{
game_render(state);
@@ -100,7 +107,6 @@ void game_loop(game_state_t *state)
next_update = Microsecondes() + REFRESH_CYCLE;
}
/* Gestion des événements Souris */
if (SourisCliquee())
{
int i;
@@ -109,7 +115,11 @@ void game_loop(game_state_t *state)
int tile_w = state->all_tiles[0]->width;
int tile_h = state->all_tiles[0]->height;
/* Parcourir toutes les tuiles pour voir laquelle a été cliquée */
if (is_in_tile_rect(x_click, y_click, WINDOW_WIDTH - 200, WINDOW_HEIGHT - 60, 150, 40)) {
go_on = 0;
break;
}
for (i = 0; i < state->rows * state->cols; i++) {
int r = i / state->cols;
int c = i % state->cols;
@@ -118,14 +128,12 @@ void game_loop(game_state_t *state)
int y_pos = MARGIN + r * tile_h;
if (is_in_tile_rect(x_click, y_click, x_pos, y_pos, tile_w, tile_h)) {
/* Tenter de déplacer la tuile cliquée (indice i) */
game_move_tile(state, i);
break;
}
}
}
/* Gestion des événements Clavier */
if (ToucheEnAttente()) {
int key = Touche();
@@ -134,48 +142,45 @@ void game_loop(game_state_t *state)
int empty_c = state->empty_index % state->cols;
if (key == XK_Escape) {
exit(EXIT_SUCCESS);
}
else if (key == 'r' || key == 'R') {
go_on = 0;
}
/* CORRECTION FINALE : Inverse le mapping pour la perception intuitive */
else if (key == XK_Up) {
/* Flèche HAUT : Déplace la tuile en BAS (r + 1) vers le vide (r) */
target_index = (empty_r + 1) * state->cols + empty_c;
} else if (key == XK_Down) {
/* Flèche BAS : Déplace la tuile en HAUT (r - 1) vers le vide (r) */
target_index = (empty_r - 1) * state->cols + empty_c;
}
else if (key == XK_Left) {
/* Flèche GAUCHE : Déplace la tuile de DROITE (c + 1) vers le vide (c) */
target_index = empty_r * state->cols + (empty_c + 1);
} else if (key == XK_Right) {
/* Flèche DROITE : Déplace la tuile de GAUCHE (c - 1) vers le vide (c) */
target_index = empty_r * state->cols + (empty_c - 1);
}
/* Tenter le mouvement s'il y a une cible */
if (target_index != -1) {
game_move_tile(state, target_index);
}
}
}
/* Si la boucle est terminée par la victoire ou ESC */
if (state->is_solved) {
game_render(state);
CopierZone(0, 0, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0);
printf("BRAVO ! Partie terminee en %lu coups. Pressez 'N' pour Nouvelle Partie ou 'Q' pour Quitter.\n", state->moves);
printf("BRAVO ! Partie terminee en %lu coups.\n", state->moves);
/* Gère le choix de rejouer/quitter après la victoire */
while (1) {
if (ToucheEnAttente()) {
int key = Touche();
if (key == 'n' || key == 'N') {
return; /* Retourne au main pour relancer le menu */
return;
} else if (key == 'q' || key == 'Q') {
exit(EXIT_SUCCESS); /* Quitte le programme entier */
exit(EXIT_SUCCESS);
}
}
Microsecondes();
}
}
return;
}
+3 -6
View File
@@ -1,16 +1,13 @@
/* src/game_view.h
* Définitions du module de la vue du plateau de jeu.
*/
#ifndef GAME_VIEW_H
#define GAME_VIEW_H
#include "game_logic.h"
#include "defs.h"
/* Dessine le plateau de jeu, les tuiles à leur position actuelle, et le compteur de coups. */
void game_render(const game_state_t *state);
/* Gère la boucle principale du jeu, les événements (clics/clavier) et les rafraîchissements. */
void game_loop(game_state_t *state);
#endif /* GAME_VIEW_H */
#endif
+2 -16
View File
@@ -1,26 +1,19 @@
/* src/images.c
* Gère le découpage de l'image source en tuiles (structures tile_t).
*/
#include "images.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Stocke les chemins des images disponibles (doit correspondre à NUM_IMAGES dans menu_view.h) */
static const char *IMAGE_PATHS[] = {
"assets/image1.png",
"assets/image2.png",
"assets/image3.png"
};
/* Retourne les informations de l'image choisie */
image_source_t get_image_source(int selected_index)
{
image_source_t src;
/* TODO: Normalement, il faudrait charger l'image ici pour obtenir la VRAIE taille (width/height)
avec une fonction IUT. Pour l'instant, on simule une taille fixe. */
src.width = 750;
src.height = 450;
@@ -32,7 +25,6 @@ image_source_t get_image_source(int selected_index)
return src;
}
/* Crée un tableau de tuiles découpées (allocation dynamique de structures) */
tile_t **images_slice(image_source_t img_src, int rows, int cols)
{
int num_tiles = rows * cols;
@@ -40,25 +32,20 @@ tile_t **images_slice(image_source_t img_src, int rows, int cols)
tile_t **tiles;
int i, j, id = 0;
/* Calcul des dimensions d'une tuile */
tile_w = img_src.width / cols;
tile_h = img_src.height / rows;
/* Allocation du tableau de pointeurs vers les structures de tuiles */
tiles = (tile_t **) calloc(num_tiles, sizeof(tile_t *)); /* calloc pour initialiser à NULL */
tiles = (tile_t **) calloc(num_tiles, sizeof(tile_t *));
if (tiles == NULL) return NULL;
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
/* Allocation de la structure de tuile */
tile_t *t = (tile_t *) malloc(sizeof(tile_t));
if (t == NULL) {
/* Gérer l'échec de malloc */
images_free_tiles(tiles, id);
return NULL;
}
/* Remplissage des champs (coordonnées de découpe) */
strcpy(t->path, img_src.path);
t->width = tile_w;
t->height = tile_h;
@@ -73,7 +60,6 @@ tile_t **images_slice(image_source_t img_src, int rows, int cols)
return tiles;
}
/* Libère la mémoire allouée par images_slice */
void images_free_tiles(tile_t **tiles, int num_tiles)
{
int i;
+2 -13
View File
@@ -1,35 +1,24 @@
/* src/images.h
* Définition des structures pour la gestion et le découpage de l'image.
*/
#ifndef IMAGES_H
#define IMAGES_H
/* Une tuile est une partie de l'image source */
typedef struct {
char path[30];
/* Coordonnées de la tuile DANS l'image source */
int src_x, src_y;
int width, height;
int id; /* ID unique, de 0 à (L*C - 2) */
int id;
} tile_t;
/* Structure pour l'image source complète */
typedef struct {
int width;
int height;
char path[30];
} image_source_t;
/* Prototypes */
/* Obtient les informations de l'image choisie */
image_source_t get_image_source(int selected_index);
/* Crée et retourne un tableau de tuiles (découpage) */
tile_t **images_slice(image_source_t img_src, int rows, int cols);
/* Libère la mémoire allouée par images_slice (selon la règle free/malloc) */
void images_free_tiles(tile_t **tiles, int num_tiles);
#endif /* IMAGES_H */
#endif
+9 -27
View File
@@ -1,8 +1,3 @@
/* src/main.c
* Point d'entrée du programme Taquin.
* Gère la boucle principale des événements et la transition de vue (Menu -> Jeu).
*/
#include "menu_view.h"
#include "game_logic.h"
#include "images.h"
@@ -17,23 +12,18 @@ int main(void)
{
menu_state_t menu_state;
unsigned long next_update;
int play_again = 1;
/* 1. Initialisation de l'environnement IUT */
InitialiserGraphique();
CreerFenetre(10, 10, WINDOW_WIDTH, WINDOW_HEIGHT);
srand((unsigned int)time(NULL));
/* Grande boucle pour rejouer (retourne au menu) */
do {
play_again = 0; /* Réinitialisation pour cette tentative */
/* 2. Phase de Configuration (Menu) */
menu_init(&menu_state);
next_update = Microsecondes() + REFRESH_CYCLE;
while (menu_state.ready_to_play == 0 && menu_state.ready_to_play != -1)
while (menu_state.ready_to_play == 0)
{
if (Microsecondes() > next_update)
{
@@ -46,9 +36,10 @@ int main(void)
menu_handle_mouse_click(&menu_state);
}
menu_handle_key(&menu_state);
if (menu_state.ready_to_play == -1) goto end_program;
}
/* Sortie du menu par validation */
if (menu_state.ready_to_play == 1) {
image_source_t img_src;
@@ -56,7 +47,6 @@ int main(void)
game_state_t game_state;
int num_tiles;
/* Préparation des données et initialisation du moteur de jeu */
img_src = get_image_source(menu_state.selected_image);
tiles = images_slice(img_src, menu_state.rows, menu_state.cols);
@@ -69,28 +59,20 @@ int main(void)
game_init(&game_state, menu_state.rows, menu_state.cols, tiles);
game_shuffle_safe(&game_state, 500);
printf("DEBUG: Jeu prêt. Grille %d x %d melangee.\n",
printf("DEBUG: Jeu prêt. Grille %d x %d melangee. Lancement de la partie...\n",
game_state.rows, game_state.cols);
/* Lancement de la BOUCLE DE JEU */
game_loop(&game_state);
/* Après game_loop (si la boucle est sortie par victoire ou ESC) */
/* S'assurer que le joueur veut rejouer */
if (ToucheEnAttente()) {
int final_key = Touche();
if (final_key == 'n' || final_key == 'N') {
play_again = 1; /* Remet la grande boucle en marche */
}
}
/* Nettoyage des ressources allouées */
images_free_tiles(tiles, num_tiles);
game_free(&game_state);
}
} while (play_again == 1);
} while (1);
end_program:;
FermerGraphique();
return EXIT_SUCCESS;
+4 -43
View File
@@ -1,16 +1,8 @@
/* src/menu_view.c
* Implémentation complète de l'interface de configuration (Menu)
* Utilise la bibliothèque graphique IUT (graph.h).
*/
#include "menu_view.h"
#include <graph.h>
#include <stdio.h> /* Pour sprintf */
#include <stdlib.h> /* Pour les calculs simples */
#include <stdio.h>
#include <stdlib.h>
/* --- DÉCLARATIONS (CONSTANTES ET VARIABLES GLOBALES IUT) --- */
/* Constantes de positionnement */
#define IMG_PREVIEW_SIZE 150
#define IMG_START_X 50
#define IMG_START_Y 150
@@ -18,28 +10,23 @@
#define BUTTON_SIZE 30
#define DIM_START_Y 350
/* Variables globales de la bibliothèque IUT pour la souris */
extern int _X;
extern int _Y;
/* --- PROTOTYPES DES UTILITAIRES PRIVÉS (OBLIGATOIRE EN C89) --- */
static int is_in_rect(int x_click, int y_click, int rx, int ry, int rw, int rh);
static void draw_button(int x, int y, const char *text, couleur C_BG);
static void draw_text_centered(int x, int y, int w, int h, const char *text, int size);
/* --- IMPLÉMENTATION DES FONCTIONS PUBLIQUES (.h) --- */
/* Initialise l'état du menu */
void menu_init(menu_state_t *state)
{
state->selected_image = 0; /* Image 1 sélectionnée par défaut */
state->selected_image = 0;
state->rows = MIN_DIMENSION;
state->cols = MIN_DIMENSION;
state->ready_to_play = 0;
}
/* Dessine l'écran de configuration du menu */
void menu_render(const menu_state_t *state)
{
int i;
@@ -53,11 +40,9 @@ void menu_render(const menu_state_t *state)
EffacerEcran(C_FOND);
ChoisirCouleurDessin(C_TEXTE);
/* 1. Titre et Section Image */
EcrireTexte(IMG_START_X, 50, "CONFIGURATION DU JEU TAQUIN", 2);
EcrireTexte(IMG_START_X, 100, "1. Choisir l'image :", 1);
/* BOUCLE : Affichage des 3 aperçus d'images */
for (i = 0; i < NUM_IMAGES; i++) {
int x = IMG_START_X + i * IMG_SPACING;
int y = IMG_START_Y;
@@ -65,10 +50,8 @@ void menu_render(const menu_state_t *state)
sprintf(path, "assets/image%d.png", i + 1);
/* Affiche l'image */
ChargerImage(path, x, y, 0, 0, IMG_PREVIEW_SIZE, IMG_PREVIEW_SIZE);
/* Encadrement si sélectionné */
if (state->selected_image == i) {
ChoisirCouleurDessin(C_SELECTION);
DessinerRectangle(x - 5, y - 5, IMG_PREVIEW_SIZE + 10, IMG_PREVIEW_SIZE + 10);
@@ -76,33 +59,27 @@ void menu_render(const menu_state_t *state)
}
ChoisirCouleurDessin(C_TEXTE);
/* 2. Section Dimensions */
int dim_section_x = IMG_START_X;
int button_l_offset = 180;
int button_c_offset = 400;
EcrireTexte(dim_section_x, DIM_START_Y, "2. Choisir les dimensions (3x3 a 8x8) :", 1);
/* Affichage de la taille LIGNES */
EcrireTexte(dim_section_x, DIM_START_Y + 40, "Lignes :", 0);
sprintf(buffer, "%d", state->rows);
EcrireTexte(dim_section_x + 100, DIM_START_Y + 40, buffer, 0);
/* Affichage de la taille COLONNES */
EcrireTexte(dim_section_x + 250, DIM_START_Y + 40, "Colonnes :", 0);
sprintf(buffer, "%d", state->cols);
EcrireTexte(dim_section_x + 350, DIM_START_Y + 40, buffer, 0);
/* Boutons de contrôle LIGNES */
draw_button(dim_section_x + button_l_offset, DIM_START_Y + 30, "+", C_BOUTON);
draw_button(dim_section_x + button_l_offset + 40, DIM_START_Y + 30, "-", C_BOUTON);
/* Boutons de contrôle COLONNES */
draw_button(dim_section_x + button_c_offset, DIM_START_Y + 30, "+", C_BOUTON);
draw_button(dim_section_x + button_c_offset + 40, DIM_START_Y + 30, "-", C_BOUTON);
/* 3. Bouton DÉMARRER LA PARTIE */
ChoisirCouleurDessin(C_START);
RemplirRectangle(300, 500, 200, 50);
ChoisirCouleurDessin(CouleurParNom("white"));
@@ -110,7 +87,6 @@ void menu_render(const menu_state_t *state)
}
/* Gère l'interaction après un clic de souris */
void menu_handle_mouse_click(menu_state_t *state)
{
int i;
@@ -121,7 +97,6 @@ void menu_handle_mouse_click(menu_state_t *state)
int button_l_offset = 180;
int button_c_offset = 400;
/* 1. Clic sur les images */
for (i = 0; i < NUM_IMAGES; i++) {
int x_img = IMG_START_X + i * IMG_SPACING;
int y_img = IMG_START_Y;
@@ -132,35 +107,27 @@ void menu_handle_mouse_click(menu_state_t *state)
}
}
/* 2. Clic sur les boutons de Lignes (+/-) */
/* + Lignes */
if (is_in_rect(x_click, y_click, dim_section_x + button_l_offset, DIM_START_Y + 30, btn_size, btn_size)) {
if (is_in_rect(x_click, y_click, dim_section_x + button_l_offset, DIM_START_Y + 30, btn_size, btn_size)) {
if (state->rows < MAX_DIMENSION) state->rows++;
return;
}
/* - Lignes */
if (is_in_rect(x_click, y_click, dim_section_x + button_l_offset + 40, DIM_START_Y + 30, btn_size, btn_size)) {
if (state->rows > MIN_DIMENSION) state->rows--;
return;
}
/* 3. Clic sur les boutons de Colonnes (+/-) */
/* + Colonnes */
if (is_in_rect(x_click, y_click, dim_section_x + button_c_offset, DIM_START_Y + 30, btn_size, btn_size)) {
if (state->cols < MAX_DIMENSION) state->cols++;
return;
}
/* - Colonnes */
if (is_in_rect(x_click, y_click, dim_section_x + button_c_offset + 40, DIM_START_Y + 30, btn_size, btn_size)) {
if (state->cols > MIN_DIMENSION) state->cols--;
return;
}
/* 4. Clic sur DÉMARRER */
if (is_in_rect(x_click, y_click, 300, 500, 200, 50)) {
state->ready_to_play = 1;
return;
@@ -168,7 +135,6 @@ void menu_handle_mouse_click(menu_state_t *state)
}
/* Gère l'interaction clavier */
void menu_handle_key(menu_state_t *state)
{
if (ToucheEnAttente()) {
@@ -195,15 +161,12 @@ void menu_handle_key(menu_state_t *state)
}
}
/* --- IMPLÉMENTATION DES UTILITAIRES PRIVÉS --- */
/* Vérifie si (x_click, y_click) est dans le rectangle */
static int is_in_rect(int x_click, int y_click, int rx, int ry, int rw, int rh)
{
return (x_click >= rx && x_click <= rx + rw && y_click >= ry && y_click <= ry + rh);
}
/* Dessine un bouton rectangulaire rempli avec du texte centré */
static void draw_button(int x, int y, const char *text, couleur C_BG)
{
ChoisirCouleurDessin(C_BG);
@@ -212,12 +175,10 @@ static void draw_button(int x, int y, const char *text, couleur C_BG)
draw_text_centered(x, y, BUTTON_SIZE, BUTTON_SIZE, (char*)text, 1);
}
/* Centre le texte dans une zone (x, y, w, h) */
static void draw_text_centered(int x, int y, int w, int h, const char *text, int size)
{
int text_w = TailleChaineEcran((char*)text, size);
int text_h_sup = TailleSupPolice(size);
/* Calcul de la position de départ pour centrer le texte */
int draw_x = x + (w - text_w) / 2;
int draw_y = y + (h + text_h_sup) / 2;
+6 -10
View File
@@ -1,5 +1,3 @@
/* src/menu_view.h */
#ifndef MENU_VIEW_H
#define MENU_VIEW_H
@@ -7,18 +5,16 @@
#define MIN_DIMENSION 3
#define MAX_DIMENSION 8
/* Structure de l'état du menu */
typedef struct {
int selected_image; /* Index de l'image (0, 1, ou 2) */
int rows; /* Nombre de lignes (3 à 8) */
int cols; /* Nombre de colonnes (3 à 8) */
int ready_to_play; /* 1 si le joueur a validé, -1 si demande de quitter */
} menu_state_t; /* <--- POINT-VIRGULE CORRECT */
int selected_image;
int rows;
int cols;
int ready_to_play;
} menu_state_t;
/* Prototypes des fonctions publiques */
void menu_init(menu_state_t *state);
void menu_render(const menu_state_t *state);
void menu_handle_mouse_click(menu_state_t *state);
void menu_handle_key(menu_state_t *state);
#endif /* MENU_VIEW_H */
#endif
-5
View File
@@ -1,9 +1,6 @@
/* src/utils.c */
#include "utils.h"
#include <stdlib.h>
/* Renvoie la valeur absolue */
int abs_val(int n)
{
if (n < 0) {
@@ -12,10 +9,8 @@ int abs_val(int n)
return n;
}
/* Renvoie un entier aléatoire entre 0 et max-1 */
int random_int(int max)
{
if (max <= 0) return 0;
/* rand() est initialisé dans main.c */
return rand() % max;
}
+1 -7
View File
@@ -1,14 +1,8 @@
/* src/utils.h
* Déclarations des fonctions utilitaires simples.
*/
#ifndef UTILS_H
#define UTILS_H
/* Renvoie la valeur absolue d'un entier */
int abs_val(int n);
/* Renvoie un entier aléatoire entre 0 et max-1 */
int random_int(int max);
#endif /* UTILS_H */
#endif
BIN
View File
Binary file not shown.