From 5f5f77bb24a6eabbad6a8601c14074eccb4cc90d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Mogu=C3=A9rou?= Date: Sun, 12 Nov 2023 23:41:12 +0100 Subject: [PATCH] Reconstruction --- .gitignore | 2 + CGU.txt | 56 +++++ Makefile | 20 ++ grille | Bin 0 -> 18096 bytes grille.c | 382 ------------------------------- main.c | 8 - src/cli.c | 418 ++++++++++++++++++++++++++++++++++ src/display.c | 64 ++++++ src/grille.c | 473 +++++++++++++++++++++++++++++++++++++++ grille.h => src/grille.h | 23 +- 10 files changed, 1048 insertions(+), 398 deletions(-) create mode 100644 CGU.txt create mode 100644 Makefile create mode 100755 grille delete mode 100644 grille.c delete mode 100644 main.c create mode 100644 src/cli.c create mode 100644 src/display.c create mode 100644 src/grille.c rename grille.h => src/grille.h (56%) diff --git a/.gitignore b/.gitignore index b0a1990..d3b618d 100644 --- a/.gitignore +++ b/.gitignore @@ -188,3 +188,5 @@ fabric.properties # Android studio 3.1+ serialized cache file .idea/caches/build_file_checksums.ser +bin/ +obj/ diff --git a/CGU.txt b/CGU.txt new file mode 100644 index 0000000..15ae4c7 --- /dev/null +++ b/CGU.txt @@ -0,0 +1,56 @@ + Conditions Générales d'Utilisation + +En jouant à ce jeu, vous acceptez tacitement les présentes Conditions Générales d'Utilisation. + +I. Définitions + + Par Joueur nous entendons toute personne physique, morale ayant la capacité juridique ou, dans le cas contraire, ayant eu le consentement d'un de ses responsables légaux. + + Par Programme nous entendons l'ensemble constitué de l'exécutable sous forme binaire virtuellement stockée sur un support physique idoine (disque dur, SSD, clef USB, disquette, cassette, carte à trous, serveur distant, papier calque, tableau noir ou serveur téléphonique accessible via un terminal minitel). + + Par Autobus nous entendons toue passoire du troisième ordre dont le diamètre des trous est nul et qui ne possède pas de manche. + + Par Conditions Générales D'Utilisation nous entendons le texte français que le Joueur lit, écoute, télépathe, rêve, crie, chuchotte, marmonne, hurle, et caetera. + +II. Dispositions générales + +1. Le précent logiciel est fourni sans aucune garantie, y compris sans garatie implicite de fiabilité ou d'adéquation à un usage particulier. En particulier, le non-amusement ne constitue pas un motif valable de remboursement du présent Logiciel. + +2. En cas de désaccord avec les présentes Conditions générales, vous vous engagez à ne pas poursuivre l'exécution du Logiciel en effectuant l'une des actions suivantes : + + 2.1. Arrêt immédiat interne de l'exécution du logiciel en appuyant sur une des combinaisons de touche suivantes : ^C, ^D ; + + 2.2. Arrêt immédiat externe de l'exécution du logiciel en utilisant un logiciel externe non fourni (kill, gestionnaire des tâches) ; + + 2.3. Arrêt immédiat en éteignant votre ordinateur en appuyant sur un bouton physique ou virtuel + + 2.4. Arrêt différé du logiciel en débranchant toute source d'alimentation à votre ordinateur et en laissant sa batterie se vider (cet arrêt est immédiat si votre support d'exécution est dépourvu de batterie d'accumulateurs). + +III. Dispositions spécifiques + +1. Il est strictement interdit d'utiliser le Programme pour accomplir les actes suivants : + + 1.1. Actes terroristes ou de nature à porter atteinte à l'intégrité de la République Française, ou de tout état dans lequel le Programme est exécuté ; + + 1.2. Catastrophes naturelles (tornades, innondations, sécheresse, pluie, ouragan, typhon, tremblement de terre, glissement de terrain, éruption d'un volcan effusif ou explosif, tsunami, froid hivernal de nature à provoquer un rhume) ; + + 1.3. Création d'une œuvre artistique sonore de nature à constituer une chanson qui reste dans la tête et ce de ce fait, de nature à créer un trouble de l'ordre public. + +IV. Effets secondaires + +1. Le Joueur reconnaît que l'utilisation répétée du Jeu peut créer de l'addiction, de l'ennui, ou ultimement des troubles psychatriques irréversibles. Le Joueur s'engage à consulter son médecin traitant avant toute utilisation du Jeu. + +2. Le Joueur reconnait que la non-utilisation du Jeu permet la réalisation d'activités de nature à améliorer le Joueur en tant que personne (sport, interactions sociales, jardinage, balade en forêt, pêche, programmation, mathématiques, physique, lecture, hygiène) + +3. Le Joueur consent à la défaite tout comme à la victoire. En cas de litige, il est invité à consulter le Médiateur: + + Médiateur des Mauvais Perdants + 42 boulevard de la Mauvaise Foi + 75021 Paris 21e arrdt. CEDEX + +V. Applicabilité + +L'auteur du Programme remercie le Joueur d'avoir pris le temps de lire les présentes Conditions. Le Joueur reconnaît que le Programme est placé sous license GNU GPL v3 ou ultérieure telle que publiée par la Free Software Foundation. Les termes et conditions de la GNU GPL v3 annulent et remplacent les présentes Conditions, à l'exceptions des années bissextiles multiples de 100 non multiples de 400. + + Si vous acceptez les présentes Conditions, + vous pouvez appuyer sur . diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..70d130a --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +CC=gcc +CFLAGS=-Wall -Wextra -Wpedantic +LDFLAGS= + +bin/cli: obj/grille.o obj/cli.o + @mkdir -p bin + $(CC) -o $@ $^ $(LDFLAGS) + +obj/grille.o: src/grille.c src/grille.h + @mkdir -p obj + $(CC) -o $@ -c $< $(CFLAGS) + +obj/cli.o: src/cli.c + @mkdir -p obj + $(CC) -o $@ -c $< $(CFLAGS) + +.PHONY: clean + +clean: + rm -rf bin/ obj/ diff --git a/grille b/grille new file mode 100755 index 0000000000000000000000000000000000000000..3336d347dc2a3c97c07fa3443e365952fa8c3a88 GIT binary patch literal 18096 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 NoseJa5%3h*{{ZPpi|GIW literal 0 HcmV?d00001 diff --git a/grille.c b/grille.c deleted file mode 100644 index 8796a3d..0000000 --- a/grille.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * 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 . - */ - -#include // à enlever après -#include -#include - -#include "grille.h" - - -char repr_jeton(jeton j) -{ - switch (j) - { - case (BLEU): - return 'B'; - case (ROUGE): - return 'R'; - default: - return '_'; - } -} - -void print_tab(jeton *tab, int n) -{ - for (int i=0; i %x (%d)\n", &tab[i], tab[i], tab[i]); - printf("\n"); -} - -void print_colonne(colonne *col) -{ - for (int i=0; icapacite; i++) - putc(repr_jeton(col->jetons[i]), stdout); - putc('\n', stdout); -} - -void init_zeros(jeton* ptr, int count) -{ - for (int i=0; ijetons = malloc(capacite*sizeof(jeton)); - if (col->jetons == NULL) - { - free(col); - return NULL; - } - - init_zeros(col->jetons, capacite); - - 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 - - col->jetons = jetons_nouv; - - // on met des zéros dans la partie nouvellement attribuée - init_zeros(col->jetons + col->capacite, diff_taille); - - // free est appelée par realloc et les éléments sont copiés par realloc - col->capacite += diff_taille; - - return true; - -} - -bool ajouter_jeton_col(jeton j, colonne *col) -{ - if (col->hauteur >= col->capacite - && !agrandir_colonne(Y_BLOCK_SIZE, col)) - return false; - - col->jetons[col->hauteur] = j; - printf("(%p)->jetons[%d] = %c\n", col, col->hauteur, repr_jeton(j)); - col->hauteur++; - - return true; -} - -jeton get_jeton_col(int indice, colonne *col) -{ - return (indice < col->hauteur) ? col->jetons[indice] : VIDE; -} - -void detruire_colonne(colonne *col) -{ - free(col->jetons); - free(col); -} - -/* - * 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 - */ - -grille *creer_grille(int largeur) -{ - /* On divise largeur en deux : - * - * |-----------------------------|-----------------------------| - * negatifs 0 positifs - * - * d'où n_positifs = largeur/2 + largeur%2 - * n_negatifs = largeur/2 - * - * de telle sorte que: - * n_negatifs + n_positifs = largeur - * - * Ex : - * - L'intervalle [-10, 9] de cardinal 20 se découpe en - * 10 nombres positifs [0, 9] et 10 nombres négatifs [-10, -1] représenté - */ - - grille *g = malloc(sizeof(grille)); - if (g == NULL) - return NULL; - - g->n_positifs = largeur/2 + largeur%2; - g->n_negatifs = largeur/2; - g->positifs = malloc(g->n_positifs * sizeof(colonne*)); - g->negatifs = malloc(g->n_negatifs * sizeof(colonne*)); - - /* - if (g->positifs == NULL || g->negatifs == NULL) - { - free(g->positifs); - free(g->negatifs); - free(g); - return NULL; - } - - bool echec_allocation = false; - */ - - for (int i=0; i < g->n_positifs; i++) - { - g->positifs[i] = creer_colonne(Y_BLOCK_SIZE); - //if (g->positifs[i] == NULL) - // echec_allocation = true; - } - - 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; - } - - - // si une colonne n'a pas pu être crée, on détruit la grille - /* - if (echec_allocation) - { - detruire_grille(g); - return 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; - for (int i=0; in_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); -} - - -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) -{ - 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)); -} - - -void detruire_grille(grille *g) -{ - for (int i=0; i < g->n_positifs; i++) - if (g->positifs[i] != NULL) - detruire_colonne(g->positifs[i]); - - for (int i=0; i < g->n_negatifs; i++) - if (g->negatifs[i] != NULL) - detruire_colonne(g->negatifs[i]); - - free(g); -} - -// =========================================== TEST ================================================= - - - - -int test_colonne() -{ - colonne *col = creer_colonne(Y_BLOCK_SIZE); - print_colonne(col); - - for (int i=0; i<15; i++) - { - 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; -} - -void print_grille(grille *g) -{ - printf("n_positifs : %d ; n_negatifs : %d\n", g->n_positifs, g->n_negatifs); - for (int i=-g->n_negatifs; in_positifs; i++) - { - printf("% 5d | ", i); - print_colonne(get_colonne(i, g)); - } - -} - -int test_grille() -{ - grille *g = creer_grille(20); - - ajouter_jeton(BLEU, 0, g); - ajouter_jeton(BLEU, 0, g); - ajouter_jeton(BLEU, 0, g); - ajouter_jeton(ROUGE, -1, g); - ajouter_jeton(BLEU, -1, g); - ajouter_jeton(BLEU, -1, g); - ajouter_jeton(BLEU, -2, g); - ajouter_jeton(ROUGE, 4, g); - ajouter_jeton(ROUGE, 4, g); - ajouter_jeton(ROUGE, 4, g); - ajouter_jeton(BLEU, 240, g); - - print_grille(g); - - detruire_grille(g); - - return 0; -} - -int main() -{ - return test_grille(); -} diff --git a/main.c b/main.c deleted file mode 100644 index 2571cf2..0000000 --- a/main.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "grille.h" -#include "display.h" - -int main(int argc, char **argv) -{ - - return 0; -} diff --git a/src/cli.c b/src/cli.c new file mode 100644 index 0000000..9314910 --- /dev/null +++ b/src/cli.c @@ -0,0 +1,418 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "grille.h" + +#define NEXT_CH_BUFFER_IS(ch) (!feof(stdin) && getc(stdin)==ch) + +/* +* Sur Caséine le terminal fait 132 caractères de large +* +*/ + +typedef struct +{ + int lignes; + int colonnes; +} ecran; + + +bool is_number(wchar_t string[]) +{ + int i=0; + if (!isdigit(string[0]) && string[0] != L'+' && string[0] != L'-') + return false; + i++; + + while (string[i] != L'\0') + { + if (!isdigit(string[i])) + return false; + i++; + } + + return true; +} + +bool wcmp_fst_word(wchar_t str1[], wchar_t str2[]) +{ + int i=0; + while ((str1[i] != L' ' && str1[i] != L'\0') && (str2[i] != L' ' && str2[i] != L'\0')) + { + if (str1[i] != str2[i]) + return false; + } + return true; +} + +void flush_stdin() +{ + int c; + while ((c=getchar()) != '\n' && c != EOF); +} + +const char symbols[][5] = { + " ", // VIDE + "\U0001f534", // red circle + "\U0001f535", // blue circle + "\U0001f7e2", // green circle + "\U0001f7e1", // yellow circle + "\U0001f7e0", // orange circle + "\U0001f7e3", // purple circle + "\U0001f7e4", // brown circle + "\u26AB", // black circle + "\u26AA", // white circle +}; + +void cur_goto(int line, int column) +{ + printf("\033[%d;%dH", line, column); +} + +void clear_screen() +{ + printf("\033[2J"); +} + +void rect(int x1, int x2, int y1, int y2) +{ + cur_goto(y1, x1); + printf("\u250C"); + cur_goto(y1, x2); + printf("\u2510"); + cur_goto(y2, x1); + printf("\u2514"); + cur_goto(y2, x2); + printf("\u2518"); + + for (int x=x1+1; x= y1) + { + cur_goto(y, x); + printf("%lc", ch); + x++; + } + + if (x>x2) + { + y++; + x = x1; + } + ch = fgetwc(fichier); + } + + fclose(fichier); +} + +void print_rect(int x1, int x2, int y1, int y2, int* chaine, int offset_y) +{ + int x=x1, y=y1-offset_y; + + for (int *ch = chaine; *ch != '\0' && y <= y2; ch++) + { + if (x>x2) + { + y++; + x = x1; + } + + if (*ch == '\n') + { + x = x1; + y++; + } + else if (y >= y1) + { + cur_goto(y, x); + printf("%lc", *ch); + x++; + } + } + +} + +int **prompt_names(ecran ecr, const int prompt[], int n_joueurs) +{ + clear_screen(); + rect(ecr.colonnes/3, 2*ecr.colonnes/3, ecr.lignes/3, 2*ecr.lignes/3); + + getchar(); + return NULL; +} + +int quot(int a, int b) +{ + return (a>=0) ? a/b : a/b-1; +} + +void print_grille(ecran ecr, int base_x, int base_y, grille *g) +{ + clear_screen(); + if (ecr.lignes-base_y-1 < ecr.lignes && ecr.lignes > base_y+1) + { + for (int x=1; x<=ecr.colonnes; x+=2) + { + cur_goto(ecr.lignes-base_y-2, x); + printf("\u2500\u2500"); // box drawing character + if ((quot((x+1),2)-base_x)%10==0 && x+2 < ecr.colonnes) printf("\v%d", quot(x+1,2)-base_x); + } + } + + for (int y=1; y0) + { + prompt[i-1] = 0; + i--; + } + break; + case '\033': + if (NEXT_CH_BUFFER_IS('[')) + switch (getchar()) + { + case 'C': // -> + break; + case 'D': // <- + if (i>0) + i--; + } + else + return; + default: + if (i<99) + { + prompt[i] = c; + prompt[i+1] = 0; + i++; + } + } + cur_goto(ecr.lignes, 0); + printf("\033[2K:%ls", prompt); + cur_goto(ecr.lignes, i+2); + c = getchar(); + } + + if (is_number(prompt)) + { + *offset_x = ecr.colonnes/4 - wcstol(prompt, NULL, 10); + } + /* else if (wcmp_fst_word(prompt, L"save")) + { + printf("Saving..."); + getchar(); + } */ +} + +void process_input(ecran ecr, int *offset_x, int *offset_y, bool *do_abort, jeton joueur, int *last_x, int *last_y, grille *g) +{ + bool tour = true; + while (tour && !*do_abort) + { + print_grille(ecr, *offset_x, *offset_y, g); + cur_goto(0, ecr.colonnes/2+1); + printf("%s", symbols[joueur]); + + switch (getchar()) + { + case ':': + process_command(ecr, offset_x, offset_y, do_abort, &tour, g); + break; + case '\003': + printf("^C\n"); + *do_abort = true; + break; + case '\004': + printf("^D\n"); + *do_abort = true; + break; + case '\033': + if (NEXT_CH_BUFFER_IS('[')) + switch(getc(stdin)) + { + case 'A': + //printf("A"); break; + (*offset_y)--; break; + case 'B': + //printf("B"); break; + (*offset_y)++; break; + case 'C': + //printf("C"); break; + (*offset_x)--; break; + case 'D': + //printf("D"); break; + (*offset_x)++; break; + } + break; + case ' ': + *last_x = ecr.colonnes/4 - *offset_x; + ajouter_jeton(joueur, *last_x, last_y, g); + tour = false; + break; + } + } +} + +bool read_cgu(ecran ecr) +{ + + int offset_y=0; + bool cgu_agree = false, cgu_disagree = false; + while (!cgu_agree && !cgu_disagree) + { + clear_screen(); + rect(2, ecr.colonnes-1, 2, ecr.lignes-1); + + cur_goto(3,4); + print_rect_fichier(4, ecr.colonnes-3, 3, ecr.lignes-2, "CGU.txt", offset_y); + + switch (getchar()) + { + case '\n': + cgu_agree = true; break; + case '\033': // ESC + if (NEXT_CH_BUFFER_IS('[')) + switch(getchar()) + { + case 'A': if (offset_y>0) offset_y--; break; + case 'B': offset_y++; break; + } + break; + case '\003': + case '\004': + cgu_disagree = true; + break; + } + } + + return cgu_agree; +} + +void jouer(ecran ecr, int n_joueurs) +{ + grille *g = creer_grille(); + + ajouter_jeton(BLEU, 0, NULL, g); + ajouter_jeton(ROUGE, 0, NULL, g); + + int offset_x = ecr.colonnes/4, offset_y = 0; + int last_x = 0, last_y = 0; + bool do_abort = false; + + jeton joueur = 0; + + do { + joueur = joueur%n_joueurs + 1; + + process_input(ecr, &offset_x, &offset_y, &do_abort, joueur, &last_x, &last_y, g); + } while (!gagnant(last_x, last_y, 5, g) && !do_abort); + + if (!do_abort) + { + print_grille(ecr, offset_x, offset_y, g); + cur_goto(0,0); + printf("Le joueur %s a gagné. Appuyer sur une touche pour continuer...", symbols[joueur]); + getchar(); + cur_goto(0,0); + clear_screen(); + } + + detruire_grille(g); +} + +int main() +{ + setlocale (LC_ALL, ""); + + static struct termios oldterm, newterm; + + tcgetattr(STDIN_FILENO, &oldterm); + newterm = oldterm; + + newterm.c_lflag &= ~(ICANON | IEXTEN | ISIG | ECHO | ECHONL); + tcsetattr(STDIN_FILENO, TCSANOW, &newterm); + + ecran ecr = {20, 80}; + + setvbuf(stdin, NULL, _IONBF, 4); + + printf("\033[?1049h"); // écran alternatif + + if (read_cgu(ecr)) + { + //prompt_names(ecr, L"Joueurs ?", 2); + jouer(ecr, 2); + } + + + printf("\033[?1049l"); // écran initial + tcsetattr(STDIN_FILENO, TCSANOW, &oldterm); + + flush_stdin(); + + return 0; +} diff --git a/src/display.c b/src/display.c new file mode 100644 index 0000000..ec809cf --- /dev/null +++ b/src/display.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include + +#define ATOM_SIZE 3 + +typedef wchar_t pixel; + +typedef struct { + int width, height; + pixel **pixels; +} ecran; + +ecran* creer_ecran(int width, int height) +{ + ecran* ecr = malloc(sizeof(ecran)); + + ecr->width = width; + ecr->height = height; + ecr->pixels = malloc(height * sizeof(pixel)); + + for (int i=0; iheight; i++) + ecr->pixels[i] = malloc((width+1) * sizeof(pixel)); + + return ecr; +} + +void detruire_ecran(ecran* ecr) +{ + for (int i=0; iheight; i++) + free(ecr->pixels[i]); + + free(ecr->pixels); + free(ecr); +} + +void set_px(pixel px, int x, int y, ecran *ecr) +{ + ecr->pixels[y][x] = px; +} + +pixel get_px(int x, int y, ecran *ecr) +{ + return ecr->pixels[y][x]; +} + +void print_ecran(ecran *ecr) +{ + for (int i=0; iheight; i++) + printf("%ls\n", ecr->pixels[i]); +} + + +int main(void) +{ + setlocale(LC_ALL, ""); + + ecran *ecr = creer_ecran(100, 50); + + print_ecran(ecr); + + detruire_ecran(ecr); +} diff --git a/src/grille.c b/src/grille.c new file mode 100644 index 0000000..dc1b100 --- /dev/null +++ b/src/grille.c @@ -0,0 +1,473 @@ +/* + * 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 . + */ + +#include // pour la gestion des fichiers +#include +#include + +#include "grille.h" + +/* +void print_tab(jeton *tab, int n) +{ + for (int i=0; i %x (%d)\n", (void*)&tab[i], tab[i], tab[i]); + printf("\n"); +} + +void print_colonne(colonne *col) +{ + for (int i=0; icapacite; i++) + putc(repr_jeton(col->jetons[i]), stdout); + putc('\n', stdout); +} +*/ + +void init_zeros(jeton* ptr, int count) +{ + for (int i=0; ijetons = malloc(capacite*sizeof(jeton)); + if (col->jetons == NULL) + { + free(col); + return NULL; + } + + init_zeros(col->jetons, capacite); + + 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 + + col->jetons = jetons_nouv; + + // on met des zéros dans la partie nouvellement attribuée + init_zeros(col->jetons + col->capacite, diff_taille); + + // free est appelée par realloc et les éléments sont copiés par realloc + col->capacite += diff_taille; + + return true; + +} + +bool ajouter_jeton_col(jeton j, colonne *col, int* y) +{ + if (col->hauteur >= col->capacite) + if (!agrandir_colonne(Y_BLOCK_SIZE, col)) + return false; + + col->jetons[col->hauteur] = j; + col->hauteur++; + + if (y != NULL) *y = col->hauteur - 1; + + return true; +} + +jeton get_jeton_col(int indice, colonne *col) +{ + return (indice < col->hauteur && indice >= 0) ? col->jetons[indice] : 0; +} + +void detruire_colonne(colonne *col) +{ + if (col == NULL) return; + + free(col->jetons); + free(col); +} + +/* + * 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 + */ + +grille *creer_grille() +{ + /* On divise largeur en deux : + * + * |-----------------------------|-----------------------------| + * negatifs 0 positifs + * + * d'où n_positifs = largeur/2 + largeur%2 + * n_negatifs = largeur/2 + * + * de telle sorte que: + * n_negatifs + n_positifs = largeur + * + * Ex : + * - L'intervalle [-10, 9] de cardinal 20 se découpe en + * 10 nombres positifs [0, 9] et 10 nombres négatifs [-10, -1] représenté + */ + + grille *g = malloc(sizeof(grille)); + if (g == NULL) + return NULL; + + g->n_positifs = X_BLOCK_SIZE/2 + X_BLOCK_SIZE%2; + g->n_negatifs = X_BLOCK_SIZE/2; + g->positifs = malloc(g->n_positifs * sizeof(colonne*)); + g->negatifs = malloc(g->n_negatifs * sizeof(colonne*)); + + if (g->positifs == NULL || g->negatifs == NULL) + { + free(g->positifs); + free(g->negatifs); + free(g); + return NULL; + } + + bool echec_allocation = false; + + for (int i=0; i < g->n_positifs; i++) + { + g->positifs[i] = creer_colonne(Y_BLOCK_SIZE); + if (g->positifs[i] == NULL) + echec_allocation = true; + } + + 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; + } + + + // si une colonne n'a pas pu être crée, on détruit la grille + if (echec_allocation) + { + detruire_grille(g); + return 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; + for (int i=0; in_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); +} + + +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) : 0; +} + +int ceil_div(int a, int b) +{ + return (a%b == 0) ? (a/b) : (a/b + 1); +} + +int next_step(int x, int step) +{ + return step * ceil_div(x, step); +} + + +bool ajouter_jeton(jeton j, int x, int *y, grille *g) +{ + if (x >= 0 && x >= g->n_positifs) + { + if (!(etendre_droite(next_step(x - g->n_positifs + 1, X_BLOCK_SIZE), g))) + return false; + } + + if (x < 0 && ~x >= g->n_negatifs) + { + if (!(etendre_gauche(next_step(~x - g->n_negatifs + 1, X_BLOCK_SIZE), g))) + return false; + } + + return ajouter_jeton_col(j, get_colonne(x, g), y); +} + + +void detruire_grille(grille *g) +{ + for (int i=0; i < g->n_positifs; i++) + detruire_colonne(g->positifs[i]); + + for (int i=0; i < g->n_negatifs; i++) + detruire_colonne(g->negatifs[i]); + + free(g); +} + + +bool gagnant_aux(int x, int y, int dx, int dy, int n, grille *g) +{ + if (n==1) + return true; + + return (get_case(x+dx, y+dy, g) == get_case(x, y, g) && get_case(x, y, g) != 0) + ? gagnant_aux(x+dx, y+dy, dx, dy, n-1, g) + : false; +} + +bool gagnant(int x, int y, int N, grille *g) +{ + /* Fonction qui renvoie si le dernier joueur gagne + * en fonction de la position du dernier joueur. + * + * x: abscisse du dernier jeton posé + * y: ordonnée du dernier jeton posé + * g: grille de travail + */ + + for (int dx = -1; dx < 2; dx++) + for (int dy = -1; dy < 2; dy++) + if ((dx != 0 || dy != 0) && gagnant_aux(x, y, dx, dy, N, g)) + return true; + + return false; +} + +void sauvegarder_colonne(FILE *stream, colonne *c) +{ + for (int i=0; ihauteur; i++) + if (c->jetons[i] != 0) + fprintf(stream, "%d\n", c->jetons[i]); +} + +void sauvegarder(FILE *stream, grille *g) +{ + for (int i=0; in_positifs; i++) + { + fprintf(stream, "%d;", i); + sauvegarder_colonne(stream, g->positifs[i]); + } + + for (int i=0; in_negatifs; i++) + { + fprintf(stream, "%d;", ~i); + sauvegarder_colonne(stream, g->negatifs[i]); + } +} + +grille *charger(FILE *stream) +{ + grille *g = creer_grille(); + + int col, joueur; + while (fscanf(stream, "%d;%d", &col, &joueur) == 3) + ajouter_jeton(joueur, col, NULL, g); + + return g; +} + +// =========================================== TEST ================================================= + +/* + + +int test_colonne() +{ + colonne *col = creer_colonne(Y_BLOCK_SIZE); + print_colonne(col); + + int y; + for (int i=0; i<241; i++) + { + if (ajouter_jeton_col((i%2==0) ? ROUGE : BLEU, col, &y)) + printf("Jeton ajouté à hauteur %d.\n", y); + else + fprintf(stderr, "Erreur dans l'ajout d'un jeton.\n"); + } + + print_colonne(col); + + detruire_colonne(col); + + return 0; +} + +void print_grille_temp(grille *g) +{ + printf("n_positifs : %d ; n_negatifs : %d\n", g->n_positifs, g->n_negatifs); + for (int i=-g->n_negatifs; in_positifs; i++) + { + printf("% 5d | ", i); + print_colonne(get_colonne(i, g)); + } + +} + +int test_grille() +{ + grille *g = creer_grille(); + + int y; + for (int i=0; i<6; i++) + { + ajouter_jeton(BLEU, 0, &y, g); + + print_grille_temp(g); + printf("\n\n\n\n\n"); + + if (gagnant(0, y, 5, g)) + printf("Le dernier joueur a gagné.\n"); + } + + + + detruire_grille(g); + + return 0; +} + + +jeton jouer() +{ + grille *g = creer_grille(); + int tour = 0; + + int x, y; + do { + print_grille_temp(g); + + printf("Test %c\n", repr_jeton(get_case(-50, -50, g))); + + printf("Tour %d, joueur %c. Entrer colonne : ", tour, repr_jeton((jeton)(tour%2 + 1))); + scanf("%d", &x); + + ajouter_jeton((jeton)(tour%2 + 1), x, &y, g); + + tour++; + } while (!gagnant(x, y, 5, g)); + + print_grille_temp(g); + + jeton gagnant = (tour-1)%2 + 1; + printf("Le gagnant est %c.\n", repr_jeton(gagnant)); + + return gagnant; +} + + +int main(void) +{ + jouer(); + return 0; +} +*/ diff --git a/grille.h b/src/grille.h similarity index 56% rename from grille.h rename to src/grille.h index bc43ea7..e424ebd 100644 --- a/grille.h +++ b/src/grille.h @@ -1,14 +1,13 @@ #ifndef GRILLE_H_INCLUDED #define GRILLE_H_INCLUDED -#define X_BLOCK_SIZE 20 +#include +#include + +#define X_BLOCK_SIZE 10 #define Y_BLOCK_SIZE 10 -typedef enum jeton { - VIDE = 0, - BLEU = 1, - ROUGE = 2 -} jeton; +typedef int jeton; typedef struct colonne { int hauteur; @@ -24,14 +23,22 @@ typedef struct grille { } grille; -grille *creer_grille(int largeur); +grille *creer_grille(); colonne *get_colonne(int i, grille *g); jeton get_case(int x, int y, grille *g); -bool ajouter_jeton(jeton j, int x, grille *g); +bool ajouter_jeton(jeton j, int x, int *y, grille *g); void detruire_grille(grille *g); +bool gagnant(int x, int y, int N, grille *g); + +jeton get_case(int x, int y, grille *g); + +void sauvegarder(FILE *stream, grille *g); + +grille *charger(FILE *stream); + #endif /* GRILLE_H_INCLUDED */