Aller au contenu

Puissance 4 en C


Invité

Messages recommandés

C'était dans le cadre d'un projet d'école (réaliser un jeu type puissance 4 en C avec l'aide d'une librairie graphique (SDL) ). Réalisé entièrement par moi et en solo, voici une petite démo

A propos du code, il est commenté mais les algorithmes sont un peu "ghettos", compliqués et pas optimisés mais c'était à mes débuts dans la prog. 

Le code:

Spoiler

 

main.c


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

//librairie graphique
#include "lib/libgraphique.h"

#ifndef CONSTANTES_STATIQUES
#define CONSTANTES_STATIQUES

#define SIZE 100        // = diamètre
#define SIZEBY2 50      // = rayon

#define NB_CASE_L 8
#define NB_CASE_H 6

#define L (NB_CASE_L * SIZE)
#define H (NB_CASE_H * SIZE)

#define player1_color fabrique_couleur(255,0,0)
#define player2_color fabrique_couleur(255,255,0)

enum SENS_TYPE
{
    DIAGONALEDOWN = 0,
    DIAGONALEUP,
    VERTICAL,
    HORIZONTAL,
};

enum TYPE_DE_JEU
{
    UNJOUEUR = 1,
    DEUXJOUEURS,
};

#endif //CONSTANTES


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ____  _____ _____ ___ _   _ ___ _____ ___ ___  _   _    ____  _____ ____     _____ ___  _   _  ____ _____ ___ ___  _   _ ____
// |  _ \| ____|  ___|_ _| \ | |_ _|_   _|_ _/ _ \| \ | |  |  _ \| ____/ ___|   |  ___/ _ \| \ | |/ ___|_   _|_ _/ _ \| \ | / ___|
// | | | |  _| | |_   | ||  \| || |  | |  | | | | |  \| |  | | | |  _| \___ \   | |_ | | | |  \| | |     | |  | | | | |  \| \___ \
// | |_| | |___|  _|  | || |\  || |  | |  | | |_| | |\  |  | |_| | |___ ___) |  |  _|| |_| | |\  | |___  | |  | | |_| | |\  |___) |
// |____/|_____|_|   |___|_| \_|___| |_| |___\___/|_| \_|  |____/|_____|____/   |_|   \___/|_| \_|\____| |_| |___\___/|_| \_|____/
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//////////////////////////////
//////////////////////////////
//LISTES DES FONCTIONS
///////////////////////////////
///////////////////////////////

//Fonction qui corrige la position des pions pour les aligner dans les colonnes
Point coin_case( Point p, int cote_case );

//Fonction qui dessine les pions et les fait tomber.
void dessiner_case( Point p, Couleur color );

//Fonction qui vérifie s'il y a un gagnant à chaque pion posé.
int checkvictoire( Point p, Couleur color ); //return 1 = win rouge 2 = win jaune

//Fonction qui dessine les pions alignés par 4 en vert.
void dessiner_cercles_gagnants( int x, int y, int sens, Couleur color );

//Fonction qui dessine une grille comme celle du véritable puissance 4
void dessiner_quadrillage( int quadrillagesize, Couleur color );

//Fonction qui fait jouer un adversaire contrôlé par le hasard
Point adversaire( Point p );

//variable qui stock la position y du dernier carré posé
int lastesthauteur = 0;

//////////////////////////////////
// __  __    _    ___ _   _
// |  \/  |  / \  |_ _| \ | |
// | |\/| | / _ \  | ||  \| |
// | |  | |/ ___ \ | || |\  |
// |_|  |_/_/   \_\___|_| \_|
//
//////////////////////////////////


/////////////////////////
/////////////////////////
// MAIN
//////////////////////////
//////////////////////////

