Skip to content

Instantly share code, notes, and snippets.

@Meithal
Created June 14, 2018 09:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Meithal/0eb231cdeea1830af3a03956c0ab4f03 to your computer and use it in GitHub Desktop.
Save Meithal/0eb231cdeea1830af3a03956c0ab4f03 to your computer and use it in GitHub Desktop.
puissance 4 de zeste de savoir
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <string.h>
#include <memory.h>
#define LARGEUR_DAMIER (7)
#define HAUTEUR_DAMIER (6)
#define LONGUEUR_DAMIER (LARGEUR_DAMIER * HAUTEUR_DAMIER)
#define LONGUEUR_VICTOIRE (4)
#define NOMBRE_JOUEURS (2)
#define CASE_VIDE ' '
#define CASE_JOUEUR_1 'X'
#define CASE_JOUEUR_2 'O'
enum {
DIRECTION_NORD = 0,
DIRECTION_NORD_EST = 1,
DIRECTION_EST = 2,
DIRECTION_SUD_EST = 3,
DIRECTION_SUD = 4,
DIRECTION_SUD_OUEST = 5,
DIRECTION_OUEST = 6,
DIRECTION_NORD_OUEST = 7,
NOMBRE_DIRECTIONS = 8
};
struct case_damier {
char contenu;
long index;
long ligne;
long colonne;
} damier[LARGEUR_DAMIER * HAUTEUR_DAMIER];
struct curseur {
struct case_damier * soi;
struct case_damier * directions[NOMBRE_DIRECTIONS];
} curseur;
struct joueur {
char humain;
char symbole;
int poids_colonne[LARGEUR_DAMIER];
int poids_max;
int index_max;
} joueurs[NOMBRE_JOUEURS];
int verbose = 0;
void assigne_curseur(struct case_damier * soi) {
for (int i = 0 ; i < NOMBRE_DIRECTIONS ; ++i) {
curseur.directions[i] = NULL;
}
curseur.soi = soi;
if (soi->ligne > 0)
curseur.directions[DIRECTION_NORD] = &damier[soi->index - LARGEUR_DAMIER];
if (soi->ligne > 0 && soi->colonne < LARGEUR_DAMIER - 1)
curseur.directions[DIRECTION_NORD_EST] = &damier[soi->index - LARGEUR_DAMIER + 1];
if (soi->colonne < LARGEUR_DAMIER - 1)
curseur.directions[DIRECTION_EST] = &damier[soi->index + 1];
if (soi->ligne < HAUTEUR_DAMIER - 1 && soi->colonne < LARGEUR_DAMIER - 1)
curseur.directions[DIRECTION_SUD_EST] = &damier[soi->index + LARGEUR_DAMIER + 1];
if (soi->ligne < HAUTEUR_DAMIER - 1)
curseur.directions[DIRECTION_SUD] = &damier[soi->index + LARGEUR_DAMIER];
if (soi->ligne < HAUTEUR_DAMIER - 1 && soi->colonne > 0)
curseur.directions[DIRECTION_SUD_OUEST] = &damier[soi->index + LARGEUR_DAMIER - 1];
if (soi->colonne > 0)
curseur.directions[DIRECTION_OUEST] = &damier[soi->index - 1];
if (soi->colonne > 0 && soi->ligne > 0)
curseur.directions[DIRECTION_NORD_OUEST] = &damier[soi->index - LARGEUR_DAMIER - 1];
}
int gagnant() {
char symbole;
for (int i = 0; i < LONGUEUR_DAMIER ; ++i) {
if (damier[i].contenu == CASE_VIDE) continue;
symbole = damier[i].contenu;
for (int direction = 0 ; direction < NOMBRE_DIRECTIONS ; direction ++) {
int longueur = 1;
assigne_curseur(&damier[i]);
while(curseur.directions[direction] && curseur.directions[direction]->contenu == symbole) {
assigne_curseur(curseur.directions[direction]);
if(++longueur == LONGUEUR_VICTOIRE) {
if(symbole == CASE_JOUEUR_1) return 1;
if(symbole == CASE_JOUEUR_2) return 2;
}
}
}
}
return 0;
}
enum {
DOIT_AFFICHER_NUMEROS = (unsigned)0x01, /* 0b00001 */
DOIT_AFFICHER_CASE = (unsigned)0x02, /* 0b01000 */
DOIT_AFFICHER_FIN_LIGNE = (unsigned)0x04, /* 0b00010 */
DOIT_AFFICHER_SEPARATION_HORIZONTALE = (unsigned)0x08, /* 0b00100 */
DOIT_AFFICHER_DEBUG = (unsigned)0x10 /* 0b10000 */
};
void afficher_damier() {
unsigned int DRAPEAUX;
unsigned int TACHE;
int damier_i = -1;
do {
DRAPEAUX = 0;
if (damier_i == -1 || damier_i == LONGUEUR_DAMIER)
DRAPEAUX |= DOIT_AFFICHER_NUMEROS;
if (damier_i >= 0 && damier_i < LONGUEUR_DAMIER)
DRAPEAUX |= DOIT_AFFICHER_CASE;
if (((damier_i + 1) % LARGEUR_DAMIER) == 0 && damier_i != -1)
DRAPEAUX |= DOIT_AFFICHER_FIN_LIGNE;
if (damier_i == -1 || ((damier_i + 1) % LARGEUR_DAMIER) == 0)
DRAPEAUX |= DOIT_AFFICHER_SEPARATION_HORIZONTALE;
if (damier_i == LONGUEUR_DAMIER)
if (verbose)
DRAPEAUX |= DOIT_AFFICHER_DEBUG;
TACHE = 0;
while (DRAPEAUX) {
for (unsigned i = 0 ; i < 8 ; ++i) {
if (DRAPEAUX & ((unsigned) 1 << i)) {
TACHE = (unsigned) 1 << i;
DRAPEAUX ^= (unsigned) 1 << i;
break;
}
}
switch (TACHE) {
case DOIT_AFFICHER_NUMEROS:
for (int j = 1; j <= LARGEUR_DAMIER; ++j) {
printf(" %d ", j);
}
putchar('\n');
break;
case DOIT_AFFICHER_CASE:
printf("| %c ", damier[damier_i].contenu);
fflush(stdout);
break;
case DOIT_AFFICHER_FIN_LIGNE:
puts("|");
break;
case DOIT_AFFICHER_SEPARATION_HORIZONTALE:
for (int j = 1; j <= LARGEUR_DAMIER; ++j) {
printf("+---");
}
puts("+");
break;
case DOIT_AFFICHER_DEBUG:
for (int joueur_i = 0; joueur_i < NOMBRE_JOUEURS; ++joueur_i) {
for (int j = 1; j <= LARGEUR_DAMIER; ++j) {
printf(" %d ", joueurs[joueur_i].poids_colonne[j]);
}
putchar(joueurs[joueur_i].symbole);
putchar('\n');
}
break;
default:
break;
}
}
} while (damier_i++ <= LONGUEUR_DAMIER);
}
void faire_tomber_curseur_jusque_case_vide(long colonne) {
assigne_curseur(&damier[colonne]);
while (curseur.directions[DIRECTION_SUD] != NULL
&& curseur.directions[DIRECTION_SUD]->contenu == CASE_VIDE) {
assigne_curseur(curseur.directions[DIRECTION_SUD]);
}
}
int longueur_suite(struct joueur * pJoueur) {
int longueur;
struct case_damier * position_initiale = curseur.soi;
int plus_grande_longueur = 1;
int sens[4] = {1, 1, 1, 1};
for (int direction = 0 ; direction < NOMBRE_DIRECTIONS ; direction++) {
assigne_curseur(position_initiale);
longueur = 0;
while(curseur.directions[direction] != NULL
&& curseur.directions[direction]->contenu == pJoueur->symbole) {
assigne_curseur(curseur.directions[direction]);
++longueur;
}
sens[direction % 4] += longueur;
if (sens[direction % 4] > plus_grande_longueur) plus_grande_longueur = sens[direction % 4];
}
return plus_grande_longueur;
}
void ponderer_colonnes(void) {
int poids;
for(int i_joueur = 0 ; i_joueur < NOMBRE_JOUEURS ; i_joueur++) {
joueurs[i_joueur].index_max = LARGEUR_DAMIER / 2;
joueurs[i_joueur].poids_max = -1;
for(int i_colonne = 0 ; i_colonne < LARGEUR_DAMIER ; i_colonne++) {
joueurs[i_joueur].poids_colonne[i_colonne] = -1;
if(damier[i_colonne].contenu != CASE_VIDE) continue;
faire_tomber_curseur_jusque_case_vide(i_colonne);
poids = longueur_suite(&joueurs[i_joueur]);
joueurs[i_joueur].poids_colonne[i_colonne] = poids;
if (poids > joueurs[i_joueur].poids_max) {
joueurs[i_joueur].poids_max = poids;
joueurs[i_joueur].index_max = i_colonne;
continue;
}
if (poids == joueurs[i_joueur].poids_max) {
if ((rand() % 100) > 80) {
joueurs[i_joueur].index_max = i_colonne;
}
}
}
}
}
int choix_ia(struct joueur * pJoueur, struct joueur * pEnnemi) {
int choix = pJoueur->index_max;
if (pEnnemi->poids_max > pJoueur->poids_max || pEnnemi->poids_max == LONGUEUR_VICTOIRE)
choix = pEnnemi->index_max; /* On contre l'ennemi */
return choix;
}
int main(int argc, char * argv[]) {
char char_rec = '\0';
time_t the_time = time(NULL);
if (the_time == -1) {
puts("Cannot initialize the time");
return EXIT_FAILURE;
}
srand((unsigned int) the_time);
joueurs[0].symbole = CASE_JOUEUR_1;
joueurs[1].symbole = CASE_JOUEUR_2;
for (int i = 0 ; i < LONGUEUR_DAMIER ; i++) {
damier[i].contenu = CASE_VIDE;
damier[i].index = i;
damier[i].colonne = i % LARGEUR_DAMIER;
damier[i].ligne = i / LARGEUR_DAMIER;
}
for(int arg_i = 1 ; arg_i < argc ; ++arg_i) {
if (strcmp("-v", argv[arg_i]) == 0) {
verbose = 1;
}
}
afficher_damier();
for (int i = 0 ; i < NOMBRE_JOUEURS ; ++i) {
do {
printf("\nJoueur %d humain ou ordinateur ? (H/O)\n> ", i + 1);
scanf(" %c%*[^\n]", &char_rec);
if (tolower(char_rec) == 'h') {
joueurs[i].humain = '\1';
}
} while (tolower(char_rec) != 'h' && tolower(char_rec) != 'o');
}
struct joueur *joueur_actif = &joueurs[1];
struct joueur *joueur_ennemi;
long colonne_jouee;
int joueur_gagnant;
while(!(joueur_gagnant = gagnant())) {
joueur_ennemi = joueur_actif;
joueur_actif = (joueur_actif == &joueurs[0]) ? &joueurs[1] : &joueurs[0];
ponderer_colonnes();
if (joueur_actif->humain) {
printf(
"Au joueur %ld (%c) de jouer (un chiffre entre 1 et 7)\n> ",
((joueur_actif - &joueurs[0]) + 1),
joueur_actif->symbole
);
while (1) {
scanf(" %c%*[^\n]", &char_rec);
if (char_rec >= '1' && char_rec <= '7') {
colonne_jouee = strtol(&char_rec, NULL, 10) - 1;
if(damier[colonne_jouee].contenu == CASE_VIDE)
break;
else {
puts("Colonne remplie, veuillez en choisir une autre.");
}
} else {
puts("Chiffre invalide.");
}
}
} else {
colonne_jouee = choix_ia(joueur_actif, joueur_ennemi);
printf("L'ordinateur joue pour le joueur %ld (%c)\n",
((joueur_actif - &joueurs[0]) + 1),
joueur_actif->symbole
);
getchar();
}
faire_tomber_curseur_jusque_case_vide(colonne_jouee);
curseur.soi->contenu = joueur_actif->symbole;
afficher_damier();
if(joueur_actif->poids_max == -1 && joueur_ennemi->poids_max == -1) {
joueur_gagnant = -1;
break;
}
}
if (joueur_gagnant > 0)
printf("Le joueur %d (%c) a gagné", joueur_gagnant, joueur_actif->symbole);
else
puts("Egalité !");
getchar();
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment