Puissance 4 en C [Fermé]

Signaler
Messages postés
10
Date d'inscription
dimanche 4 mai 2008
Statut
Membre
Dernière intervention
18 mai 2009
-
 maryouma08 -
Bonjour,
je suis actuellement sur mon projet à la fac qui est de créer le jeu puissance 4 en C. Donc j'aimerais avoir votre avis sur mon programme, j'accepte toutes les critiques ;)

Le voici:

#include <stdio.h>
#include <stdlib.h>

#define LIGNE 7
#define COLONNE 6
/*initialisation de certaines variable de programme*/
char grille[LIGNE][COLONNE];
char X='X';
char O='O';
char j1[20];
char j2[20];
int resultat;
char rejouer;



void menu(){

printf("\n *******************************************************\n");
printf(" ********** **********\n");
printf(" *** ***\n");
printf(" * PUISSANCE 4 *\n");
printf(" * Faycal et Mounir *\n");
printf(" *** ***\n");
printf(" ********** **********\n");
printf(" *******************************************************\n");
/*Les joueurs choisissent leurs noms*/
printf("Nom du Joueur1?");
scanf("%s", &j1);
printf("Nom du Joueur2?");
scanf("%s",&j2);
}



void affichagegrille(){
/*Affichage de la grille*/
int i,j;

printf("| 0 | 1 | 2 | 3 | 4 | 5 | 6 |\n");
printf("|---|---|---|---|---|---|---|\n");
for(i=0; i<COLONNE; i++){
printf("|");
for(j=0; j<LIGNE; j++){
printf(" %c |", grille[j][i]);
}
printf("\n");
printf("|---|---|---|---|---|---|---|\n");
}
printf("| 0 | 1 | 2 | 3 | 4 | 5 | 6 |\n\n\n");
}





void remplissage(){
/*Remplissage de la grille pour le debut du jeu:
chaque cellule contient un espace*/
int m,n,k=1,l;

for(m=0; m<LIGNE; m++){
for(n=0; n<COLONNE; n++){
grille[m][n]=' ';
}
}
}




void coup(char joueur[20], char grille[LIGNE][COLONNE]){

int abscice,p,resultat;
/*Le joueur choisi la colonne*/
printf("A %s de jouer! Entrez les coordonnees: ", joueur);
printf("\nChoisissez une colonne! => ");
scanf("%d", &abscice);
/*Tant que la colonne choisie est pleine, le joueur
doit en choisir une autre*/
while((grille[abscice][0]==X) || (grille[abscice][0]==O)){
printf("La colonne est pleine!\n\n");
printf("Choisissez une colonne! => ");
scanf("%d", &abscice);
}
/*Tant que le joueur n'entre pas une colonne valide,
il doit en choisir une autre*/
while((abscice>6) || (abscice<0)){
printf("Entrez une colonne correct!\n\n");
printf("Choisissez une colonne! => ");
scanf("%d", &abscice);
}
/*Verifie si la premiere case (de la derniere ligne
de la grille) est vide et choisi celle au dessus dans
le cas contraire (qui sera aussi verifiée)*/
for(p=5; p>=0; p--){
if(grille[abscice][p]==' '){
if(joueur==j1){
grille[abscice][p]=X;
break;
}
else{
grille[abscice][p]=O;
break;
}
}
}
}




int verification(char grille[LIGNE][COLONNE]){

int j,k;
/*Verification cellule par celulle et renvoie 1 s'il y a alignement*/
for(j=0; j<LIGNE; j++){
for(k=5; k>=0; k--){
/*Verification d'un alignement vertical*/
if(k>=3){
if((grille[j][k]==X && grille[j][k-1]==X
&& grille[j][k-2]==X && grille[j][k-3]==X)
|| (grille[j][k]==O && grille[j][k-1]==O
&& grille[j][k-2]==O && grille[j][k-3]==O)){
return 1;
}
}
/*Verification d'un alignement horizontal*/
else if(j<=3){
if((grille[j][k]==X && grille[j+1][k]==X
&& grille[j+2][k]==X && grille[j+3][k]==X)
|| (grille[j][k]==O && grille[j+1][k]==O
&& grille[j+2][k]==O && grille[j+3][k]==O)){
return 1;
}
}
/*Verification d'un alignement diagonal de haut en bas*/
else if((k<=2) && (j<=3)){
if((grille[j][k]==X && grille[j+1][k+1]==X
&& grille[j+2][k+2]==X && grille[j+3][k+3]==X)
|| (grille[j][k]==O && grille[j+1][k+1]==O
&& grille[j+2][k+2]==O && grille[j+3][k+3]==O)){
return 1;
}
}
/*Verification d'un alignement diagonal de bas en haut*/
else if((k>=3) && (j<=3)){
if((grille[j][k]==X && grille[j+1][k-1]==X
&& grille[j+2][k-2]==X && grille[j+3][k-3]==X)
|| (grille[j][k]==O && grille[j+1][k-1]==O
&& grille[j+2][k-2]==O && grille[j+3][k-3]==O)){
return 1;
}
}

else{
return 0;
}
}
}
}