int main(int argc, char *argv[])
{
    //Initialisation de la fenetre
    ouvrir_fenetre(L,H);

    //afficher la souris
    SDL_ShowCursor(SDL_ENABLE);

    //////////////////////////
    //Décalaration des variables importantes
    //////////////////////////
    Point coingauche = { 0, 0 };
    Point clic;     //variable qui stock les positions des clics
    int boucle_jeu = 0, boucle_menu = 1, boucle_win = 0;    //boucles qui nous permettront de switcher entre le jeu, le menu et l'écran "gagné"
    int joueur1 = 1;    //variable qui va nous permettre d'alterner les couleurs.
    int victoire = 0;   //check pour la victoire
    Couleur color;  //couleur des pions
    SDL_Event event;    //variable qui stockera les évènements
    int mousex, mousey;   //positions du curseur de la souris
    int mode_selection = 0, mode_choisi = 0;   //variables qui gèrent les modes de jeu (1 ou 2 joueurs)

    //////////////////////////
    // boucle du menu
    ////////////////////////
    while( boucle_menu )
    {
        //boucle d'évènements
        //on stock les évèments qui surviennent dans une variable
        //WaitEvent bloque le programme jusqu'à ce qu'un evenement survienne
        SDL_WaitEvent(&event);
        switch(event.type)  //switch/case pour avoir les évènements qui nous intéresse
        {
            case SDL_QUIT:  //action de quitter (croix)
                boucle_menu = 0;    //on ferme notre boucle principale => on quitte
                break;
            case SDL_KEYDOWN:   //touche pressée
                if( event.key.keysym.sym == SDLK_ESCAPE) //echap
                    boucle_menu = 0;    //on ferme notre boucle principale => on quitte
                break;
            case SDL_MOUSEBUTTONUP: //clic souris gauche
                //on stock les coordonnées de la souris
                mousex = event.button.x, mousey = event.button.y;
                //printf("x: %i, y: %i \n", mousex, mousey);
                if( !mode_selection )
                {
                    //bouton jouer
                    if( (mousex >= 337 && mousex <= 436) && (mousey >= 279 && mousey <= 315) )
                        mode_selection = 1; //on affiche l'image de la selection du mode de jeu
                    //bouton quitter
                    else if( (mousex >= 337 && mousex <= 436) && (mousey >= 345 && mousey <= 380) )
                        boucle_menu = 0;    //on quitte
                }
                //menu selection des modes
                else
                {
                    //bouton retour
                    if( (mousex >= 322 && mousex <= 421) && (mousey >= 425 && mousey <= 462) )
                        mode_selection = 0; //on reaffiche l'image du menu
                    //bouton "1 Joueur"
                    else if( (mousex >= 260 && mousex <= 499) && (mousey >= 271 && mousey <= 305) )
                    {
                        mode_selection = 0;
                        mode_choisi = UNJOUEUR;
                        boucle_jeu = 1;
                    }
                    //bouton "2 Joueur"
                    else if( (mousex >= 260 && mousex <= 499) && (mousey >= 303 && mousey <= 334) )
                    {
                        mode_selection = 0;
                        mode_choisi = DEUXJOUEURS;
                        boucle_jeu = 1;
                    }
                }
                break;
        }

        //affichage de l'image du menu
        afficher_image("image/menu.bmp", coingauche );

        //menu de selection des modes
        if( mode_selection )
            afficher_image("image/mode_de_jeu.bmp", coingauche );

        actualiser();

        //démarrer sur fond noir le jeu
        if( boucle_jeu )
        {
            dessiner_rectangle( coingauche, L, H, fabrique_couleur(0,0,0));
            actualiser();
        }

        ///////////////////////////
        //  boucle de jeu
        /////////////////////////
        while( boucle_jeu )
        {
            //boucle d'évènements
            //on stock les éléments qui surviennent dans une variable
            //PollEvent au contraire de WaitEvent ne bloque pas le programme lorsqu'il ne se passe rien
            //Utile pour faire jouer un bot (ordinateur)
            SDL_PollEvent(&event);
            switch(event.type)
            {
                case SDL_QUIT:  //action de quitter (croix)
                    boucle_jeu = 0;
                    boucle_menu = 0;
                    break;
                case SDL_KEYDOWN:   //touche pressée
                    if( event.key.keysym.sym == SDLK_ESCAPE) //echap
                        boucle_jeu = 0;    //on ferme notre boucle de jeu
                    break;
            }

            //on dessine la grille dès le démarrage
            dessiner_quadrillage( 5, fabrique_couleur( 0, 128, 255) );
            actualiser();

            //on alterne les couleurs
            if( joueur1 )
            {
                color = player1_color;
                clic = attendre_clic(); //on stock les coordonnées du clic
                joueur1 = 0;
            }
            else
            {
                color = player2_color;
                if( mode_choisi == DEUXJOUEURS )    //si 2 joueurs, on attend un clic
                    clic = attendre_clic();
                else
                    clic = adversaire( clic );   //sinon on génère une valeur aléatoire
                joueur1 = 1;
            }

            //On appelle la fonction pour dessiner les pions
            //coin_case() renvoie la position corrigées des pions pour qu'ils se positionnent bien dans les colonnes
            dessiner_case( coin_case( clic, SIZE ), color);

            //on vérifie s'il y a 4 pions alignés
            victoire = checkvictoire( coin_case( clic, SIZE ), color );
            //s'il y a un gagnant, on ouvre la boucle "win"
            if( victoire != 0 )
            {
                boucle_jeu = 0;
                boucle_win = 1;
            }
        }

        ///////////////////////////
        //  boucle de jeu
        /////////////////////////
        while( boucle_win )
        {
            //boucle d'évènements
            SDL_WaitEvent(&event);
            switch(event.type)
            {
                case SDL_QUIT:  //action de quitter (croix)
                    boucle_win = 0;
                    boucle_jeu = 0;
                    boucle_menu = 0;
                    break;
                case SDL_KEYDOWN:   //touche pressée
                    if( event.key.keysym.sym == SDLK_ESCAPE) //echap
                        boucle_win = 0;    //on ferme notre boucle "win"
                    break;
                case SDL_MOUSEBUTTONUP: //clic souris gauche
                    mousex = event.button.x, mousey = event.button.y;
                    if( (mousex >= 329 && mousex <= 429) && (mousey >= 421 && mousey <= 457) )  //bouton rejouer
                    {
                        boucle_win = 0; //on ferme la boucle win
                        boucle_jeu = 1; //on ouvre la boucle jouer
                    }
                    else if( (mousex >= 329 && mousex <= 429) && (mousey >= 485 && mousey <= 522) ) //bouton quitter
                    {
                        boucle_win = 0;
                        boucle_jeu = 0; //on revient dans le menu
                    }
                    break;
            }

            //si le gagnant est jaune
            if( victoire == 2)
                afficher_image("image/winscreen_yellow.bmp", coingauche );
            else    //rouge
                afficher_image("image/winscreen_red.bmp", coingauche );

            actualiser();   //on rafraichie
        }
    }

    // fin de la session graphique
    fermer_fenetre();

    return 0;
}

