264 lines
6.6 KiB
C
264 lines
6.6 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <graph.h>
|
|
#include <string.h>
|
|
#include "utils.h"
|
|
#include "taquin.h"
|
|
#include "graph_sup.h"
|
|
|
|
/* La marge en pixel entre chaque pièce du Taquin */
|
|
#define MARGIN 1
|
|
|
|
/* Définit le nombre d'itérations de la fonction random à faire
|
|
afin de randomiser le taquin */
|
|
#define RANDOM_ITER 50000
|
|
|
|
int OffsetX, OffsetY;
|
|
int ImageX, ImageY, PieceX, PieceY;
|
|
|
|
int Lines, Columns;
|
|
int MoveCount;
|
|
unsigned char* Taquin;
|
|
|
|
char Filename[100];
|
|
|
|
/* Dessine la partie de l'image correspondante à l'indice donné */
|
|
void DrawPiece(int index, couleur color) {
|
|
int CoordX = (index % Columns) * PieceX;
|
|
int CoordY = (index / Columns) * PieceY;
|
|
|
|
int ImCoordX = (Taquin[index] % Columns) * PieceX;
|
|
int ImCoordY = (Taquin[index] / Columns) * PieceY;
|
|
|
|
if (Taquin[index] != 0) ChargerImage(Filename, CoordX + OffsetX, CoordY + OffsetY, ImCoordX, ImCoordY, PieceX, PieceY);
|
|
else {
|
|
SetColor(255, 255, 255);
|
|
RemplirRectangle(CoordX + OffsetX, CoordY + OffsetY, PieceX, PieceY);
|
|
}
|
|
SetColorC(color);
|
|
DessinerRectangle(CoordX + OffsetX, CoordY + OffsetY, PieceX - 1, PieceY - 1);
|
|
}
|
|
|
|
void UpdateTaquin() {
|
|
int i;
|
|
couleur color = GetColor(0, 0, 0);
|
|
for (i = 0; i < Lines * Columns; i++) DrawPiece(i, color);
|
|
}
|
|
|
|
/* Vérifie la validité des mouvements et met à jour le taquin graphiquement
|
|
si l'argument should_update est égal à 1.*/
|
|
int MovePiece(int index, int should_update) {
|
|
int moves[4] = {
|
|
index + 1,
|
|
index - 1,
|
|
index + Columns,
|
|
index - Columns
|
|
};
|
|
|
|
int i;
|
|
couleur selected = GetColor(255, 0, 0), black = GetColor(0, 0, 0);
|
|
for (i = 0; i < 4; i++) {
|
|
if (moves[i] >= 0 && moves[i] < Columns * Lines) {
|
|
if (Taquin[moves[i]] == 0) {
|
|
Taquin[moves[i]] = Taquin[index];
|
|
Taquin[index] = 0;
|
|
|
|
if (should_update) {
|
|
DrawPiece(moves[i], black);
|
|
DrawPiece(index, selected);
|
|
|
|
ChargerImage("./images/assets/move_count.png", 497, 600, 0, 0, 205, 85);
|
|
SetColor(192, 205, 228);
|
|
|
|
char str[5];
|
|
sprintf(str, "%d", MoveCount);
|
|
EcrireTexte(620, 650, str, 2);
|
|
MoveCount++;
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Randomise le Taquin */
|
|
void RandomizeTaquin() {
|
|
int index = 0, last_move = -1, move, i;
|
|
int moves[4] = {1, -1, Columns, -Columns};
|
|
int piece_count = Lines * Columns;
|
|
/* L'aléatoire n'est pas idéal, afin de mieux exploiter
|
|
la fonction, on devrait éviter de faire des coups inutiles
|
|
du genre essayer de sortir du Taquin mais elle marche
|
|
relativement bien au delà de ces problèmes. */
|
|
MoveCount = 0;
|
|
|
|
for (i = 0; i < RANDOM_ITER; i++) {
|
|
srand(Microsecondes());
|
|
move = rand() % 4;
|
|
if (move != last_move) {
|
|
move = moves[move];
|
|
if (index + move >= 0 && index + move < piece_count) {
|
|
MovePiece(index, 0);
|
|
index += move;
|
|
}
|
|
}
|
|
}
|
|
|
|
ChargerImage("./images/assets/move_count.png", 497, 600, 0, 0, 205, 85);
|
|
SetColor(192, 205, 228);
|
|
|
|
char str[5];
|
|
sprintf(str, "%d", MoveCount);
|
|
EcrireTexte(620, 650, str, 2);
|
|
}
|
|
|
|
/* Renvoie 1 si le taquin est en ordre */
|
|
int CheckForVictory() {
|
|
int i;
|
|
for (i = 0; i < Lines * Columns; i++) {
|
|
if (Taquin[i] != i) return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* Bloque le programme pendant la partie, appelle les fonctions liées au coups
|
|
et aussi celles afin de randomiser et quitter le taquin. */
|
|
int TaquinRenderLoop() {
|
|
int button_id = -1, last_id = -1;
|
|
int controller = 0, key;
|
|
|
|
couleur selected = GetColor(255, 0, 0), black = GetColor(0, 0, 0);
|
|
|
|
while (1) {
|
|
if (SourisCliquee()) {
|
|
controller = 0;
|
|
button_id = GetButton(_X, _Y);
|
|
if (button_id >= 0) {
|
|
MovePiece(button_id, 1);
|
|
if (CheckForVictory()) return 1;
|
|
}
|
|
else if (button_id == -3) {
|
|
RandomizeTaquin();
|
|
UpdateTaquin();
|
|
}
|
|
else if (button_id == -2) return 0;
|
|
}
|
|
|
|
if (ToucheEnAttente()) {
|
|
controller = 1;
|
|
|
|
key = Touche();
|
|
if (button_id < 0) button_id = 0;
|
|
|
|
if (key == XK_Left || key == XK_q) {
|
|
if (button_id - 1 >= 0) {
|
|
last_id = button_id;
|
|
button_id -= 1;
|
|
}
|
|
} else if (key == XK_Right || key == XK_d) {
|
|
if (button_id + 1 < Columns * Lines) {
|
|
last_id = button_id;
|
|
button_id += 1;
|
|
}
|
|
} else if (key == XK_Up || key == XK_z) {
|
|
if (button_id - Columns >= 0) {
|
|
last_id = button_id;
|
|
button_id -= Columns;
|
|
}
|
|
} else if (key == XK_Down || key == XK_s) {
|
|
if (button_id + Columns < Lines * Columns) {
|
|
last_id = button_id;
|
|
button_id += Columns;
|
|
}
|
|
} else if (key == XK_space) {
|
|
MovePiece(button_id, 1);
|
|
if (CheckForVictory()) return 1;
|
|
}
|
|
|
|
if (button_id >= 0) DrawPiece(button_id, selected);
|
|
if (last_id >= 0) DrawPiece(last_id, black);
|
|
}
|
|
|
|
if (DrawNextFrame()) {
|
|
if (controller == 0) {
|
|
SourisPosition();
|
|
button_id = GetButton(_X, _Y);
|
|
if (button_id != last_id) {
|
|
if (button_id > -1) DrawPiece(button_id, selected);
|
|
if (last_id > -1) DrawPiece(last_id, black);
|
|
last_id = button_id;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* L'écran de victoire */
|
|
void ShowVictoryScreen() {
|
|
ClearButtons();
|
|
AddButton(WIDTH/4 + 60, HEIGHT/4 + 250, 230, 78, 1);
|
|
AddButton(WIDTH/4 + 312, HEIGHT/4 + 250, 230, 78, 2);
|
|
|
|
int BT_ID;
|
|
|
|
while (1) {
|
|
if (DrawNextFrame()) {
|
|
ChargerImage("./images/assets/win_screen.png", WIDTH/4, HEIGHT/4, 0, 0, WIDTH/2, HEIGHT/2);
|
|
|
|
if (SourisCliquee()) {
|
|
BT_ID = GetButton(_X, _Y);
|
|
if (BT_ID == 1) {
|
|
return;
|
|
} else if (BT_ID == 2) {
|
|
CreateTaquin(Filename, ImageX, ImageY, Lines, Columns);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Crée le Taquin et lance les fonctions liées à la logique et au graphisme du Taquin */
|
|
void CreateTaquin(char * filename, int ImageWidth, int ImageHeight, int lines, int columns) {
|
|
/* On externalise les valeurs données afin de pouvoir facilement les utiliser plus tard. */
|
|
int i;
|
|
|
|
Lines = lines;
|
|
Columns = columns;
|
|
strcpy(Filename, filename);
|
|
|
|
ImageX = ImageWidth;
|
|
ImageY = ImageHeight;
|
|
PieceX = ImageX / Columns;
|
|
PieceY = ImageY / Lines;
|
|
|
|
OffsetX = WIDTH - 50 - ImageX;
|
|
OffsetY = (HEIGHT - ImageY) / 2 - 50;
|
|
|
|
/* On alloue l'espace mémoire nécéssaire au Taquin et on l'initialise en premier résolu.
|
|
On ajoute aussi les boutons servant à vérifier les clics souris.*/
|
|
Taquin = calloc(Lines * Columns, sizeof(unsigned char));
|
|
for (i = 0; i < Lines * Columns; i++) {
|
|
AddButton(OffsetX + (i % Columns) * PieceX, OffsetY +(i / Columns) * PieceY, PieceX, PieceY, i);
|
|
Taquin[i] = i;
|
|
}
|
|
|
|
ChargerImage("./images/assets/background_taquin.png", 0, 0, 0, 0, 1200, 700);
|
|
ChargerImage(Filename, 50, OffsetY, 0, 0, ImageX, ImageY);
|
|
|
|
AddButton(WIDTH/4 - 100, HEIGHT -100, 200, 80, -2); //Bouton Quitter
|
|
AddButton(WIDTH/4 * 3 - 100, HEIGHT - 100, 200, 80, -3); //Bouton Randomiser
|
|
|
|
RandomizeTaquin();
|
|
UpdateTaquin();
|
|
|
|
if (TaquinRenderLoop()) {
|
|
ShowVictoryScreen();
|
|
}
|
|
}
|