int main(){

int compteur=0;
rejouer='o';

menu();

do{
printf("Que la partie commence!\n\n\n\n");
remplissage();
affichagegrille();
do{
coup(j1,grille);
affichagegrille();
compteur++;
if(compteur>=7){
resultat=verification(grille);
if(resultat==1){
printf("Bien joue %s! Vous remportez la partie!",j1);
compteur=43;
}
}

if(resultat!=1){
coup(j2,grille);
affichagegrille(grille);
compteur++;
if(compteur>=8){
resultat=verification(grille);
if(resultat==1){
printf("Bien joue %s! Vous remportez la partie!",j2);
compteur=43;
}
}
}
}
while(compteur<42);

if(compteur==42){
printf("Match Nul!");
}
printf("Voulez-vous rejouer la partie? o=oui ou n=non",rejouer);
scanf("%c",&rejouer);
}
while(rejouer=='o');
}


Par contre j'ai un petit problème pour la vérification et dès que je trouve le problème je vous met le nouveau programme.

Merci à tous pour vos réponses :)

11 réponses

salut;

je vient de lire vos codes c'est génial donc est que vous pouvez m'aider à faire un projet de puissance 4 en c++ ou bien à m'expliquer un peut le code déjà écrit.
3
Merci

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

CCM 60511 internautes nous ont dit merci ce mois-ci