////////////////////////////////////////////////////////////////
// _____ ___  _   _  ____ _____ ___ ___  _   _ ____
// |  ___/ _ \| \ | |/ ___|_   _|_ _/ _ \| \ | / ___|
// | |_ | | | |  \| | |     | |  | | | | |  \| \___ \
// |  _|| |_| | |\  | |___  | |  | | |_| | |\  |___) |
// |_|   \___/|_| \_|\____| |_| |___\___/|_| \_|____/
//
////////////////////////////////////////////////////////////////

 /////////////////////////
/////////////////////////
// FONCTIONS
//////////////////////////
//////////////////////////


Point coin_case( Point p, int cote_case )
{
	Point coin = {cote_case * (p.x/cote_case), cote_case * (p.y/cote_case)}	;
	return coin;
}

void dessiner_case( Point p, Couleur color )
{
    //force le bord gauche du pion à commencer a x = 0;
    p.x += SIZEBY2;
    //force le pion a descendre depuis le haut de la fenetre
    p.y = 0;

    Couleur test;
    int estrempli = 0, i, hauteur = 0;
    //on parcourt le milieu de chaque ligne et on releve la couleur pour voir s'il y a un pion
    for( i = 50; i < H; i+=SIZE)
    {
        test = getpixel( p.x, i);
        //si la couleur n'est pas noir => pion => on releve la position du pixel coloré pour en déduire celle du pion en question
        if( test != fabrique_couleur( 0,0,0 ) )
        {
            estrempli = 1;
            hauteur = i;    //on enregistre la hauteur obtenue dans une variable
            break;  //on a trouvé un pion, on peut sortir du for
        }
    }

    //animation
    //tant que le pion n'est pas tout en bas de l'écran
    //et que la distance relevée d'un éventuel pion dans la colonne = 0 (pas de pion dans la colonne) ou > SIZEBY2 (il ya un pion mais on peut encore en placer dans la colonne)
    while( (p.y + SIZEBY2) <= H && ( hauteur == 0 || hauteur > SIZEBY2 ))
    {
        //ANCIENNE VERSION AVEC LES CARRES
        //Point carrequicache = { p.x, p.y - size};
        //dessiner_rectangle( carrequicache, size, size, fabrique_couleur( 0, 0, 0));
        //dessiner_rectangle( p, size, size, color);
        //dessiner_cercle( p.x, p.y - size, size / 2, fabrique_couleur( 0, 0, 0));
        dessiner_cercle( p.x, p.y, SIZEBY2+5, fabrique_couleur( 0, 0, 0));
        dessiner_cercle( p.x, p.y, SIZEBY2, color);

        //on actualise le quadrillage
        dessiner_quadrillage( 5, fabrique_couleur( 0, 128, 255) );

        //rafraichissement
        actualiser();

        //on fait descendre les pions
        p.y += 5;

        //si on touche un pion, on arrete de descendre (break)
        if( estrempli && p.y > ( hauteur - SIZE ) )
            break;

        //on enregistre la position y du pion pour s'en servir pour le bot
        lastesthauteur = p.y;

        //délais pour l'animation
        attente( 3 );
    }
}

