Skip to content

Instantly share code, notes, and snippets.

@Meithal
Last active June 15, 2018 21:17
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/265c6498f729275bc10da3b9bb69260e to your computer and use it in GitHub Desktop.
Save Meithal/265c6498f729275bc10da3b9bb69260e to your computer and use it in GitHub Desktop.
puissance 4
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.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 joueur_actif_i = 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->colonne < LARGEUR_DAMIER - 1)
curseur.directions[DIRECTION_NORD_EST] = &damier[soi->index - LARGEUR_DAMIER + 1];
if (soi->colonne > 0)
curseur.directions[DIRECTION_NORD_OUEST] = &damier[soi->index - LARGEUR_DAMIER - 1];
}
if (soi->ligne < HAUTEUR_DAMIER - 1) {
curseur.directions[DIRECTION_SUD] = &damier[soi->index + LARGEUR_DAMIER];
if (soi->colonne > 0) {
curseur.directions[DIRECTION_SUD_OUEST] = &damier[soi->index + LARGEUR_DAMIER - 1];
}
if (soi->colonne < LARGEUR_DAMIER - 1)
curseur.directions[DIRECTION_SUD_EST] = &damier[soi->index + LARGEUR_DAMIER + 1];
}
if (soi->colonne > 0)
curseur.directions[DIRECTION_OUEST] = &damier[soi->index - 1];
if (soi->colonne < LARGEUR_DAMIER - 1) {
curseur.directions[DIRECTION_EST] = &damier[soi->index + 1];
}
}
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 */
};
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;
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;
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) > 70) {
joueurs[i_joueur].index_max = i_colonne;
}
}
}
}
}
int choix_ia() {
int choix = joueurs[joueur_actif_i].index_max;
for (int i = 0; i < NOMBRE_JOUEURS; ++i) {
if (i == joueur_actif_i) continue;
if (joueurs[i].poids_max > joueurs[joueur_actif_i].poids_max || joueurs[i].poids_max == LONGUEUR_VICTOIRE)
choix = joueurs[i].index_max; /* On contre l'ennemi */
}
return choix;
}
int main(int argc, char * argv[]) {
char char_rec = '\0';
long colonne_jouee;
int jeu_fini_egalite = 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;
}
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');
}
while(1) {
ponderer_colonnes();
if (joueurs[joueur_actif_i].humain) {
printf(
"Au joueur %d (%c) de jouer (un chiffre entre 1 et 7)\n> ",
(joueur_actif_i + 1),
joueurs[joueur_actif_i].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) {
printf("Le joueur %d (%c) joue à la colonne %ld\n",
(joueur_actif_i + 1),
joueurs[joueur_actif_i].symbole,
colonne_jouee + 1
);
break;
}
else {
puts("Colonne remplie, veuillez en choisir une autre.");
}
} else {
puts("Chiffre invalide.");
}
}
} else {
colonne_jouee = choix_ia();
printf("L'ordinateur joue pour le joueur %d (%c) à la colonne %ld\n",
(joueur_actif_i + 1),
joueurs[joueur_actif_i].symbole,
colonne_jouee + 1
);
getchar();
}
faire_tomber_curseur_jusque_case_vide(colonne_jouee);
curseur.soi->contenu = joueurs[joueur_actif_i].symbole;
afficher_damier();
if(joueurs[joueur_actif_i].poids_colonne[colonne_jouee] >= LONGUEUR_VICTOIRE) {
break;
}
jeu_fini_egalite = 1;
for (int i = 0; i < LARGEUR_DAMIER; ++i) {
if(damier[i].contenu == CASE_VIDE) {
jeu_fini_egalite = 0;
break;
}
}
if (jeu_fini_egalite) {
joueur_actif_i = -1;
break;
}
joueur_actif_i = (joueur_actif_i + 1) % NOMBRE_JOUEURS;
}
if (joueur_actif_i >= 0)
printf("Le joueur %d (%c) a gagné", joueur_actif_i, joueurs[joueur_actif_i].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