Moondir
Messages postés10Date d'inscriptiondimanche 4 mai 2008StatutMembreDernière intervention18 mai 2009
-
4 mai 2008 à 05:09
maryouma08 -
30 nov. 2010 à 12:47
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;
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.
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.
Mahmah
Messages postés496Date d'inscriptionlundi 17 septembre 2007StatutMembreDernière intervention22 juin 2010125 4 mai 2008 à 23:06
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 !
Mahmah
Messages postés496Date d'inscriptionlundi 17 septembre 2007StatutMembreDernière intervention22 juin 2010125 5 mai 2008 à 00:20
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.
Moondir
Messages postés10Date d'inscriptiondimanche 4 mai 2008StatutMembreDernière intervention18 mai 20091 6 mai 2008 à 12:54
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...
Vous n’avez pas trouvé la réponse que vous recherchez ?
Mahmah
Messages postés496Date d'inscriptionlundi 17 septembre 2007StatutMembreDernière intervention22 juin 2010125 4 mai 2008 à 12:48
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 ;-)
Moondir
Messages postés10Date d'inscriptiondimanche 4 mai 2008StatutMembreDernière intervention18 mai 20091 4 mai 2008 à 19:14
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!
Mahmah
Messages postés496Date d'inscriptionlundi 17 septembre 2007StatutMembreDernière intervention22 juin 2010125 4 mai 2008 à 21:46
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é.
Moondir
Messages postés10Date d'inscriptiondimanche 4 mai 2008StatutMembreDernière intervention18 mai 20091 4 mai 2008 à 22:25
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.