int checkvictoire( Point p, Couleur color )
{
    //p nous envoie ici la position du bord extreme gauche (le bord gauche du carré autour du cercle)
    //on ajuste donc pour avoir le milieu du cercle en ajoutant la taille du rayon aux coordonnées
    p.x += SIZEBY2;
    p.y += SIZEBY2;

    int i,j;

    /////////////////////////////////////////
    //CHECK VICTOIRE 4 CARRES HORIZONTAUX
    //////////////////////////////////////////
    //on parcourt toutes les lignes possibles
    //on commence par la dernière
    for( i = H - 50; i >= 50; i -= SIZE )
    {
        //on parcourt toutes les colonnes possibles
        for( j = 50; j <= 450; j += SIZE)
        {
            if( color == player1_color )
            {
                if( (getpixel(j, i) == color)
                    && (getpixel(j + SIZE, i) == color)
                    && (getpixel(j + 200, i) == color) //(SIZE*2)
                    && (getpixel(j + 300, i) == color) //(SIZE*3)
                    )
                {
                    dessiner_cercles_gagnants( j, i, HORIZONTAL, fabrique_couleur(0,255,0));
                    return 1;
                    break;
                }
            }
            else if( color == player2_color )
            {
                if( (getpixel(j, i) == color)
                    && (getpixel(j + SIZE, i) == color)
                    && (getpixel(j + 200, i) == color) //(SIZE*2)
                    && (getpixel(j + 300, i) == color) //(SIZE*3)
                    )
                {
                    dessiner_cercles_gagnants( j, i, HORIZONTAL, fabrique_couleur(0,255,0));
                    return 2;
                    break;
                }
            }
        }
    }

    /////////////////////////////////////////
    //CHECK VICTOIRE 4 CARRES VERTICAUX
    //////////////////////////////////////////
    //on parcourt toutes les colonnes possibles
    for( i = 50; i < L; i += SIZE)
    {
        //on parcourt toutes les lignes possibles
        for( j = 50; j <= 250; j += SIZE)
        {
            if( color == player1_color )
            {
                if( (getpixel(i, j) == color)
                    && (getpixel(i, j + SIZE) == color)
                    && (getpixel(i, j + 200) == color) //(SIZE*2)
                    && (getpixel(i, j + 300) == color) //(SIZE*3)
                    )
                {
                    dessiner_cercles_gagnants( i, j, VERTICAL, fabrique_couleur(0,255,0));
                    return 1;
                    break;
                }
            }
            else if( color == player2_color )
            {
                if( (getpixel(i, j) == color)
                    && (getpixel(i, j + SIZE) == color)
                    && (getpixel(i, j + 200) == color) //(SIZE*2)
                    && (getpixel(i, j + 300) == color) //(SIZE*3)
                    )
                {
                    dessiner_cercles_gagnants( i, j, VERTICAL, fabrique_couleur(0,255,0));
                    return 2;
                    break;
                }
            }
        }
    }

    /////////////////////////////////////////
    //CHECK VICTOIRE 4 CARRES EN DIAGONALE
    //////////////////////////////////////////
    //on parcourt toutes les colonnes possibles
    for( i = 50; i < L; i += SIZE)
    {
        //on parcourt toutes les lignes possibles
        for( j = 50; j < H; j += SIZE)
        {
            if( color == player1_color )
            {
                //diagonal de type escalier qui descend
                if( (getpixel(i, j) == color)
                    && (getpixel(i + SIZE, j + SIZE) == color)
                    && (getpixel(i + 200, j + 200) == color) //(SIZE*2)
                    && (getpixel(i + 300, j + 300) == color) //(SIZE*3)
                    )
                {
                    dessiner_cercles_gagnants( i, j, DIAGONALEDOWN, fabrique_couleur(0,255,0));
                    return 1;
                    break;
                }
                //diagonal de type escalier qui monte
                else if( (getpixel(i, j) == color)
                    && (getpixel(i + SIZE, j - SIZE) == color)
                    && (getpixel(i + 200, j - 200) == color) //(SIZE*2)
                    && (getpixel(i + 300, j - 300) == color) //(SIZE*3)
                    )
                {
                    dessiner_cercles_gagnants( i, j, DIAGONALEUP, fabrique_couleur(0,255,0));
                    return 1;
                    break;
                }
            }
            else if( color == player2_color )
            {
                if( (getpixel(i, j) == color)
                    && (getpixel(i + SIZE, j + SIZE) == color)
                    && (getpixel(i + 200, j + 200) == color) //(SIZE*2)
                    && (getpixel(i + 300, j + 300) == color) //(SIZE*3)
                    )
                {
                    dessiner_cercles_gagnants( i, j, DIAGONALEDOWN, fabrique_couleur(0,255,0));
                    return 2;
                    break;
                }
                else if( (getpixel(i, j) == color)
                    && (getpixel(i + SIZE, j - SIZE) == color)
                    && (getpixel(i + 200, j - 200) == color) //(SIZE*2)
                    && (getpixel(i + 300, j - 300) == color) //(SIZE*3)
                    )
                {
                    dessiner_cercles_gagnants( i, j, DIAGONALEUP, fabrique_couleur(0,255,0));
                    return 2;
                    break;
                }
            }
        }
    }

    return 0;
}

void dessiner_cercles_gagnants( int x, int y, int sens, Couleur color )
{
    int i, j;
    switch( sens )
    {
        //on dessine les ronds alignés horizontalements en commençant par celui de gauche
        case HORIZONTAL:
        {
            for( i = x; i <= x + 300; i += 100)
            {
                dessiner_cercle( i, y, SIZEBY2, color);
                actualiser();
                attente(100);
            }
            break;
        }
        //on dessine les ronds alignés verticalement en commencant par le plus haut
        case VERTICAL:
        {
            for( i = y; i <= y + 300; i += 100)
            {
                dessiner_cercle( x, i, SIZEBY2, color);
                actualiser();
                attente(100);
            }
            break;
        }
        //on dessine les ronds en diagonale escalier qui descend en commencant par le plus a gauche
        case DIAGONALEDOWN:
        {
            for( i = x, j = y; i <= x + 300, j <= y + 300; i += 100, j += 100)
            {
                dessiner_cercle( i, j, SIZEBY2, color);
                actualiser();
                attente(100);
            }
            break;
        }
        //on dessine les ronds en diagonale escalier qui monte en commencant par le plus a gauche
        case DIAGONALEUP:
        {
            for( i = x, j = y; i <= x + 300, j >= y - 300; i += 100, j -= 100)
            {
                dessiner_cercle( i, j, SIZEBY2, color);
                actualiser();
                attente(100);
            }
            break;
        }
    }
}

