-
-
Save Meithal/0eb231cdeea1830af3a03956c0ab4f03 to your computer and use it in GitHub Desktop.
puissance 4 de zeste de savoir
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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