Messages postés
496
Date d'inscription
lundi 17 septembre 2007
Statut
Membre
Dernière intervention
22 juin 2010
123
Je pointais ceci :
void coup(char joueur[20], char grille[LIGNE][COLONNE]){

    /*Le joueur choisi la colonne*/
	printf("A %s de jouer! Entrez les coordonnees: ", joueur);
	printf("\nChoisissez une colonne! => ");
	scanf("%d", &abscice);
    /*Tant que la colonne choisie est pleine, le joueur
    doit en choisir une autre*/
	while((grille[abscice][0]==X) || (grille[abscice][0]==O)){


Si l'utilisateur rentre n'importe quoi le programme essaie tout de suite d'accéder à une case hors dimensions... aïe !


M.
Messages postés
496
Date d'inscription
lundi 17 septembre 2007
Statut
Membre
Dernière intervention
22 juin 2010
123
La vérification paraît bizarre en effet.

Un petit point qui pourrait simplifier. Seul le joueur qui vient de jouer peut avoir gagné, donc inutile de faire la vérification pour le joueur qui n'est pas le joueur actif. (Simplifions la fonction ^^)

Autre point, les dimensions de la grille ne sont pas vérifiées. Si le joueur joue en colonne 0, la fonction contrôle les colonnes -3, -2 et -1. (Du moins je pense)

Je pense que le mieux serait de faire quatre séries de tests (horizontal, vertical, et les deux diagonales)
Ils peuvent être faits avec des boucles sinon des if.
Le but serait pour une direction donnée (prennons horizontal pour l'exemple) de compter à partir du pion joué le nombre de pions successifs identiques (ça évite un paramètre pour connaître le joueur courant) à gauche et à droite de la case ciblée. On refait la somme.

En bref:

iLigne et iColonne les coordonnées du pion joué

i, j la ligne et la colonne testée
prev = 0, post = 0 le nombre de pions identiques successifs avant et après.



// Avant
i = -1 // horizontal prev
j = 0 // horizontal

Tant que ( i > -4 ) _ET_ (iLigne + i) >= 0 _ET_ grille[iLigne + i][iColonne] == grille[iLigne][iColonne]
    prev++
    i--; // horizontal prev



// après
i = 1 // // horizontal post
j = 0 // horizontal

Tant que  ( i < 4 ) _ET_ (iLigne + i) < COLONNE _ET_ grille[iLigne + i][iColonne] == grille[iLigne][iColonne]
    post++
    i++; // horizontal post



// Résultat
if ( prev + post >= 3 )
   ...


Je fais ça un peu au feelling , ça va agrandir le code un peu... Il y a peut-être moyen de faire plus court ? Vu que la fonction peut vite rallonger en mettant les tests pour la verticale et les deux diagonales, je mettrais chacun des quatre test dans des fonctions séparées et gouvernées par la fonction de vérification principale.

Tout ça reste un avis personnel.

M.

Messages postés
10
Date d'inscription
dimanche 4 mai 2008
Statut
Membre
Dernière intervention
18 mai 2009
1
Alors voilà, après avoir suivi tes précieux conseils, j'ai fini la modification de mon programme.

Par contre lorsque mon programme tente d'accéder a ma fonction verification, le programme de bloque et je ne peut plus rien faire.

J'ai eu beau chercher toute les erreur possibles qui conduisent le programme a ce blocage mais en vain...

Voici ma fonction:

            /*Verification d'un alignement vertical*/
int vertical(int j, int k){
        if(k>=3 && k<=5){
				if(grille[j][k]==grille[j][k-1]==grille[j][k-2]==grille[j][k-3]){
                    return 1;
                }
        }
        return 0;
}


            /*Verification d'un alignement horizontal*/
int honrizontal(int j, int k){
        if(j<=3 && j>=0){
                if(grille[j][k]==grille[j+1][k]==grille[j+2][k]==grille[j+3][k]){
                    return 1;
                }
        }
        return 0;
}

            /*Verification d'un alignement diagonal de haut en bas*/
int diagonalhb(int j, int k){
        if(k<=2 && k>=0 && j<=3 && j>=0){
                if(grille[j][k]==grille[j+1][k+1]==grille[j+2][k+2]==grille[j+3][k+3]){
                    return 1;
				}
        }
        return 0;
}

            /*Verification d'un alignement diagonal de bas en haut*/
int diagonalbh(int j, int k){
        if(k>=3 && k<=5 && j<=3 && j>=0){
                if(grille[j][k]==grille[j+1][k-1]==grille[j+2][k-2]==grille[j+3][k-3]){
                    return 1;
				}
        }
        return 0;
}


int verification(char grille[LIGNE][COLONNE], int j, int k){

    int i,p;
    /*Verification de la cellule jouée et renvoie 1 s'il y a alignement*/
    for(i=0;i<=3;i++){
        p=vertical(j,k-i);
        if(p==1){
            return 1;
        }
    }

    for(i=0;i<=4;i++){
        p=honrizontal(j+i,k);
        if(p==1){
            return 1;
        }
    }

    for(i=0;i<=3;i++){
        p=diagonalhb(j+i,k+i);
        if(p==1){
            return 1;
        }
    }

    for(i=0;i<=3;i++){
        p=diagonalbh(j-i,k-i);
        if(p==1){
            return 1;
        }
    }

    return 0;
}


Donc voila je pensais que l'erreur venait du fait que mes fonction essayaient d'accéder à des coordonnées hors tableau or celles-ci sont controllées par des if...


Messages postés
1929
Date d'inscription
vendredi 21 avril 2006
Statut
Membre
Dernière intervention
5 août 2015
112
int verification(char grille[LIGNE][COLONNE]){
tu peux écrire :
int verification(char **grille){

Sinon bonne programmation.
Ne pas hésiter de mettre des commentaires !
Messages postés
10
Date d'inscription
dimanche 4 mai 2008
Statut
Membre
Dernière intervention
18 mai 2009
1
Ah j'ai essayé de mettre le plus de commentaire possible mais j'ai oublié les commentaires de la fonction main ^^' je vais régler ceci... :)
Messages postés
496
Date d'inscription
lundi 17 septembre 2007
Statut
Membre
Dernière intervention
22 juin 2010
123
Bonjour,

Dans l'ensemble je suis d'accord aussi.

(sauf avec Tatou_38 pour son:
int verification(char grille[LIGNE][COLONNE]){
tu peux écrire :
int verification(char **grille){

Je doute fortement de la correspondance des deux codes pour accéder à une case)

Ce que je voyais plutôt est la fonction verification aussi mais... Il n'est pas nécessaire de vérifier toute la grille à chaque tour mais seulement si le dernier pion ajouté fait gagner celui qui l'a mis.

Pour un prochain projet c'est toujours bien d'isoler le coeur du programme (le moteur du jeu ici) et l'interface graphique. Cela donne plus de fonctions mais simplifie chacune d'elles. Accessoirement on obtient aussi un moteur de jeu ré-utilisable.

(sans trop y regarder je ne vois pas beaucoup de vérification des dimensions de la grille dans verification cela peut-être la cause du problème que tu as)

M.

EDIT.
Avec les caractères ASCII de 179 à 218 on peut faire de jolies choses ;-)
Messages postés
10
Date d'inscription
dimanche 4 mai 2008
Statut
Membre
Dernière intervention
18 mai 2009
1
Merci Mahmah pour tes conseils ^^ Je crois que je vais changer un peu ma fonction vérification afin de vérifier seulement le pion joué car ça ne sert a rien de vérifier toute les cellules.

Tu dis: (sans trop y regarder je ne vois pas beaucoup de vérification des dimensions de la grille dans verification cela peut-être la cause du problème que tu as)

=>Par contre je ne vois pas exactement ce que tu veux dire par là, car je ne vois toujours pas pourquoi ma fonction verification ne renvoie la valeur 1 que pour un alignement vertical :/

Je pense que je vais aussi changer l'interface graphique car je ne savais pas que l'on pouvait faire des caractères comme ceux que tu m'as conseillé, ça a l'air beaucoup plus intéressant ;)

Je vous tiens au courant dès que j'ai fini de modifier mon programme!

Merci encore :)
Messages postés
10
Date d'inscription
dimanche 4 mai 2008
Statut
Membre
Dernière intervention
18 mai 2009
1
Donc voila j'ai modifié mon programme mais il reste encore quelque problèmes...

Le voici:

#include <stdio.h>
#include <stdlib.h>

#define LIGNE 7
#define COLONNE 6
/*Initialisation de certaines variable du programme*/
char grille[LIGNE][COLONNE];
char X='X';
char O='O';
char j1[20];
char j2[20];
int resultat,compteur=0;
int abscice,p;
char rejouer='o';



void menu(){

	printf("\n      *******************************************************\n");
	printf("      **********                                   **********\n");
	printf("      ***                                                 ***\n");
	printf("      *                     PUISSANCE 4                     *\n");
	printf("      *                   Faycal et Mounir                  *\n");
	printf("      ***                                                 ***\n");
	printf("      **********                                   **********\n");
	printf("      *******************************************************\n");
    /*Les joueurs choisissent leurs noms*/
	printf("Nom du Joueur1?");
	scanf("%s", &j1);
	printf("Nom du Joueur2?");
	scanf("%s",&j2);
}



void affichagegrille(){
    /*Affichage de la grille*/
	int i,j;

    printf("| 0 | 1 | 2 | 3 | 4 | 5 | 6 |\n");
    printf("|---|---|---|---|---|---|---|\n");
	for(i=0; i<COLONNE; i++){
	    printf("|");
		for(j=0; j<LIGNE; j++){
			printf(" %c |", grille[j][i]);
		}
    printf("\n");
    printf("|---|---|---|---|---|---|---|\n");
	}
    printf("| 0 | 1 | 2 | 3 | 4 | 5 | 6 |\n\n\n");
}





void remplissage(){
    /*Remplissage de la grille pour le debut du jeu:
     chaque cellule contient un espace*/
	int m,n,k=1,l;

	for(m=0; m<LIGNE; m++){
		for(n=0; n<COLONNE; n++){
				grille[m][n]=' ';
		}
	}
}




void coup(char joueur[20], char grille[LIGNE][COLONNE]){

    /*Le joueur choisi la colonne*/
	printf("A %s de jouer! Entrez les coordonnees: ", joueur);
	printf("\nChoisissez une colonne! => ");
	scanf("%d", &abscice);
    /*Tant que la colonne choisie est pleine, le joueur
    doit en choisir une autre*/
	while((grille[abscice][0]==X) || (grille[abscice][0]==O)){
            printf("La colonne est pleine!\n\n");
            printf("Choisissez une colonne! => ");
            scanf("%d", &abscice);
	}
    /*Tant que le joueur n'entre pas une colonne valide,
     il doit en choisir une autre*/
	while((abscice>6) || (abscice<0)){
			printf("Entrez une colonne correct!\n\n");
			printf("Choisissez une colonne! => ");
			scanf("%d", &abscice);
	}
    /*Verifie si la premiere case (de la derniere ligne
     de la grille) est vide et choisi celle au dessus dans
     le cas contraire (qui sera aussi verifiée)*/
	for(p=5; p>=0; p--){
		if(grille[abscice][p]==' '){
			if(joueur==j1){
				grille[abscice][p]=X;
				break;
			}
			else{
				grille[abscice][p]=O;
				break;
			}
		}
	}
}




int verification(char grille[LIGNE][COLONNE], int j, int k){

    /*Verification de la cellule jouée et renvoie 1 s'il y a alignement*/
            /*Verification d'un alignement vertical*/
            if(k>=3){
				if((grille[j][k]==X && grille[j][k-1]==X
                    && grille[j][k-2]==X && grille[j][k-3]==X)
                    || (grille[j][k]==O && grille[j][k-1]==O
                    && grille[j][k-2]==O && grille[j][k-3]==O)){
                    return 1;
                }
			}
            /*Verification d'un alignement horizontal*/
			else if(j<=3){
				if((grille[j][k]==X && grille[j+1][k]==X
                    && grille[j+2][k]==X && grille[j+3][k]==X)
                    || (grille[j][k]==O && grille[j+1][k]==O
                    && grille[j+2][k]==O && grille[j+3][k]==O)){
                    return 1;
                }
			}
            /*Verification d'un alignement diagonal de haut en bas*/
			else if((k<=2) && (j<=3)){
				if((grille[j][k]==X && grille[j+1][k+1]==X
                    && grille[j+2][k+2]==X && grille[j+3][k+3]==X)
                    || (grille[j][k]==O && grille[j+1][k+1]==O
                    && grille[j+2][k+2]==O && grille[j+3][k+3]==O)){
                    return 1;
				}
			}
            /*Verification d'un alignement diagonal de bas en haut*/
			else if((k>=3) && (j<=3)){
				if((grille[j][k]==X && grille[j+1][k-1]==X
                    && grille[j+2][k-2]==X && grille[j+3][k-3]==X)
                    || (grille[j][k]==O && grille[j+1][k-1]==O
                    && grille[j+2][k-2]==O && grille[j+3][k-3]==O)){
                    return 1;
				}
			}

			else{
                    return 0;
			}
}



int main(){


	menu();

	do{
        printf("Que la partie commence!\n\n\n\n");
        remplissage();
        affichagegrille();

        do{
            coup(j1,grille);
            affichagegrille();
            compteur++;

            if(compteur>=7){
                resultat=verification(grille,abscice,p);
                if(resultat==1){
                    printf("Bien joue %s! Vous remportez la partie!",j1);
                    compteur=43;
                }
            }

            if(resultat!=1){
                coup(j2,grille);
                affichagegrille(grille);
                compteur++;
                if(compteur>=8){
                    resultat=verification(grille,abscice,p);
                    if(resultat==1){
                        printf("Bien joue %s! Vous remportez la partie!",j2);
                        compteur=43;
                    }
                }
            }
        }
        while(compteur<42);

        if(compteur==42){
            printf("Match Nul!");
        }
        printf("Voulez-vous rejouer la partie? o=oui ou n=non",rejouer);
        scanf("%c",&rejouer);
    }
    while(rejouer=='o');
}



Les problèmes sont que dès que la boucle do/while est finie (compteur<42), le programme se ferme sans demander

aux joueurs s'ils veulent bien rejouer une partie; et il y a aussi un problème au niveau de la vérification de tout les

alignements: je pense que c'est à cause de mes variables j et k qui ne correspondent pas aux variables abscice et p.

Merci pour vos réponses :)
Messages postés
496
Date d'inscription
lundi 17 septembre 2007
Statut
Membre
Dernière intervention
22 juin 2010
123
Pour le problème du rejouer c'est un peu tordu.
Pour résumer vite fait, lors de la saisie du dernier nombre, l'utilisateur à entré un nombre puis Entrée. Comme pour rejouer on demande un caractère, le scanf voit qu'il y en a un de disponible dans le buffer d'entrée clavier donc il ne bloque pas le programme en attendant une saisie utilisateur. Il lit le Enter de la dernière fois.
Il faut vider le buffer clavier avant le scanf( "%c"
Developpez.com : Vider le buffer clavier.

Dans coup le premier scanf, on peut saisir 22 ce n'est pas vérifié.

M.
Messages postés
10
Date d'inscription
dimanche 4 mai 2008
Statut
Membre
Dernière intervention
18 mai 2009
1
Merci pour ton explication Mahmah, j'ai réussi à régler le problème pour rejouer une partie en vidant le buffer clavier.

Mais tu dis que mon premier scanf de coup n'est pas vérifié, or à la suite il y a deux boucle while qui vérifie ce scanf ^^ (tu n'as peut-être dû pas les voir).

Maintenant il me reste le problème de la vérification, je ne sais pas si le problème vient d'une mauvaise gestion de mes variables dans la fonction verification ou bien de ma fontion main.