void dessiner_quadrillage( int quadrillagesize, Couleur color )
{
    Point coin = { 0, 0 }, bascoin = { 0, H - quadrillagesize };
    int i,j;
    for( i = 0; i <= L; i += SIZE)
    {
        coin.x = i;
        for( j = 0; j <= H; j += SIZE )
        {
            coin.y = j;
            dessiner_rectangle(coin, quadrillagesize, H, color );
            dessiner_rectangle(coin, L, quadrillagesize, color );
        }
    }
    dessiner_rectangle(bascoin, L, quadrillagesize, color );
}

Point adversaire( Point p )
{
    Point position;
    int hasard = rand()%5;  //génère des valeurs de 0 à 5
    int colonnevalues[8] = { 0, 100, 200, 300, 400, 500, 600, 700 }; //tableau avec les valeurs des colonnes

    //si on pose 3 pions verticalement, le bot nous bloque en le placant dans la meme colonne
    if( (lastesthauteur < 450) || (lastesthauteur < 550 && hasard == 1) )
        position.x = p.x;
    //si la valeur retournée par le rand est >= 3, on place le pion du bot une colonne après notre pion (pour bloquer un eventuel alignement)
    else if( hasard >= 3)
    {
        position.x = p.x + colonnevalues[1];
        if( position.x >= 800 ) //si le pion qui doit etre placé est en dehors de la fenetre, on le place dans une colonne au hasard
            position.x = colonnevalues[rand()%8];
    }
    //si la valeur retournée par le rand est < 3, on place le pion du bot une colonne avant notre pion (pour bloquer un eventuel alignement)
    else
    {
        position.x = p.x - colonnevalues[1];
        if( position.x < 0 ) //si le pion qui doit etre placé est en dehors de la fenetre, on le place dans une des 3 premieres colonnes
            position.x = colonnevalues[rand()%3];
    }

    return position;
}

La lib graphique:

libgraphique.h


/*******************************************************************************
 * libraphique.c                                                               *
 * Quelques fonctions C basées sur la SDl pour réaliser des opérations         *
 * graphiques simples                                                          *
 *                                                                             *
 * Pour compiler en ligne de commande :                                        *
 * gcc ../lib/libgraphique.c prog.c -o resultat                                *
 *           `sdl-config --libs --cflags` -lm -lSDL                            *
 *                                                                             *
 * où                                                                          *
 *             prog.c : votre code source                                      *
 *             resultat    : nom de l'exécutable                               *
 *******************************************************************************
*/

///////////////////////////////////////////////////////////////////////////////
//0. Directive préprocesseur
#include <SDL.h>


///////////////////////////////////////////////////////////////////////////////
//1. Déclaration des types "maison"
typedef Uint32 Couleur;
typedef struct {int x,y;} Point;

extern SDL_Surface *ecran;


////////////////////////////////////////////////////////////////////////////////
// Déclaration des fonctions
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// 1. Ouvrir et fermer une fenêtre

// ouvrir une fenêtre de taille largeur (x), hauteur (y)
void ouvrir_fenetre(int largeur, int hauteur);

// terminer le programme
void fermer_fenetre();

// teste si la fin du programme a été demandée et le termine si nécessaire
// ne pas utiliser directement
void _test_arret() ;

////////////////////////////////////////////////////////////////////////////////
// 2. Fonctions de dessin

// actualise l'affichage des modifications graphiques
// sans appel à cet fonction les modifications sont non apparentes
void actualiser();

// fonction de dessin principale
// changer la couleur du Point pix
void changer_pixel(Point pix, Couleur couleur) ;

// dessine un rectangle de couleur de largeur et hauteur données
// coin est le coin haut, gauche
void dessiner_rectangle(Point coin, int largeur, int hauteur, Couleur couleur) ;

// trace une ligne du Point p1 au point p2 dela couleur donnée
// utilise l'algorithme de Bresenham
void dessiner_ligne(Point p1, Point p2, Couleur);

    // affiche l'image sous forme .bmp (bitmap), contenue dans le même dossier
// nom est une chaine de caracteres qui est le nom (complet) du fichier image
// coin est le coin haut, gauche voulu pour l'image à afficher dans l'ecran
void afficher_image(char *nom, Point coin);

////////////////////////////////////////////////////////////////////////////////
// 3. Gestion des événements

// renvoie le code SDLK de la prochaine touche pressée
// fonction bloquante
int attendre_touche(void);

// renvoie les coordonnees du prochain clic (gauche ou droite) de souris
// fonction bloquante
Point attendre_clic() ;

////////////////////////////////////////////////////////////////////////////////
// 4. Autres

// renvoie une Couleur (UInt32) RGB avec les valeurs entre 0 et 255 données
// en rouge r, vert g et bleu b
Couleur fabrique_couleur(int r, int g, int b);

// fait patienter la machine quelques millisecondes
void attente(int duree);

Uint32 getpixel(int x, int y);

void dessiner_cercle(int x, int y, int radius, Couleur couleur);



//CouleurS ///////////////////////
// 16 couleurs de base en francais

