infini_puissance_5/grille.c

352 lines
7.6 KiB
C
Raw Normal View History

2023-10-22 11:52:46 +02:00
/*
* Infini puissance N : un jeu à plusieurs joueurs.
* Copyright (C) 2023 Valentin Moguérou
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h> // à enlever après
#include <stdlib.h>
#include <stdbool.h>
2023-10-22 11:52:46 +02:00
#include "grille.h"
2023-10-22 11:52:46 +02:00
char repr_jeton(jeton j)
{
switch (j)
{
case (BLEU):
return 'X';
case (ROUGE):
return '0';
default:
return ' ';
}
}
void print_tab(jeton *tab, int n)
{
for (int i=0; i<n; i++)
printf("%p --> %x (%d)\n", &tab[i], tab[i], tab[i]);
printf("\n");
}
void print_colonne(colonne *col)
{
2023-10-22 11:52:46 +02:00
for (int i=0; i<col->hauteur; i++)
putc(repr_jeton(col->jetons[i]), stdout);
putc('\n', stdout);
}
void init_zeros(jeton* ptr, int count)
{
for (int i=0; i<count; i++)
{
2023-10-20 21:46:48 +02:00
ptr[i] = VIDE;
}
}
2023-10-20 18:18:20 +02:00
colonne *creer_colonne(int capacite)
{
colonne *col = malloc(sizeof(colonne));
2023-10-20 21:46:48 +02:00
if (col == NULL)
return NULL;
2023-10-20 18:18:20 +02:00
col->jetons = malloc(capacite*sizeof(jeton));
2023-10-20 21:46:48 +02:00
if (col->jetons == NULL)
{
free(col);
return NULL;
}
2023-10-20 18:18:20 +02:00
init_zeros(col->jetons, capacite);
2023-10-20 18:18:20 +02:00
col->capacite = capacite;
col->hauteur = 0;
return col;
}
bool agrandir_colonne(int diff_taille, colonne *col)
{
jeton *jetons_nouv = realloc(col->jetons, (col->capacite + diff_taille)*sizeof(jeton));
if (jetons_nouv == NULL)
return false; // allocation impossible, on garde col->jetons tel quel
2023-10-20 21:46:48 +02:00
2023-10-20 18:18:20 +02:00
col->jetons = jetons_nouv;
// on met des zéros dans la partie nouvellement attribuée
2023-10-20 18:18:20 +02:00
init_zeros(col->jetons + col->capacite, diff_taille);
2023-10-20 21:46:48 +02:00
// free est appelée par realloc et les éléments sont copiés par realloc
2023-10-20 18:18:20 +02:00
col->capacite += diff_taille;
return true;
}
2023-10-22 11:52:46 +02:00
bool ajouter_jeton_col(jeton j, colonne *col)
{
2023-10-20 21:46:48 +02:00
if (col->hauteur >= col->capacite
&& !agrandir_colonne(Y_BLOCK_SIZE, col))
return false;
col->jetons[col->hauteur] = j;
col->hauteur++;
return true;
}
2023-10-22 11:52:46 +02:00
jeton get_jeton_col(int indice, colonne *col)
2023-10-20 21:46:48 +02:00
{
return (indice < col->hauteur) ? col->jetons[indice] : VIDE;
}
void detruire_colonne(colonne *col)
{
free(col->jetons);
free(col);
}
2023-10-20 21:46:48 +02:00
/*
* On essaie de représenter une structure abstraite comme ceci :
* En abscisse, les "colonne*"; en ordonnée, les "jeton"
*
* +oo (jetons)
* ^
* |
* |
* |
* |
* |
* -oo <------------------------I----------------------> +oo (colonne*)
*
* Représentation en mémoire :
*
* g->positifs = [colonne*(0), colonne*(1), ...]
* // autant que de colonnes positives ou nulles ç.à.d autant que g->n_positifs
*
* g->negatifs = [colonne*(-1), colonne*(-2) , ...]
* // autant que de colonnes str. négatives ç.à.d autant que g->n_negatifs
2023-10-22 11:52:46 +02:00
*/
2023-10-20 21:46:48 +02:00
grille *creer_grille(int largeur)
{
/* On divise largeur en deux :
*
* |-----------------------------|-----------------------------|
* negatifs 0 positifs
*
2023-10-22 11:52:46 +02:00
* d' n_positifs = largeur/2 + largeur%2
* n_negatifs = largeur/2
2023-10-20 21:46:48 +02:00
*
* de telle sorte que:
* n_negatifs + n_positifs = largeur
*
* Ex :
* - L'intervalle [-10, 9] de cardinal 20 se découpe en
2023-10-22 11:52:46 +02:00
* 10 nombres positifs [0, 9] et 10 nombres négatifs [-10, -1] représenté
2023-10-20 21:46:48 +02:00
*/
grille *g = malloc(sizeof(grille));
if (g == NULL)
return NULL;
2023-10-22 11:52:46 +02:00
g->n_positifs = largeur/2 + largeur%2;
g->n_negatifs = largeur/2;
2023-10-20 21:46:48 +02:00
g->positifs = malloc(g->n_positifs * sizeof(colonne*));
2023-10-22 11:52:46 +02:00
g->negatifs = malloc(g->n_negatifs * sizeof(colonne*));
2023-10-20 21:46:48 +02:00
2023-10-22 11:52:46 +02:00
if (g->positifs == NULL || g->negatifs == NULL)
{
free(g->positifs);
free(g->negatifs);
2023-10-20 21:46:48 +02:00
free(g);
2023-10-22 11:52:46 +02:00
}
2023-10-20 21:46:48 +02:00
bool echec_allocation = false;
2023-10-22 11:52:46 +02:00
for (int i=0; i < g->n_positifs; i++)
2023-10-20 21:46:48 +02:00
{
g->positifs[i] = creer_colonne(Y_BLOCK_SIZE);
if (g->positifs[i] == NULL)
2023-10-22 11:52:46 +02:00
echec_allocation = true;
2023-10-20 21:46:48 +02:00
}
2023-10-22 11:52:46 +02:00
for (int i=0; i < g->n_negatifs; i++)
{
g->negatifs[i] = creer_colonne(Y_BLOCK_SIZE);
if (g->negatifs[i] == NULL)
echec_allocation = true;
}
2023-10-20 21:46:48 +02:00
// si une colonne n'a pas pu être crée, on détruit la grille
if (echec_allocation)
{
detruire_grille(g);
g = NULL;
}
return g;
}
bool etendre_tab(int d_len, int *len, colonne ***tab)
{
/* Fonction qui prend en entrée une différence de taille, un pointeur
* vers un tableau de colonnes et un pointeur vers sa longueur.
*
* Si la réallocation n'échoue pas (99.99% des cas), le pointeur vers
* le tableau est éventuellement modifié (selon la tambouille de realloc)
* et la taille est modifiée.
*
* Un argument est un colonne*** car c'est un pointeur vers un tableau de colonne*
*
*/
colonne **tab_nouv = realloc(*tab, (*len + d_len)*sizeof(colonne*));
if (tab_nouv == NULL)
return false; // la mémoire n'a pas pu être allouée
*tab = tab_nouv;
bool echec_allocation = false;
2023-10-22 11:52:46 +02:00
for (int i=0; i<d_len; i++)
2023-10-20 21:46:48 +02:00
{
(*tab)[*len + i] = creer_colonne(Y_BLOCK_SIZE);
if ((*tab)[*len + i] == NULL)
echec_allocation = true;
}
// si échec on revient à l'état initial
if (echec_allocation)
{
for (int i=0; i<d_len; i++)
if ((*tab)[*len + i] != NULL)
detruire_colonne((*tab)[*len + i]);
return false;
}
*len += d_len;
return true;
}
bool etendre_gauche(int d_len, grille *g)
{
// application sur les négatifs
return etendre_tab(d_len, &g->n_negatifs, &g->negatifs);
}
bool etendre_droite(int d_len, grille *g)
{
// application sur les positifs
return etendre_tab(d_len, &g->n_positifs, &g->positifs);
}
2023-10-22 11:52:46 +02:00
colonne *get_colonne(int i, grille *g)
{
/* La structure de tableau double sens se traduit de la façon suivante :
*
* Si i >= 0, on regarde g->positifs[i]
* Si i < 0, on regarde g->negatifs[-i-1]
*/
if (i >= 0 && i < g->n_positifs)
return g->positifs[i];
else if (i < 0 && ~i < g->n_negatifs)
return g->negatifs[~i];
else
return NULL; // en dehors de l'allocation
}
jeton get_case(int x, int y, grille *g)
{
colonne *col = get_colonne(x, g);
return (col != NULL) ? get_jeton_col(y, col) : VIDE;
}
bool ajouter_jeton(jeton j, int x, grille *g)
2023-10-20 21:46:48 +02:00
{
2023-10-22 11:52:46 +02:00
if (x >= 0 && x > g->n_positifs)
for (int i=0; i < x-g->n_positifs+1; i++)
if (!etendre_droite(X_BLOCK_SIZE, g))
return false;
if (x < 0 && ~x > g->n_negatifs)
for (int i=0; i < ~x-g->n_negatifs+1; i++)
if (!etendre_gauche(X_BLOCK_SIZE, g))
return false;
return ajouter_jeton_col(j, get_colonne(x, g));
2023-10-20 21:46:48 +02:00
}
void detruire_grille(grille *g)
{
2023-10-22 11:52:46 +02:00
for (int i=0; i < g->n_positifs; i++)
2023-10-20 21:46:48 +02:00
if (g->positifs[i] != NULL)
detruire_colonne(g->positifs[i]);
2023-10-22 11:52:46 +02:00
for (int i=0; i < g->n_negatifs; i++)
2023-10-20 21:46:48 +02:00
if (g->negatifs[i] != NULL)
detruire_colonne(g->negatifs[i]);
free(g);
}
// =========================================== TEST =================================================
2023-10-22 11:52:46 +02:00
int test_colonne()
{
colonne *col = creer_colonne(Y_BLOCK_SIZE);
print_colonne(col);
for (int i=0; i<15; i++)
{
2023-10-22 11:52:46 +02:00
if (ajouter_jeton_col((i%2==0) ? ROUGE : BLEU, col))
printf("Jeton ajouté.\n");
else
fprintf(stderr, "Erreur dans l'ajout d'un jeton.\n");
}
print_colonne(col);
detruire_colonne(col);
return 0;
}
2023-10-22 11:52:46 +02:00
int test_grille()
{
grille *g = creer_grille(20);
detruire_grille(g);
return 0;
}
int main()
{
return test_grille();
}