Tu as des bugs aussi, quand un joueur à cliqué sur la case de gauche, pour cliquer sur celle juste à droite il faut cliquer genre 15 pixels plus loin.
Si je ramène ta grille sur 3x3 ça bug :
Pour ton problème de segfault, c'est que tu fais des SDL_Quit un peu n'importe où, du coup quand tu appelles les fonctions ça ne va pas. Et, si la fonction exit fonctionne sous linux, c'est standard.
ça je m'en occupe : j'edite
-> c'est parce que d'habitude je charge l'icone mais j'ai pensé que vous avais pas besoin de la fonction.
sinon normalement ça doit marcher maintenant, j'ai supprimé l'appel à la fonction, modifié le prototype, modifié la fonction pour ne pas mettre d'icone
Pour vérifier si on a gagné: il faut que y reste constant, y = last_clic.y, et on va modifier la valeur de x vers la droite (x += 1) et vers la gauche ( x -= 1), si on retrouve le signe du joueur actuelle on incrémente un compteur.
Dans le code suivant :
int compterDir(int * tab, Coord * c, int x, int y, int joueur) {
int cnt, i, j;
cnt = 0; // le compteur
for (j = c->x + x, i = c->y + y; // pour notre cas i doit être constat, don on l'affecte a c->y(last_clic.y) et on lui ajoute y qui vaut 0. tandis que j doit être altérer, pour vérifier a droite on lui ajoute x qui vaut 1 et pour vérifier vers la droite on lui ajoute x et qui vaut dans ce cas -1.
(unsigned) j < TAB_W && (unsigned) i < TAB_H &&
tab[i * TAB_W + j] == joueur; i += y, j += x)
cnt++;
return cnt;
}
int testerGrille(int * tab, Coord * c, int joueur) {
Coord dir[4] = {
{ 0, 1 }, { 1, 0 }, // { 1, 0 } ce couple représente notre cas ou on vérifie vers la droite
{ 1, 1 }, { 1, -1 }
};
int cnt, i;
for (i = 0; i < 4; i++) {
cnt = compterDir(tab, c, dir[i].x, dir[i].y, joueur);
cnt += compterDir(tab, c, -dir[i].x, -dir[i].y, joueur); // ici c'est le contraire de { 1, 0 } donc on vérifie vers la gauche { -1, 0 }
if (cnt + 1 >= NBR_P) //
return 1;
}
return 0;
}
le reste c'est la même chose . Le mieux c'est de prendre un papier est schématisé le tout, tu verras certainement comment faire
bool NEWgagner(Signe Grille[NOMBRECASE][NOMBRECASE], int JOUEUR, int nombreCoups)
{
char *chaine[] = {"- MORPION - J1 gagne", "- MORPION - J2 gagne", "- MORPION - MATCH NUL"};
int x, y;
int i,j;
int nombreAlignementV = 0, nombreAlignementH = 0, nombreAlignementD1 = 0, nombreAlignementD2 = 0;
for (x = 0 ; x < NOMBRECASE ; x++)
{
for (y = 0 ; y < NOMBRECASE ; y++)
{
if (Grille[x][y] == VIDE)continue;
//on vérifie ceux qui sont horisontaux
for (i = x , j = y ; i < NOMBRECASE ; i++)
{
if(Grille[i][j] == VIDE)break;
if(Grille[x][y] == Grille[i][j])nombreAlignementH++;
}
//on vérifie ceux qui sont verticaux
for (j = y , i = x ; j < NOMBRECASE ; j++)
{
if(Grille[i][j] == VIDE)break;
if(Grille[x][y] == Grille[i][j])nombreAlignementV++;
}
}
}
if(nombreAlignementV == NOMBRECASEALIGNEPOURGAGNER ||
nombreAlignementH == NOMBRECASEALIGNEPOURGAGNER)
return true;
return false;
}
mais j'ai un problème : quand j'ai mis 3 cases dans la grille(J1, J2, J1)je pense que ça doit venir des conditions qui incrémente les variables mais j'ai aucune idée pour le résoudre
EDIT 2 : j'ai corrigé et la fonction marche : voila la nouvelle :
bool NEWgagner(Signe Grille[NOMBRECASE][NOMBRECASE], int JOUEUR, int nombreCoups)
{
char *chaine[] = {"- MORPION - J1 gagne", "- MORPION - J2 gagne", "- MORPION - MATCH NUL"};
int x, y;
int i,j;
int nombreAlignementV = 0, nombreAlignementH = 0, nombreAlignementD1 = 0, nombreAlignementD2 = 0;
for (x = 0 ; x < NOMBRECASE ; x++)
{
for (y = 0 ; y < NOMBRECASE ; y++)
{
if (Grille[x][y] == VIDE)continue;
//on vérifie ceux qui sont horisontaux
for (i = x , j = y ; i < NOMBRECASE ; i++)
{
if(Grille[x][y] == Grille[i][j] && Grille[i][j] != VIDE)nombreAlignementH++;
}
if(nombreAlignementV == NOMBRECASEALIGNEPOURGAGNER)
{
SDL_WM_SetCaption((JOUEUR == 1)? chaine[0] : chaine[1], NULL);
SDL_Delay(1000);
return true;
}
nombreAlignementV = 0;
//on vérifie ceux qui sont verticaux
for (j = y , i = x ; j < NOMBRECASE ; j++)
{
if(Grille[x][y] == Grille[i][j] && Grille[i][j] != VIDE)nombreAlignementV++;
}
if(nombreAlignementH == NOMBRECASEALIGNEPOURGAGNER)
{
SDL_WM_SetCaption((JOUEUR == 1)? chaine[0] : chaine[1], NULL);
SDL_Delay(1000);
return true;
}
nombreAlignementH = 0;
}
}
if (nombreCoups == NOMBRECOUPMAX)
{
SDL_WM_SetCaption(chaine[2], NULL);
SDL_Delay(1000);
return true;
}
return false;
}
C159 >
Le 3ème paramètre de SDL_SetVideoMode c'est pas le nombre de couleurs, mais le nombre de bits à utiliser pour afficher 1 pixel (bpp -> bits per pixel)
Les noms de variable en majuscules sont généralement 'réservées' aux constantes. Je dis 'réservées' parce que tu n'as aucune obligation, mais c'est un style de codage que la plupart des gens utilisent.
C'est pas trop mal ta fonction erreurSDL mais le problème c'est que si t'as le moindre écart dans ton programme tu le quittes, tu pourrais faire en sorte d'afficher un message et remédier au problème. Genre, si SDL_BlitSurface n'a pas réussi, tu attends un peu (SDL_Delay(1)) et tu recommences.
Comme tu as fait un fichier spécial SDL, tu pourrais sauvegarder le pointeur retourné par SDL_GetVideoSurface dans une variable static globale à ton fichier.
Tu pourrais protéger ton header contre l'inclusion infinie
Tu pourrais faire en sorte d'avoir des noms de variable moins long (question de goût, mais c'est plus facile et rapide à lire d'avoir des noms courts)
Quand tu déclares ta grille, comme VIDE est égal à 0 tu n'as pas besoin d'initialiser tous les champs
Tu pourrais déclarer toutes tes variables en débugt de bloc
Tu pourrais tirer le joueur qui commence aléatoirement, là c'est toujours le joueur 1 qui commence
My_SDL_CreateRGBSurface ton nom est incorrect, tu 'fill' aussi ta surface
Pareil pour 'couleur', ton nom est mal choisi
ALIGNE ne prend qu'un seul L
Tu pourrais utiliser un tableau pour tes surfaces de pions, ça te permettrait d'avoir un accès direct à ton tableau en fonction de la valeur de Grille[...][...]
Tu pourrais enlever ton #define dans ta fonction AfficherGrille, il aurait mieux valu mettre le if dans la fonction, ça éclaircirait le code
Dans ta fonction 'choix', le ternaire dans l'appel de fonction SDL_WM_SetCaption, je suis pas fan. Tu aurais pu faire un accès direct à ton tableau en fonction de la variable JOUEUR. Genre :
Quand tu demandes à quitter (SDL_QUIT), tu fermes ton programme direct, tu pourrais libérer tes surfaces et pourquoi pas revenir dans le main si jamais tu ajoutes une fonction de fin d'exécution (genre comme SDL_Quit mais que tu ne peux pas appeler avec atexit).
Grille[i][j] = (JOUEUR == 1)?JOUEUR1 : JOUEUR2; => inutile, il suffit de faire une affectation avec JOUEUR
Dans ta fonction gagner, même remarque que plus haut pour le WM_SetCaption
Je ne suis pas du tout fan de ta macro ALLIGNE pour tester ta grille, tu pourrais soit utiliser une fonction, soit tout mettre dans la même condition ou encore changer de technique pour tester un gagnant
Tu pourrais faire une fonction 'rejouer'
Tu pourrais plutôt attendre le clic de l'utilisateur plutôt que mettre une tempo, parce que la fenêtre qui se ferme quand le jeu est terminé, c'est pas très agréable. :x
Quand nombreCoups == 9 tu as gagné ? je ne pense pas, le nom de ta fonction est mal choisie dans ce cas là
Dans tes #define, tu devrais (dois?) mettre des parenthèses
reino >
Tu devrais modifier le nom de ta fonction 'wait', ça fait conflit avec la fonction wait de unistd.h qui est inclus par la SDL sur mac
Ta fonction wait fait une boucle infinie (done n'est jamais modifié), tu pourrais mettre while(1) dans ce cas là
Ta fonction wait retourne un int, mais en fin de fonction elle ne retourne rien (bien que ça ne serve à rien avec ta boucle infinie)
Tu fais les procédures pour quitter dans ta fonction wait, tu devrais modifier le nom de la fonction dans ce cas là ; tu pourrais aussi ne pas quitter en plein milieu mais revenir au main au cas où tu voudrais rajouter des choses à ton jeu
Tu ne vérifies pas l'initialisation de la SDL + la création de ta surface principale
Pourquoi passer un pointeur à ta fonction info ?
Tu pourrais tirer le joueur qui commence aléatoirement
Ta fonction info est une fonction 'jetable' tu pourrais essayer de la modifier pour t'en servir plus souvent dans ton programme (replay par ex.)
Le nom de tes fonctions sont mal choisies. Tu as une fonction UpdateEvents et une fonction events. Ta fonction events fait tout, elle appelle check_clic et ta fonction check_clic fait tout (tester si quelqu'un gagne, rejouer, 'fin bref...). Une fonction doit avoir 1 fonction pas 30.
D'ailleurs, à cause de ça t'es obligé de passer un pointeur sur 'role' à tes fonctions
Dans ta fonction check_clic tu fais 2 ifs imbriqués, tu pourrais n'en utiliser qu'un seul
Le nom de ta fonction grille est mal choisi. Qu'est-ce qu'elle fait ? à première vue j'en sais rien
Pourquoi utiliser une variable intermédiaire 'r' ? tu peux t'en passer
Je peux changer la taille de la grille mais pas le nombre de pions à poser.
Dans ta fonction 'grille', tu fais plusieurs ifs imbriqués, tu peux les raccourcir. Les opérateurs && || s'évaluent de gauche à droite.
Tu pourrais simplifier ta fonction 'grille'. Avec simplement des if tu gagnerais en lisibilité et en rapidité
Pareil que plus haut pour ta fonction 'replay'. Tu pourrais fusionner tes 2 if aussi.
Dans ta fonction reset, c'est encore le joueur 1 qui commence.
Tu pourrais fusionner tes fonctions check_winner et grille.
Masquer une fonction avec un #define n'est pas très idiomatique.
De plus, à chaque fois que tu appelles 'ecran' tu appelles la fonctoin, tu pourrais la mémoriser
Tu pourrais modifier le problème dont je te parlais en modifier la récupération de la case à partir des coordonnées comme suit :
/* Hé oui, tu as oublié les bordures */
i = c->x / (CASEW + 10);
j = c->y / (CASEW + 10);
@ Pouet_forever : merci bien, je l'attendais le commentaire. j'essairé de le compléter et de l'améliorer avec ce que tu as dis mais je n'ais pas compris :
Citation
Quand nombreCoups == 9 tu as gagné ? je ne pense pas, le nom de ta fonction est mal choisie dans ce cas là
Dans tes #define, tu devrais (dois?) mettre des parenthèses
*) Ta fonction s'appelle 'gagner', mais quand tu as match nul tu retournes 'true' ce qui veut dire que tu as gagné, or ce n'est pas le cas.
*) Pour les parenthèses, je pense notamment à ceux-là :
bon je pense avoir tout corriger sauf des petits trucs que je veux garder intact(ou que je ne vois pas comment modifier) :
Citation
My_SDL_CreateRGBSurface ton nom est incorrect, tu 'fill' aussi ta surface
C'est pas trop mal ta fonction erreurSDL mais le problème c'est que si t'as le moindre écart dans ton programme tu le quittes, tu pourrais faire en sorte d'afficher un message et remédier au problème. Genre, si SDL_BlitSurface n'a pas réussi, tu attends un peu (SDL_Delay(1)) et tu recommences.
donc voila le code :
main.c
#define NOMBRECASE 5
#define NOMBRECASEALIGNEPOURGAGNER 3
#include <stdio.h>
#include <time.h>
//bolleen
#include <stdbool.h>
#include <SDL/SDL.h>
#define LARGEUR (NOMBREBORDURE * TAILLEBORDURE + NOMBRECASE * TAILLECASE)
#define HAUTEUR (NOMBREBORDURE * TAILLEBORDURE + NOMBRECASE * TAILLECASE)
#define BPP 32
#define TAILLECASE (500/NOMBRECASE)
#define TAILLEBORDURE 2
#define NOMBREBORDURE (NOMBRECASE-1)
#define NOMBRECOUPMAX NOMBRECASE*NOMBRECASE
#define ALEA(MIN, MAX) (rand() % (MAX - MIN + 1)) + MIN;
//ma lib
#include "My_SDL.h"
typedef enum {VIDE = 0, JOUEUR1 = 1, JOUEUR2 = 2} Signe; // Indique ce que contient une case du plateau ainsi que le joueur qui doit jouer
SDL_Surface *ecran;
bool gagner(Signe Grille[NOMBRECASE][NOMBRECASE], int JOUEUR, int nombreCoups);
void AfficherGrille(Signe Grille[NOMBRECASE][NOMBRECASE], SDL_Surface* surface[]);
void choix(Signe Grille[NOMBRECASE][NOMBRECASE], int JOUEUR);
bool FinMatch(Signe Grille[NOMBRECASE][NOMBRECASE], int JOUEUR, int nombreCoups);
bool ReJouer(void);
void My_SDL_Pause(void);
void programme(void)
{
Signe Grille[NOMBRECASE][NOMBRECASE];
int i, j;
int JOUEUR = 2;
int nombreCoups = 0;
SDL_Surface *surface[3] = {NULL, NULL, NULL};
const Uint32 couleurs[3] = {My_SDL_MapRGB(255,255,255), My_SDL_MapRGB(255,0,0), My_SDL_MapRGB(255,255,0)};
surface[0] = My_SDL_CreateRGBSurface(SDL_HWSURFACE, TAILLECASE, TAILLECASE, BPP, couleurs[0]);
surface[1] = My_SDL_CreateRGBSurface(SDL_HWSURFACE, TAILLECASE, TAILLECASE, BPP, couleurs[1]);
surface[2] = My_SDL_CreateRGBSurface(SDL_HWSURFACE, TAILLECASE, TAILLECASE, BPP, couleurs[2]);
do
{
JOUEUR = ALEA(1, 2);
for (i = 0 ; i < NOMBRECASE ; i++)
for (j = 0 ; j < NOMBRECASE ; j++)
Grille[i][j] = VIDE;
do
{
JOUEUR = 3 - JOUEUR;
AfficherGrille(Grille, surface);
choix(Grille, JOUEUR);
AfficherGrille(Grille, surface);
nombreCoups++;
}
while(!FinMatch(Grille, JOUEUR, nombreCoups));
}
while(ReJouer());
for ( i = 0 ; i < 3 ; i++)
SDL_FreeSurface(surface[i]);
}
void AfficherGrille(Signe Grille[NOMBRECASE][NOMBRECASE], SDL_Surface* surface[])
{
SDL_Rect position;
int i, j;
for (i = 0, position.y = 0 ; i < NOMBRECASE ; i++ , position.y += (TAILLEBORDURE+TAILLECASE))
for (j = 0, position.x = 0 ; j < NOMBRECASE ; j++ , position.x += (TAILLEBORDURE+TAILLECASE))
My_SDL_BlitSurface(surface[Grille[i][j]], NULL, &position);
My_SDL_Flip();
}
void choix(Signe Grille[NOMBRECASE][NOMBRECASE], int JOUEUR)
{
char *chaine[] = {"- MORPION - J1 choix", "- MORPION - J2 choix"};
int i = -1, j = -1;
SDL_Event event;
SDL_WM_SetCaption(chaine[JOUEUR-1], NULL);
do
{
SDL_WaitEvent(&event);
if (event.button.button == SDL_BUTTON_LEFT && event.type == SDL_MOUSEBUTTONUP)
{
i = event.button.y / (TAILLEBORDURE+TAILLECASE);
j = event.button.x / (TAILLEBORDURE+TAILLECASE);
}
}
while(Grille[i][j] != VIDE || i == -1);
Grille[i][j] = JOUEUR;
}
bool FinMatch(Signe Grille[NOMBRECASE][NOMBRECASE], int JOUEUR, int nombreCoups)
{
char *chaine[] = {"- MORPION - MATCH NUL", "- MORPION - J1 gagne", "- MORPION - J2 gagne"};
int x, y;
int i,j;
int nombreAlignementV = 0, nombreAlignementH = 0, nombreAlignementD1 = 0, nombreAlignementD2 = 0;
for (x = 0 ; x < NOMBRECASE ; x++)
{
for (y = 0 ; y < NOMBRECASE ; y++)
{
if (Grille[x][y] != VIDE)
{
//on vérifie ceux qui sont verticaux
for (i = x , j = y ; i < NOMBRECASE && Grille[i][j] == Grille[x][y]; i++)
if(Grille[x][y] == Grille[i][j])
nombreAlignementH++;
//on vérifie ceux qui sont horisontaux
for (j = y , i = x ; j < NOMBRECASE && Grille[i][j] == Grille[x][y]; j++)
if(Grille[x][y] == Grille[i][j])
nombreAlignementH++;
//on vérifie ceux qui sont en diagonnale : bas et gauche
for (j = y , i = x ; i < NOMBRECASE && j < NOMBRECASE && Grille[i][j] == Grille[x][y]; i++, j++)
if(Grille[x][y] == Grille[i][j])
nombreAlignementD1++;
//on vérifie ceux qui sont en diagonnale : bas et droite
for (j = y , i = x ; i < NOMBRECASE && j < NOMBRECASE && Grille[i][j] == Grille[x][y]; i++, j--)
if(Grille[x][y] == Grille[i][j])
nombreAlignementD2++;
if(nombreAlignementH == NOMBRECASEALIGNEPOURGAGNER+1 ||
nombreAlignementV == NOMBRECASEALIGNEPOURGAGNER+1 ||
nombreAlignementD1 == NOMBRECASEALIGNEPOURGAGNER ||
nombreAlignementD2 == NOMBRECASEALIGNEPOURGAGNER)
{
SDL_WM_SetCaption(chaine[JOUEUR], NULL);
My_SDL_Pause();
return true;
}
}
nombreAlignementH = 0;
nombreAlignementV = 0;
nombreAlignementD1 = 0;
nombreAlignementD2 = 0;
}
}
if (nombreCoups == NOMBRECOUPMAX)
{
SDL_WM_SetCaption(chaine[0], NULL);
My_SDL_Pause();
return true;
}
return false;
}
bool ReJouer(void)
{
char chaine[] = "- MORPION - Recommencer O/N";
char car = '\0';
SDL_Event event;
SDL_WM_SetCaption(chaine, NULL);
do
{
SDL_WaitEvent(&event);
if (event.type == SDL_KEYDOWN)
car = event.key.keysym.sym;
}
while(car != 'o' && car != 'n');
return (car == 'o')? true : false;
}
void My_SDL_Pause(void)
{
SDL_Event event;
do
SDL_WaitEvent(&event);
while(event.type != SDL_KEYDOWN);
}
int main(int argc, char *argv[])
{
My_SDL_initialise(SDL_INIT_VIDEO);
ecran = My_SDL_initialiserfenetre(LARGEUR,
HAUTEUR,
BPP,
SDL_DOUBLEBUF| SDL_HWSURFACE/* | SDL_FULLSCREEN*/,
"- MORPION -",
NULL);
programme();
SDL_Quit();
return EXIT_SUCCESS;
}
My_SDL.h
/*
My_SDL.h
------
Par Cyril, pour tester les retours des fonctions en SDL
Rôle : Une grande majorité des fonctions les plus importantes en SDL pour vérifier les fonctions
*/
#ifndef My_SDL
#define My_SDL
//initialise la SDL
void My_SDL_initialise(const Uint32 flags);
//cré la fenetre
SDL_Surface* My_SDL_initialiserfenetre(const int LARGEURFENETRE, const int HAUTEURFENETRE, const int NB_COULEUR, const Uint32 flags, char *nomFenetre, SDL_Surface *imageDeLaFenetre);
//créer une surface et la colore
SDL_Surface* My_SDL_CreateRGBSurface(const Uint32 flags, const int X, const int Y, const int NB_COULEUR, const Uint32 couleur);
//charge une image
SDL_Surface* My_SDL_ChargerImage(const char* fichier);
//renvoi une couleur de type uint32
Uint32 My_SDL_MapRGB(const int R, const int V, const int B);
//Colore une surface
void My_SDL_FillRect(SDL_Surface* SURFACE, const Uint32 couleur);
//blitte une surface sur l'ecran
void My_SDL_BlitSurface(SDL_Surface* SURFACE, SDL_Rect *SURFACE_BLITTE, SDL_Rect *position);
//realise le SDL_Flip
void My_SDL_Flip(void);
#endif
My_SDL.c
/*
My_SDL.c
------
Par Cyril, pour tester les retours des fonctions en SDL
Rôle : Une grande majorité des fonctions les plus importantes en SDL pour vérifier les fonctions
*/
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include "My_SDL.h"
static SDL_Surface* screen;
static void erreurSDL(const char chaine[]);
//initialise la SDL
void My_SDL_initialise(const Uint32 flags)
{
if (SDL_Init(flags) != 0)
erreurSDL ("Erreur SDL_Init");
}
//cré la fenetre
SDL_Surface* My_SDL_initialiserfenetre(const int LARGEURFENETRE, const int HAUTEURFENETRE, const int BPP, const Uint32 flags, char *nomFenetre, SDL_Surface *imageDeLaFenetre)
{
SDL_WM_SetIcon(imageDeLaFenetre, NULL);
SDL_WM_SetCaption(nomFenetre, NULL);
screen = SDL_SetVideoMode(LARGEURFENETRE,HAUTEURFENETRE,BPP, flags);
if (screen == NULL)
erreurSDL ("Erreur SDL_SetVideoMode");
return screen;
}
//créer une surface et la colore
SDL_Surface* My_SDL_CreateRGBSurface(const Uint32 flags, const int X, const int Y, const int BPP, const Uint32 couleur)
{
SDL_Surface* SURFACE = SDL_CreateRGBSurface(flags, X, Y, BPP, 0, 0, 0, 0);
if (SURFACE == NULL)
erreurSDL("Erreur SDL_CreateRGBSurface");
My_SDL_FillRect(SURFACE, couleur);
return SURFACE;
}
//charge une image
SDL_Surface* My_SDL_ChargerImage(const char* fichier)
{
char chaine[100];
sprintf(chaine, "ressources\\image\\%s", fichier);
SDL_Surface* img = IMG_Load(chaine);
if (img == NULL)
erreurSDL("Erreur IMG_Load");
return img;
}
Uint32 My_SDL_MapRGB(const int R, const int V, const int B)
{
return SDL_MapRGB(screen->format, R, V, B);
}
//Colore une surface
void My_SDL_FillRect(SDL_Surface* SURFACE, const Uint32 couleur)
{
if(SDL_FillRect(SURFACE, NULL, couleur) != 0)
erreurSDL("Erreur SDL_FillRect");
}
//blitte une surface sur l'ecran
void My_SDL_BlitSurface(SDL_Surface* SURFACE, SDL_Rect *SURFACE_BLITTE, SDL_Rect *position)
{
if (SDL_BlitSurface(SURFACE, SURFACE_BLITTE, screen, position) != 0)
erreurSDL("Erreur SDL_BlitSurface");
}
//realise le SDL_Flip
void My_SDL_Flip(void)
{
if (SDL_Flip(screen) != 0)erreurSDL("Erreur SDL_Flip");
}
//ecris dans le fichier l'erreur
static void erreurSDL(const char chaine[])
{
fprintf(stderr,"%s : %s\n", chaine, SDL_GetError());
exit (EXIT_FAILURE);
}
C159 >
Tu as un fichier My_SDL.c, pourquoi mettre My_SDL_Pause dans ton main.c ?
Tes noms de variable sont 100 fois trop long. Un nom de variable doit être concis et explicite, grand maximum 8 caractères est bien.
Pour le nom des variables en majuscule, même remarque.
Essaye d'avoir sur une ligne au maximum 80 caractères, ça évite de scroller inutilement de droite à gauche, on a déjà assez à faire de haut en bas.
La doc ne mentionne rien à propos d'envoyer NULL à SDL_WM_SetIcon (mais les sources si... )
Ta surface 'ecran' dans ton main.c ne sert à rien
Les commentaires inutiles sont... inutiles Un commentaire doit servir à éclaircir les parties sombre du code, pas à l'encombrer
Ton ; est en trop dans ta macro ALEA. De plus tu as oublié des parenthèses.
Tu n'as pas initialisé ta graine pour le rand, du coup il ne sert à rien.
Dans ta fonction FinMatch tu vérifies ta grille à l'envers, i != x et j != y c'est l'inverse i = y et j = x
Tu ferais mieux d'initialiser tes variables avant ton 'if'
Dans ta fonction Rejouer, tu n'as pas besoin de ternaire, return carr == 'o'; suffit.
Et pour finir, tu as un problème quelque part :
Salut, c'est moi, je viens vous proposez mon code SDL, fait un peu rapidement, mais bon
Il fonctionne plus ou moins, j'ai un peu fait comme Pouet pour les cases ^^, j'avais la flemme d'uploader des images, et ou de les mettres directement dans le header.
#include <stdio.h>
#include <time.h>
#include "grille.h"
int main (void)
{
Case grille[LONGUEUR][LARGEUR];
int joueur = 1;
int continuer = 1;
int nbCoups = 0;
int gagne = 0;
int termine = 0;
int coupPasJoue = 1;
int clavier;
int souris = 0;
coord position_souris;
/* Allegro */
BITMAP *vide = NULL;
BITMAP *rouge = NULL;
BITMAP *bleu = NULL;
BITMAP *buffer = NULL;
srand(time(NULL));
allegro_init();
install_keyboard();
install_timer();
souris = install_mouse();
if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0) != 0)
{
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
allegro_message("Echec de l'initialisation du mode graphique !\n");
return EXIT_FAILURE;
}
rouge = create_bitmap(COTECASE, COTECASE);
bleu = create_bitmap(COTECASE, COTECASE);
vide = create_bitmap(COTECASE, COTECASE);
buffer = create_bitmap(SCREEN_W, SCREEN_H);
clear_to_color(vide, makecol(255, 255, 255));
clear_to_color(rouge, makecol(255, 0, 0));
clear_to_color(bleu, makecol(0, 0, 255));
while (continuer == 1)
{
show_mouse(screen);
clear_to_color(buffer, makecol(0, 0, 0));
gagne = 0;
nbCoups = 0;
prepare_Grille(grille);
while (!(termine) && !(gagne))
{
afficherGrille(grille, joueur, termine, gagne, buffer, vide, rouge, bleu);
if (keypressed())
{
clear_keybuf();
}
if (nbCoups == 0)
{
joueur = rand();
if ((joueur % 2) == 0)
{
joueur = 1;
}
else
{
joueur = 2;
}
}
coupPasJoue = 1;
while (coupPasJoue)
{
coupPasJoue = placerPion(joueur, grille, &position_souris);
}
nbCoups++;
gagne = verifierGrille(grille, &position_souris, joueur);
if (gagne)
{
afficherGrille(grille, joueur, termine, gagne, buffer, vide, rouge, bleu);
clavier = readkey() >> 8;
if (clavier == KEY_Q)
{
continuer = 0;
}
}
if (joueur == 1)
{
joueur = 2;
}
else
{
joueur = 1;
}
}
}
destroy_bitmap(rouge);
destroy_bitmap(bleu);
destroy_bitmap(vide);
destroy_bitmap(buffer);
rouge = NULL;
bleu = NULL;
vide = NULL;
buffer = NULL;
allegro_exit();
return 0;
}
END_OF_MAIN()
grille.c
#include <stdio.h>
#include "grille.h"
void recupCoord(coord *position_souris)
{
poll_mouse(); /* Necessaire à chaque fois que l'on veut lire la souris : actualise la souris */
position_souris->colonne = mouse_x / (COTECASE + ESPACEMENT);
position_souris->ligne = mouse_y / (COTECASE + ESPACEMENT);
}
int placerPion (int joueur, Case grille[LONGUEUR][LARGEUR], coord *position_souris)
{
int pasPlace = 1;
recupCoord(position_souris);
if (mouse_b & 1)
{
if (grille[position_souris->ligne][position_souris->colonne] == VIDE)
{
if (joueur == 1)
{
grille[position_souris->ligne][position_souris->colonne] = PIONJOUEUR1;
}
else
{
grille[position_souris->ligne][position_souris->colonne] = PIONJOUEUR2;
}
pasPlace = 0;
}
}
return pasPlace;
}
void prepare_Grille(Case Grille[LONGUEUR][LARGEUR])
{
/* Met toute la grille en paramètre à vide */
int i = 0;
int j = 0;
while (i < LONGUEUR)
{
while (j < LARGEUR)
{
Grille[i][j] = VIDE;
j++;
}
i++;
j = 0;
}
}
int verifierLigne(Case Grille[LONGUEUR][LARGEUR], int ligne, unsigned int pion)
{
/* Retourne 1 si gagnant, 0 sinon */
int colonne = 0;
int alignes = 0;
int gagnant = 0;
while (colonne != LARGEUR && alignes != NBPIONS)
{
if (Grille[ligne][colonne] == pion)
{
alignes++;
}
else
{
alignes = 0;
}
colonne++;
}
if (alignes == NBPIONS)
{
gagnant = 1;
}
return gagnant;
}
int verifierColonne(Case Grille[LONGUEUR][LARGEUR], int colonne, unsigned int pion)
{
/* Renvoie 1 si gagnant, 0 sinon */
int ligne = 0;
int alignes = 0;
int gagnant = 0;
while (ligne != LONGUEUR && alignes != NBPIONS)
{
if (Grille[ligne][colonne] == pion)
{
alignes++;
}
else
{
alignes = 0;
}
ligne++;
}
if (alignes == NBPIONS)
{
gagnant = 1;
}
return gagnant;
}
int verifDiagBasDroite(Case Grille[LONGUEUR][LARGEUR], int ligne, int colonne, unsigned int pion)
{
int alignes = 0;
int gagne = 0;
while (Grille[ligne][colonne] == pion && alignes != NBPIONS && (ligne != LONGUEUR && colonne != LARGEUR))
{
alignes++;
ligne++;
colonne++;
}
if (alignes == NBPIONS)
{
gagne = 1;
}
return gagne;
}
int verifDiagBasGauche(Case Grille[LONGUEUR][LARGEUR], int ligne, int colonne, unsigned int pion)
{
int alignes = 0;
int gagnant = 0;
while (Grille[ligne][colonne] == pion && alignes != NBPIONS)
{
alignes++;
ligne++;
colonne--;
if (ligne == LONGUEUR || colonne < 0)
{
break;
}
}
if (alignes == NBPIONS)
{
gagnant = 1;
}
return gagnant;
}
int verifDiagHautGauche(Case Grille[LONGUEUR][LARGEUR], int ligne, int colonne, unsigned int pion)
{
int alignes = 0;
int gagnant = 0;
while (Grille[ligne][colonne] == pion && alignes != NBPIONS)
{
alignes++;
ligne--;
colonne--;
if (ligne < 0 || colonne < 0)
{
break;
}
}
if (alignes == NBPIONS)
{
gagnant = 1;
}
return gagnant;
}
int verifDiagHautDroite(Case Grille[LONGUEUR][LARGEUR], int ligne, int colonne, unsigned int pion)
{
int alignes = 0;
int gagnant = 0;
while (Grille[ligne][colonne] == pion && alignes != NBPIONS)
{
alignes++;
ligne--;
colonne++;
if (ligne < 0 || colonne == LARGEUR)
{
break;
}
}
if (alignes == NBPIONS)
{
gagnant = 1;
}
return gagnant;
}
int verifierDiagonales(Case Grille[LONGUEUR][LARGEUR], int ligne, int colonne, unsigned int pion)
{
/* Renvoie le nb de pions alignés en diagonale. Si égal à NBPIONS on a un gagnant.
Vérifie d'abord en haut à droite puis en haut à gauche avant de faire le bas dans le même ordre */
int gagne = 0;
gagne = verifDiagHautGauche(Grille, ligne, colonne, pion) || verifDiagHautDroite(Grille, ligne, colonne, pion) ||
verifDiagBasGauche(Grille, ligne, colonne, pion) || verifDiagBasDroite(Grille, ligne, colonne, pion);
return gagne;
}
int verifierGrille(Case Grille[LONGUEUR][LARGEUR], coord *position_souris, int joueur)
{
/* Vérifie s'il y a un gagnant en utilisant les fonctions précédentes */
int gagne = 0;
unsigned int pion;
if (joueur == 1)
{
pion = PIONJOUEUR1;
}
else
{
pion = PIONJOUEUR2;
}
if (!(gagne = verifierLigne(Grille, position_souris->ligne, pion)
|| !(gagne == verifierColonne(Grille, position_souris->colonne, pion))))
{
gagne = verifierDiagonales(Grille, position_souris->ligne, position_souris->colonne, pion);
}
return gagne;
}
void afficherGrille (Case grille[LONGUEUR][LARGEUR], int joueur, int termine,
int gagne, BITMAP *buffer, BITMAP *vide, BITMAP *rouge, BITMAP *bleu)
{
int positionWBlit = 0;
int positionHBlit = 0;
int nbCasesLigne = 0;
int nbCasesColonne = 0;
while (nbCasesLigne < LONGUEUR)
{
while (nbCasesColonne < LARGEUR)
{
if (grille[nbCasesLigne][nbCasesColonne] == VIDE)
{
blit(vide, buffer, 0, 0, positionWBlit, positionHBlit, COTECASE, COTECASE);
}
else if (grille[nbCasesLigne][nbCasesColonne] == PIONJOUEUR1)
{
blit(rouge, buffer, 0, 0, positionWBlit, positionHBlit, COTECASE, COTECASE);
}
else
{
blit(bleu, buffer, 0, 0, positionWBlit, positionHBlit, COTECASE, COTECASE);
}
nbCasesColonne++;
positionWBlit = positionWBlit + COTECASE + ESPACEMENT;
}
nbCasesColonne = 0;
nbCasesLigne++;
positionWBlit = 0;
positionHBlit = positionHBlit + COTECASE + ESPACEMENT;
}
positionWBlit = COTECASE * LARGEUR + ESPACEMENT * LARGEUR + 8; /* 8 : hauteur de la police des messages */
if (termine||gagne)
{
if (gagne)
{
if (joueur == 1)
{
textout_ex(buffer, font, "le joueur 1 a gagné !", 0, positionWBlit, makecol(255, 0, 0), -1);
}
else
{
textout_ex(buffer, font, "le joueur 2 a gagné !", 0, positionWBlit, makecol(255, 0, 0), -1);
}
}
else
{
textout_ex(buffer, font, "Match nul", 0, positionWBlit, makecol(255, 0, 0), -1);
}
}
textout_ex(buffer, font, "Une fois la partie terminée, q pour quitter, une autre touche pour rejouer.",
0, positionWBlit + 20, makecol(255, 0, 0), -1);
blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
}
grille.h
#ifndef head_grille
#define head_grille
#include <allegro.h>
enum Case
{
VIDE,
PIONJOUEUR1,
PIONJOUEUR2
};
typedef enum Case Case;
struct Coordonnees
{
int ligne;
int colonne;
};
typedef struct Coordonnees coord;
#define LONGUEUR 7
#define LARGEUR 7
#define NBPIONS 5
#define COTECASE 25
#define ESPACEMENT 3
int placerPion (int joueur, Case grille[LONGUEUR][LARGEUR], coord *test);
void prepare_Grille(Case Grille[LONGUEUR][LARGEUR]);
void afficher_ligne(void);
int verifierLigne(Case Grille[LONGUEUR][LARGEUR], int ligne, unsigned int pion);
int verifierColonne(Case Grille[LONGUEUR][LARGEUR], int colonne, unsigned int pion);
int verifDiagBasDroite(Case Grille[LONGUEUR][LARGEUR], int ligne, int colonne, unsigned int pion);
int verifDiagBasGauche(Case Grille[LONGUEUR][LARGEUR], int ligne, int colonne, unsigned int pion);
int verifDiagHautGauche(Case Grille[LONGUEUR][LARGEUR], int ligne, int colonne, unsigned int pion);
int verifDiagHautDroite(Case Grille[LONGUEUR][LARGEUR], int ligne, int colonne, unsigned int pion);
int verifierDiagonales(Case Grille[LONGUEUR][LARGEUR], int ligne, int colonne, unsigned int pion);
int verifierGrille(Case Grille[LONGUEUR][LARGEUR], coord *test, int joueur);
void recupCoord(coord *position_souris);
void afficherGrille (Case grille[LONGUEUR][LARGEUR], int joueur, int termine,
int gagne, BITMAP *buffer, BITMAP *vide, BITMAP *rouge, BITMAP *bleu);
#endif
Si vous avez des commentaires à faire, je suis preneur.
l'avantage par rapport à la SDL, c'est que tu as, en standard, des fonctions pour faire de l'affichage de texte basique, ainsi que le tracé de primitives.
Je vois que tu crées et libère tes bitmaps à chaque appel de ta fonction afficherGrille.
L'idéal, c'est de créer les ressources au débuts du programme, et de tout libérer à la fin.
Dans ta fonction, placerPion, tu utilises des fonctions Allegro et tu met à jour ta grille qui n'a rien à voir avec l'affichage.
Le mieux serait de retourner les coordonnées de la case cliquée.
Après c'est à la partie logique de ton jeu de gérer ces coordonnées.
Je vois que tu crées et libère tes bitmaps à chaque appel de ta fonction afficherGrille.
L'idéal, c'est de créer les ressources au débuts du programme, et de tout libérer à la fin.
C'est sûr que ça limite les allocations et libérations de la mémoire. Mais en fait j'ai fait comme ça parce que je n'avais besoin des bitmaps nulle part ailleurs.
Cela dit je suis d'accord, c'est (bien) mieux de tout faire une seule fois.
Citation : GurneyH
Dans ta fonction, placerPion, tu utilises des fonctions Allegro et tu met à jour ta grille qui n'a rien à voir avec l'affichage.
Le mieux serait de retourner les coordonnées de la case cliquée.
Après c'est à la partie logique de ton jeu de gérer ces coordonnées.
Là je suis pas sûr d'avoir bien compris ce que tu proposes. Je vais essayer d'implémenter ça sous forme de structure, mais je risque encore de mélanger les fonctions non ?
Enfin, s'il y a d'autres commentaires, je veux bien.
qnope >
Mêmes remarques qu'en console.
Initialiser toutes tes cases de structure est inutile, tu initialises la première et le reste sera initialisé à 0.
D'autres trucs, mais la flème de commenter.
Magicneo >
La flème de commenter ton code en fait.
J'le ferai plus tard, mais quelques trucs histoire de dire que j'ai pas posté pour rien :
Tu pourrais plus découper ton code en fonctions.
Ton #ifndef au début de chaque .c ne sert à rien, il aurait fallut le faire sur ton .h
Tes fonctions de vérification sont très redondantes, tu pourrais essayer de raccourcir.
Faire un pointeur sur une variable qui existe dans le 'scope' ne sert à rien : int*ptrColonne=&colonne; autant passer le pointeur directement aux fonctions
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html