#define argent     0xC0C0C0
#define blanc      0xFFFFFF
#define bleu       0x0000FF
#define bleumarine 0x000080
#define citronvert 0x00FF00
#define cyan       0x00FFFF
#define magenta    0xFF00FF
#define gris       0x808080
#define jaune      0xFFFF00
#define marron     0x800000
#define noir       0x000000
#define rouge      0xFF0000
#define sarcelle   0x008080
#define vert       0x00FF00
#define vertclair  0x008000
#define vertolive  0x808000
#define violet     0x800080


// 140 couleurs en anglais
#define aliceblue            0xF0F8FF
#define antiquewhite         0xFAEBD7
#define aqua                 0x00FFFF
#define aquamarine           0x7FFFD4
#define azure                0xF0FFFF
#define beige                0xF5F5DC
#define bisque               0xFFE4C4
#define black                0x000000
#define blanchedalmond       0xFFEBCD
#define blue                 0x0000FF
#define blueviolet           0x8A2BE2
#define brown                0xA52A2A
#define burlywood            0xDEB887
#define cadetblue            0x5F9EA0
#define chartreuse           0x7FFF00
#define chocolate            0xD2691E
#define coral                0xFF7F50
#define cornflowerblue       0x6495ED
#define cornsilk             0xFFF8DC
#define crimson              0xDC143C
#define cyan                 0x00FFFF
#define darkblue             0x00008B
#define darkcyan             0x008B8B
#define darkgoldenrod        0xB8860B
#define darkgray             0xA9A9A9
#define darkgreen            0x006400
#define darkkhaki            0xBDB76B
#define darkmagenta          0x8B008B
#define darkolivegreen       0x556B2F
#define darkorange           0xFF8C00
#define darkorchid           0x9932CC
#define darkred              0x8B0000
#define darksalmon           0xE9967A
#define darkseagreen         0x8FBC8F
#define darkslateblue        0x483D8B
#define darkslategray        0x2F4F4F
#define darkturquoise        0x00CED1
#define darkviolet           0x9400D3
#define deeppink             0xFF1493
#define deepskyblue          0x00BFFF
#define dimgray              0x696969
#define dodgerblue           0x1E90FF
#define firebrick            0xB22222
#define floralwhite          0xFFFAF0
#define forestgreen          0x228B22
#define fuchsia              0xFF00FF
#define gainsboro            0xDCDCDC
#define ghostwhite           0xF8F8FF
#define gold                 0xFFD700
#define goldenrod            0xDAA520
#define gray                 0x808080
#define green                0x008000
#define greenyellow          0xADFF2F
#define honeydew             0xF0FFF0
#define hotpink              0xFF69B4
#define indianred            0xCD5C5C
#define indigo               0x4B0082
#define ivory                0xFFFFF0
#define khaki                0xF0E68C
#define lavender             0xE6E6FA
#define lavenderblush        0xFFF0F5
#define lawngreen            0x7CFC00
#define lemonchiffon         0xFFFACD
#define lightblue            0xADD8E6
#define lightcoral           0xF08080
#define lightcyan            0xE0FFFF
#define lightgoldenrodyellow 0xFAFAD2
#define lightgreen           0x90EE90
#define lightgrey            0xD3D3D3
#define lightpink            0xFFB6C1
#define lightsalmon          0xFFA07A
#define lightseagreen        0x20B2AA
#define lightskyblue         0x87CEFA
#define lightslategray       0x778899
#define lightsteelblue       0xB0C4DE
#define lightyellow          0xFFFFE0
#define lime                 0x00FF00
#define limegreen            0x32CD32
#define linen                0xFAF0E6
#define magenta              0xFF00FF
#define maroon               0x800000
#define mediumaquamarine     0x66CDAA
#define mediumblue           0x0000CD
#define mediumorchid         0xBA55D3
#define mediumpurple         0x9370DB
#define mediumseagreen       0x3CB371
#define mediumslateblue      0x7B68EE
#define mediumspringgreen    0x00FA9A
#define mediumturquoise      0x48D1CC
#define mediumvioletred      0xC71585
#define midnightblue         0x191970
#define mintcream            0xF5FFFA
#define mistyrose            0xFFE4E1
#define moccasin             0xFFE4B5
#define navajowhite          0xFFDEAD
#define navy                 0x000080
#define oldlace              0xFDF5E6
#define olive                0x808000
#define olivedrab            0x6B8E23
#define orange               0xFFA500
#define orangered            0xFF4500
#define orchid               0xDA70D6
#define palegoldenrod        0xEEE8AA
#define palegreen            0x98FB98
#define paleturquoise        0xAFEEEE
#define palevioletred        0xDB7093
#define papayawhip           0xFFEFD5
#define peachpuff            0xFFDAB9
#define peru                 0xCD853F
#define pink                 0xFFC0CB
#define plum                 0xDDA0DD
#define powderblue           0xB0E0E6
#define purple               0x800080
#define red                  0xFF0000
#define rosybrown            0xBC8F8F
#define royalblue            0x4169E1
#define saddlebrown          0x8B4513
#define salmon               0xFA8072
#define sandybrown           0xF4A460
#define seagreen             0x2E8B57
#define seashell             0xFFF5EE
#define sienna               0xA0522D
#define silver               0xC0C0C0
#define skyblue              0x87CEEB
#define slateblue            0x6A5ACD
#define slategray            0x708090
#define snow                 0xFFFAFA
#define springgreen          0x00FF7F
#define steelblue            0x4682B4
#define tann                 0xD2B48C
#define teal                 0x008080
#define thistle              0xD8BFD8
#define tomato               0xFF6347
#define turquoise            0x40E0D0
#define violetlight          0xEE82EE
#define wheat                0xF5DEB3
#define white                0xFFFFFF
#define whitesmoke           0xF5F5F5
#define yellow               0xFFFF00
#define yellowgreen          0x9ACD32

libgraphique.c


/*******************************************************************************
 * libraphique.c                                                               *
 * Quelques fonctions C basées sur la SDl pour réaliser des opérations         *
 * graphiques simples                                                          *
 *                                                                             *
 * Pour compiler en ligne de commande :                                        *
 * gcc ../lib/libgraphique.c prog.c -o resultat                                *
 *           `sdl-config --libs --cflags` -lm -lSDL                            *
 *                                                                             *
 * où                                                                          *
 *             prog.c : votre code source                                      *
 *             resultat    : nom de l'exécutable                               *
 *******************************************************************************
*/

////////////////////////////////////////////////////////////////////////////////
// 0. directives préprocesseur

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "libgraphique.h"


////////////////////////////////////////////////////////////////////////////////
// 0. variables globales et macros

SDL_Surface *ecran = NULL;                 // totalité de l'écran
SDL_Event lastevent ;                      // utilisé pour gestion événements
int LARGEUR = -1 ;                         // largeur de l'écran en pixels
int HAUTEUR = -1 ;                         // hauteur de l'écran en pixels
#define octets_par_pixel ecran->format->BytesPerPixel
#define largeur_ecran (ecran->pitch / 4)


////////////////////////////////////////////////////////////////////////////////
// 1. Ouvrir et fermer une fenêtre

// ouvrir une fenêtre de taille largeur (x), hauteur (y)
void ouvrir_fenetre(int largeur, int hauteur){
    SDL_Init(SDL_INIT_VIDEO);
    //appliquer une icone a la fenetre
    SDL_WM_SetIcon(SDL_LoadBMP("image/puissance4_icone.bmp"), NULL);

    ecran = SDL_SetVideoMode(largeur, hauteur, 32, SDL_HWSURFACE );

    //titre de la fenetre
    SDL_WM_SetCaption("Puissance 4 by Arnaud", NULL);

    //initialisation des variables globales
    LARGEUR = largeur ;
    HAUTEUR = hauteur ;
    printf("LARGEUR %d HAUTEUR %d\n",LARGEUR,HAUTEUR);

    // pour permettre les répétitions de touche si elles restent enfoncées
    SDL_EnableKeyRepeat(100, 100);
}


// terminer le programme
void fermer_fenetre(){
    SDL_Quit();
    exit(0);
}

// teste si la fin du programme a été demandée et le termine si nécessaire
void _test_arret() {
    if ((lastevent.type == SDL_QUIT) ||
            ( (lastevent.type == SDL_KEYDOWN )
              && (lastevent.key.keysym.sym == SDLK_ESCAPE))
       )
        fermer_fenetre() ;
}


///////////////////////////////////////////////////////////////////////////////
// 2. Fonctions de dessin

// actualise l'affichage des modifications graphiques
// sans appel à cet fonction les modifications sont non apparentes
void actualiser(){
    SDL_PollEvent(&lastevent) ;
    _test_arret();
    SDL_Flip(ecran) ;
}


// fonction de dessin principale
// changer la couleur du Point pix
void changer_pixel(Point pix, Couleur couleur) {
    if ((0 <= pix.x) && (pix.x < LARGEUR) && (0 <= pix.y ) && (pix.y < HAUTEUR))
    {
        *( (Uint32*)ecran->pixels + pix.y * largeur_ecran + pix.x ) = couleur ;
    }
}


// dessine un rectangle de couleur de largeur et hauteur données
// coin est le coin haut, gauche
void dessiner_rectangle(Point coin, int largeur, int hauteur, Couleur couleur) {
    Point p ;
    int bord_droit = coin.x + largeur ;
    int bord_bas = coin.y + hauteur ;
    for (p.x = coin.x; p.x < bord_droit ; ++(p.x)) {
        for (p.y = coin.y ; p.y  < bord_bas ; ++(p.y) ) {
            changer_pixel(p, couleur);
        }
    }
}

// trace une ligne du Point p1 au point p2 dela couleur donnée
// utilise l'algorithme de Bresenham
void dessiner_ligne(Point p1, Point p2, Couleur couleur)
{
    // signes deplacement x et y
    int dx, dy ;

    printf("x %d y %d   ",p2.x,p2.y);
    if (p1.x < p2.x)
        dx = 1 ;
    else if (p1.x > p2.x)
        dx = -1 ;
    else
        dx = 0 ;

    if (p1.y < p2.y)
        dy = 1 ;
    else if (p1.y > p2.y)
        dy = -1 ;
    else
        dy = 0 ;
    printf("dx %d dy %d   ",dx,dy);

    // valeur absolue pente
    float pente_abs ;

    float erreur = 0;
    Point p ; // point courant

    //lignes horizontales et certicales : plus rapide
    if (dy == 0)
    {
        printf(" H\n");
        p.y = p1.y ;
        for(p.x = p1.x ; p.x != p2.x ; p.x += dx)
            changer_pixel(p,couleur);
    }
    else if (dx == 0)
    {
        printf(" V\n");
        p.x = p1.x ;
        for(p.y = p1.y ; p.y != p2.y ; p.y += dy)
            changer_pixel(p,couleur);
    }
    else
    {

        pente_abs  = (p2.y - p1.y)/((float)(p2.x - p1.x)) ;
        if (pente_abs < 0)
            pente_abs = - pente_abs ;
        printf("%f ", pente_abs);

        if (pente_abs <=1 )
        {
            printf(" A\n");
            {
                p.y = p1.y ;
                for(p.x = p1.x ; p.x != p2.x ; p.x += dx)
                {
                    changer_pixel(p, couleur);
                    erreur += pente_abs ;
                    printf("erreur %f\n",erreur);
                    if (erreur > 0.5)
                    {
                        erreur -= 1 ;
                        p.y += dy ;
                    }
                }
            }
        }
        else
        {
            pente_abs = 1/pente_abs ;
            printf(" B\n");
            p.x = p1.x ;
            for(p.y = p1.y ; p.y != p2.y ; p.y += dy)
            {
                changer_pixel(p, couleur);
                erreur += pente_abs ;
                if (erreur > 0.5)
                {
                    erreur -= 1 ;
                    p.x += dx ;
                }
            }
        }
    }
    changer_pixel(p2,couleur);
}


// affiche l'image sous forme .bmp (bitmap), contenue dans le même dossier
// nom est une chaine de caracteres qui est le nom (complet) du fichier image
// coin est le coin haut, gauche voulu pour l'image à afficher dans l'ecran
void afficher_image(char *nom, Point coin){
    SDL_Surface *img = SDL_LoadBMP(nom) ;
    SDL_Rect position_img ;
    position_img.x = coin.x;
    position_img.y = coin.y;
    SDL_BlitSurface(img,NULL,ecran,&position_img);
}


////////////////////////////////////////////////////////////////////////////////
// 3. Gestion des événements

// renvoie le code SDLK de la prochaine touche pressée
// fonction bloquante
int attendre_touche(void){
    do {
        SDL_WaitEvent(&lastevent) ;
        _test_arret() ;
    }
    while (lastevent.type != SDL_KEYDOWN ) ;
    return lastevent.key.keysym.sym;
}

// renvoie les coordonnees du prochain clic (gauche ou droite) de souris
// fonction bloquante
Point attendre_clic() {
    do {
        SDL_WaitEvent(&lastevent) ;
        _test_arret();
    }
    while (lastevent.type != SDL_MOUSEBUTTONDOWN) ;
    Point p ;
    p.x = lastevent.button.x ;
    p.y = lastevent.button.y ;
    return p;
}


////////////////////////////////////////////////////////////////////////////////
// 4. Autres

// renvoie une Couleur (UInt32) RGB avec les valeurs entre 0 et 255 données
// en rouge r, vert g et bleu b
Couleur fabrique_couleur(int r, int g, int b)
{
    Couleur C;
    return ((r%256)<<16) + ((g%256)<<8) + (b%256);
    return C;
}

// fait patienter la machine quelques millisecondes
void attente(int duree)
{
    SDL_Delay(duree) ;
}

Uint32 getpixel(int x, int y)
{
    //pas fait pas moi
    int bpp = ecran->format->BytesPerPixel;
    Uint8 *p = (Uint8 *)ecran->pixels + y * ecran->pitch + x * bpp;

    switch(bpp) {
    case 1:
        return *p;

    case 2:
        return *(Uint16 *)p;

    case 3:
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
            return p[0] << 16 | p[1] << 8 | p[2];
        else
            return p[0] | p[1] << 8 | p[2] << 16;

    case 4:
        return *(Uint32 *)p;

    default:
        return 0;
    }
}

//cred to Daniel Earwicker
void dessiner_cercle(int x, int y, int radius, Couleur couleur)
{
    Point center;
    int xx, yy;
    for(xx = -radius; xx < radius ; xx++)
    {
        int height = (int)sqrt( (radius*radius) - (xx * xx));

        for(yy = -height; yy < height; yy++)
        {
            center.x = xx + x; center.y = yy + y;
            changer_pixel( center, couleur );
        }
    }
}

 

J'avais eu 19 avec ce truc j'crois

Lien vers le commentaire
Partager sur d’autres sites

  • 2 semaines après...
Sur 9/1/2016 at 14:43 , arcuz06 a déclaré:

Ton jeu est super ; jpense que je vais me mettre au C ^^

Merci ouais :P Le C++ est mieux que le C, mais si tu apprends le C d'abord, tu vas avoir des facilités pour le C++.

Ouais bon courage At0mox!

Lien vers le commentaire
Partager sur d’autres sites

Veuillez vous connecter pour commenter

Vous pourrez laisser un commentaire après vous êtes connecté.



Connectez-vous maintenant
×
×
  • Créer...

Information importante

En navigant ce site, vous acceptez nos Politique de confidentialité.