Advertisement
Guest User

Untitled

a guest
Sep 19th, 2017
334
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 25.32 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <errno.h>
  4. #include <string.h>
  5. #include <stdbool.h>
  6.  
  7. #ifdef WIN32
  8.   #define HAS_SOCKET
  9.   #include <winsock2.h>
  10.   #define close(s) closesocket(s)
  11.  
  12.   typedef int socket;
  13.   typedef struct SOCKADDR_IN sockaddr_in;
  14.   typedef struct SOCKADDR sockaddr;
  15.   typedef struct IN_ADDR in_addr;
  16.  
  17. #elif defined(linux)
  18.   #define HAS_SOCKET  
  19.   #include <sys/types.h>
  20.   #include <sys/socket.h>
  21.   #include <netinet/in.h>
  22.   #include <arpa/inet.h>
  23.   #include <unistd.h>
  24.   #include <netdb.h>
  25.  
  26.   #define INVALID_SOCKET -1
  27.   #define SOCKET_ERROR -1
  28.  
  29. #endif
  30.  
  31. /** Obtient une chaîne de caractères depuis l'entrée standard. Le
  32.   * buffer doit être correctement alloué en mémoire avant l'appel.
  33.   * @param buffer Pointeur sur le buffer.
  34.   * @param buffer_size Taille du buffer en octet. */
  35. void get_string (char * buffer, size_t buffer_size)
  36. {
  37.   fgets (buffer, buffer_size, stdin);
  38.  
  39.   char *ptr = strchr (buffer, '\n');
  40.   if (ptr != NULL)
  41.     *ptr = 0;
  42.   else
  43.     {
  44.       char c;
  45.       while ((c = getchar())!='\n' && c != EOF);
  46.     }
  47. }
  48.  
  49. /** Obtient un entier de 32 bits depuis l'entrée standard.
  50.   * L'entier est interprété en représentation décimale.
  51.   * @return Entier obtenu ou 0 en cas d'échec. */
  52. int get_int (void)
  53. {
  54.   int integer = 0;
  55.   char *buffer = malloc (11);
  56.   char *endptr;
  57.   if (buffer != NULL)
  58.     {
  59.       get_string (buffer, 11);
  60.       errno = 0;
  61.       integer = strtol (buffer, &endptr, 10);
  62.       if (errno != 0)
  63.     return integer;
  64.    
  65.       free (buffer);
  66.     }
  67.  
  68.   return integer;
  69. }
  70.  
  71. /** Obtient un caractère depuis l'entrée standard.
  72.   * @return Caractère obtenu. */
  73. char get_char (void)
  74. {
  75.   char c = getchar();
  76.   while (getchar() != '\n');
  77.   return c;
  78. }
  79.  
  80.  
  81.  
  82. /** Structure représentant un noeud
  83.   * de l'arbre. */
  84. typedef struct _Node
  85. {
  86.   struct _Node **children;
  87.   size_t child_n;
  88.  
  89.   struct _Node *parent;
  90.   void *data;
  91. } Node;
  92.  
  93. /** Crée un nouveau noeud.
  94.   * @param data Pointeur sur les données.
  95.   * @return Pointeur sur le nouveau noeud. */
  96. Node *node_new (void *data)
  97. {
  98.   Node * node = (Node *)malloc (sizeof (*node));
  99.   if (node != NULL)
  100.     {
  101.       node->children = NULL;
  102.       node->child_n = 0;
  103.       node->parent = NULL;
  104.       node->data = data;
  105.     }
  106.    
  107.   return node;
  108. }
  109.  
  110. /** Libère la mémoire occupée par un noeud et
  111.   * ses enfants.
  112.   * @param node Pointeur sur le noeud. */
  113. void node_destroy (Node *node)
  114. {
  115.   if (node != NULL)
  116.     {
  117.       int pos;
  118.       for (pos=0; pos < node->child_n; pos++)
  119.     node_destroy (node->children [pos]);
  120.  
  121.       if (node->children != NULL)
  122.     free (node->children);
  123.       free (node);
  124.     }
  125. }
  126.  
  127. /** Structure contenant un arbre
  128.   * où chaque noeud possède un unique parent
  129.   * mais une multitude d'enfants. */
  130. typedef struct _Tree Tree;
  131.  
  132. struct _Tree
  133. {
  134.   Node *root;
  135. };
  136.  
  137. /** Crée un nouvel arbre dynamique.
  138.   * @return Pointeur sur le nouvel arbre. */
  139. Tree *tree_new (void)
  140. {
  141.   Tree *tree = (Tree *)malloc (sizeof (*tree));
  142.   if (tree != NULL)
  143.     {
  144.       tree->root = NULL;
  145.     }
  146.    
  147.   return tree;
  148. }
  149.  
  150. /** Libère la mémoire occupée par l'arbre.
  151.   * @param tree Pointeur sur l'arbre à libérer. */
  152. void tree_destroy (Tree *tree)
  153. {
  154.   if (tree != NULL)
  155.     {
  156.       node_destroy (tree->root);
  157.       free (tree);
  158.     }
  159. }
  160.  
  161. typedef struct _Menu Menu;
  162.  
  163. typedef void (*Callback) (const Menu*, void *data);
  164. #define CALLBACK(func) (Callback)(func)
  165.  
  166. typedef struct
  167. {
  168.   const char *name;
  169.   Callback callback;
  170.   void *data;
  171. } Action;
  172.  
  173. struct _Menu
  174. {
  175.   const char *title;
  176.   Action *actions;
  177.   size_t action_n;
  178.   unsigned int default_action;
  179.   const Menu *parent;
  180. };
  181.  
  182. Menu *menu_new (const char * title)
  183. {
  184.   Menu *menu = (Menu *)malloc(sizeof (*menu));
  185.   if (menu != NULL)
  186.     {
  187.       menu->title = title;
  188.       menu->actions = NULL;
  189.       menu->action_n = 0;
  190.       menu->default_action = 0;
  191.       menu->parent = NULL;
  192.     }
  193.  
  194.   return menu;
  195. }
  196.  
  197. void menu_add_action (Menu *menu, const char *entry, Callback callback, void *data)
  198. {
  199.   menu->action_n++;
  200.   menu->actions = (Action *)realloc (menu->actions, sizeof (Action)*menu->action_n);
  201.  
  202.   Action action = {entry, callback, data};
  203.   size_t pos = menu->action_n - 1;
  204.   menu->actions [pos] = action;
  205. }
  206.  
  207. void menu_set_default_action (Menu *menu, unsigned int default_action)
  208. {
  209.   if (default_action < menu->action_n)
  210.     menu->default_action = default_action;
  211. }
  212.  
  213. void menu_set_parent (Menu *menu, const Menu *parent)
  214. {
  215.   menu->parent = parent;
  216. }
  217.  
  218. void menu_exec (const Menu *menu)
  219. {
  220.   printf ("\n%s\n", menu->title);
  221.   int pos;
  222.   for (pos=0; pos < menu->action_n; pos++)
  223.     printf ("[%i]\t%s\t\n", pos+1, menu->actions [pos].name);
  224.  
  225.   if (menu->parent != NULL)
  226.     printf ("[%i]\tRetour\t\n", ++pos);
  227.  
  228.   printf ("Entrez votre choix [1..%i](%i): ", pos, menu->default_action+1);
  229.   fflush (stdout);
  230.  
  231.   int choice = get_int ()-1;
  232.   if (choice >= -1 && choice < menu->action_n)
  233.     {
  234.       Callback callback = NULL;
  235.       if (choice == -1 && menu->default_action < menu->action_n)
  236.     callback = menu->actions [menu->default_action].callback;
  237.       else if (choice >= 0)
  238.     callback = menu->actions [choice].callback;
  239.      
  240.       if (callback != NULL)
  241.     callback(menu, menu->actions [choice].data);
  242.     }
  243.   else if (choice == pos-1)
  244.       menu_exec (menu->parent);
  245.   else
  246.     fprintf (stderr, "Entrée incorrecte :(\n");
  247. }
  248.  
  249. void menu_sub_exec (const Menu *menu, void *data)
  250. {
  251.   menu_exec ((const Menu *)(data));
  252. }
  253.  
  254. void menu_destroy (Menu *menu)
  255. {
  256.   if (menu != NULL)
  257.     {
  258.       if (menu->actions != NULL)
  259.     free (menu->actions);
  260.       free (menu);
  261.     }
  262. }
  263.  
  264.  
  265.  
  266. #define GRILLE_MAX_TAILLE 25
  267. #define GRILLE_MIN_TAILLE 6
  268. #define GRILLE_DEFAUT_TAILLE 7
  269.  
  270. #define TAILLE_DU_NOM 256
  271. #define TAILLE_MAX_URL 256
  272. #define TAILLE_MSG_RES 5
  273.  
  274. #define NOMBRE_DEFAUT_DE_JOUEURS 2
  275. #define NOMBRE_MAX_DE_JOUEURS 4
  276.  
  277. #define PORT_SERVEUR_DEFAUT 4900
  278.  
  279. typedef struct
  280. {
  281.   char nom [TAILLE_DU_NOM];
  282.   char jeton;
  283.   bool avecIA;
  284.   unsigned int score;
  285. } Joueur;
  286.  
  287. enum {LOCAL, SERVEUR, CLIENT};
  288.  
  289. typedef struct
  290. {
  291.   /** Plateau du jeu. */
  292.   int *grille;
  293.   short int *remplissage;
  294.   size_t largeur, hauteur;
  295.  
  296.   /** Joueurs. */
  297.   Joueur joueurs [NOMBRE_MAX_DE_JOUEURS];
  298.   size_t nombreDeJoueurs;
  299.  
  300.   /** Réseau. */
  301.   int type;
  302.   int sock;
  303.   int *clientSocks;
  304.   struct sockaddr_in *clientSins;
  305.   unsigned int portServeur;
  306.  
  307.   bool finDuJeu;
  308. } Puissance4;
  309.  
  310. typedef struct
  311. {
  312.   size_t largeur, hauteur;
  313.   char noms [NOMBRE_MAX_DE_JOUEURS][TAILLE_DU_NOM];
  314.   size_t nombreDeJoueurs;
  315. } Puissance4Info;
  316.  
  317. /** Initialise la structure Puissance4 avec
  318.   * des valeurs par défaut. Configure une
  319.   * partie avec deux joueurs humains sur une grilles
  320.   * classique de puissance 4. */
  321. Puissance4 nouveauPuissance4 (void)
  322. {
  323.   Puissance4 jeu;
  324.  
  325.   jeu.largeur = GRILLE_DEFAUT_TAILLE;
  326.   jeu.hauteur = GRILLE_DEFAUT_TAILLE-1;
  327.   jeu.grille = (int *)malloc(sizeof (*jeu.grille)*jeu.largeur*jeu.hauteur);
  328.   jeu.remplissage = (short int *)malloc(sizeof (*jeu.remplissage)*jeu.largeur);
  329.   jeu.nombreDeJoueurs = NOMBRE_DEFAUT_DE_JOUEURS;
  330.   jeu.portServeur = PORT_SERVEUR_DEFAUT;
  331.   jeu.type = LOCAL;
  332.  
  333.   char nomDuJoueur [TAILLE_DU_NOM];
  334.   int pos;
  335.   for (pos=0; pos < NOMBRE_MAX_DE_JOUEURS; pos++)
  336.     {
  337.       sprintf (nomDuJoueur, "Joueur %i", pos+1);
  338.       strncpy (jeu.joueurs [pos].nom, nomDuJoueur, TAILLE_DU_NOM);
  339.       jeu.joueurs [pos].jeton = 0x30 + pos + 1;
  340.       jeu.joueurs [pos].avecIA = false;
  341.       jeu.joueurs [pos].score = 0;
  342.     }
  343.  
  344.   return jeu;
  345. }
  346.  
  347. /** Libère la mémoire utilisée par le puissance 4. */
  348. void libererPuissance4 (Puissance4 *jeu)
  349. {
  350.   if (jeu != NULL)
  351.     {
  352.       if (jeu->grille !=NULL)
  353.     free (jeu->grille);
  354.       if (jeu->remplissage != NULL)
  355.     free (jeu->remplissage);
  356.     }
  357. }
  358.  
  359. /** Détermine si une case est dans la grille. */
  360. bool dansGrille (const Puissance4 *jeu, int x, int y)
  361. {
  362.   return (x >= 0 && x < jeu->largeur &&
  363.   y >= 0 && y < jeu->hauteur);
  364. }
  365.  
  366. /** Détermine si un coup est possible ou non. */
  367. bool jouable (const Puissance4 *jeu, int x)
  368. {
  369.   return (dansGrille(jeu, x, 0) &&
  370.   jeu->remplissage[x] < jeu->hauteur);
  371. }
  372.  
  373. /** Cherche un alignement de jeton à partir d'une
  374.   * position donnée dans la grille. */
  375. unsigned int adjacent (const Puissance4 *jeu, int c, int l, int dirV, int dirH)
  376. {
  377.   unsigned int nombreDeJetons = 0;
  378.   int *jetonCourant = jeu->grille+c+l*jeu->largeur;
  379.   int jetonDuJoueur = *jetonCourant;
  380.   do
  381.   {
  382.     nombreDeJetons++;
  383.    
  384.     /** Incrémente le pointeur sur le jeton courant. */
  385.     jetonCourant += dirV+dirH*jeu->largeur; c+=dirV; l+=dirH;
  386.    
  387.     /** Vérifie si le pointeur obtenu est valide et regarde
  388.       * s'il s'agit bien d'un jeton du joueur courant. */
  389.   } while(dansGrille(jeu, c,l) && *jetonCourant == jetonDuJoueur);
  390.  
  391.   return nombreDeJetons-1;
  392. }
  393.  
  394. /** Détermine si la partie est finie ou pas. */
  395. bool partieEstGagneeOuPas (const Puissance4 *jeu, int c, int l)
  396. {
  397.   int directions [][2] = {{0, 1}, {1, 0}, {1, 1}, {1, -1}};
  398.   int pos;
  399.   for (pos=0; pos < 4; pos++)
  400.     {
  401.       int dirV = directions [pos][0], dirH = directions [pos][1];
  402.       unsigned int n1 = adjacent (jeu, c, l, dirV, dirH);
  403.       unsigned int n2 = adjacent (jeu, c, l, -dirV, -dirH);
  404.       if ((n1+n2+1) >= 4)
  405.     return true;
  406.     }
  407.  
  408.   return false;
  409. }
  410.  
  411. /** Demande à l'utilisateur de saisir un coup à jouer. */
  412. unsigned int saisirCoup (const Puissance4 *jeu, const char *nom)
  413. {
  414.   unsigned int x;
  415.   do
  416.     {
  417.       printf ("Entrez le numéro de colonne %s [1-%i]: ", nom, jeu->largeur);
  418.       x = get_int ();
  419.     } while (!jouable (jeu, --x));
  420.  
  421.   return x;
  422. }
  423.  
  424. /** Affiche une ligne de tirets pour séparer deux
  425.   * lignes de la grille. */
  426. void afficherSeparateurDeLigne (unsigned int taille)
  427. {
  428.   unsigned int x;
  429.   for (x=0; x < taille; x++)
  430.       printf ("+---");
  431.   printf ("+\n");
  432. }
  433.  
  434. /** Nettoye l'écran pour un meilleur affichage
  435.   * de la grille. */
  436. void nettoyerEcran (void)
  437. {
  438.   #ifdef WIN32
  439.     system("cls");
  440.   #else
  441.     printf("\033[H\033[2J");
  442.   #endif
  443. }
  444.  
  445. /** Affiche la grille du jeu dans le terminal. */
  446. void afficherGrille (const Puissance4 *jeu)
  447. {
  448.   nettoyerEcran();
  449.   afficherSeparateurDeLigne (jeu->largeur);
  450.   int x, y;
  451.   for (y=jeu->hauteur-1; y >= 0; y--)
  452.     {
  453.       for (x=0; x < jeu->largeur; x++)
  454.       {
  455.     char str[] = "|   ";
  456.     const int valeur = *(jeu->grille+x+y*jeu->largeur);
  457.     if (valeur >= 0 && valeur < NOMBRE_MAX_DE_JOUEURS)
  458.       sprintf(str, "| %c ", jeu->joueurs [valeur].jeton);
  459.      
  460.     printf ("%s", str);
  461.       }
  462.       printf ("|\n");
  463.       afficherSeparateurDeLigne (jeu->largeur);
  464.     }
  465.  
  466.   /** Affiche une aide pour repérer le numéro des colonnes. */
  467.   for (x=1; x <= jeu->largeur; x++)
  468.     printf ("-%2i ", x);
  469.   printf ("-\n");
  470. }
  471.  
  472. /** Détermine si la grille est remplie ou non. */
  473. bool estRemplieOuNon (const Puissance4 *jeu)
  474. {
  475.   int x;
  476.   for (x=0; x < jeu->largeur; x++)
  477.     if (jeu->remplissage [x] != jeu->hauteur-1)
  478.       return false;
  479.  
  480.   return true;
  481. }
  482.  
  483. /** Vide la grille de tous les jetons. */
  484. void nettoyerGrille (Puissance4 *jeu)
  485. {
  486.   memset (jeu->grille, -1, sizeof (int)*jeu->largeur*jeu->hauteur);
  487.   memset (jeu->remplissage, 0, sizeof (short int)*jeu->largeur);
  488. }
  489.  
  490. /** Affiche le score de chaque joueur sous la forme
  491.   * d'un tableau de deux colonnes. */
  492. void afficherScore (const Menu *menu, void *data)
  493. {
  494.   Puissance4 *jeu = (Puissance4 *)data;
  495.   printf ("+------------+------------+\n");
  496.   printf ("|    Nom     |    Score   |\n");
  497.   printf ("+------------+------------+\n");
  498.   int x;
  499.   for (x=0; x < jeu->nombreDeJoueurs; x++)
  500.     printf ("| %-11s| %-11i|\n", jeu->joueurs [x].nom, jeu->joueurs [x].score);
  501.  
  502.   printf ("+------------+------------+\n");  
  503. }
  504.  
  505. /** Lance une nouvelle partie de puissance 4.
  506.   * Une fois la partie achevée les scores des joueurs sont affichés. */
  507. void lancerJeu (const Menu *menu, void *data)
  508. {
  509.   Puissance4 *jeu = (Puissance4 *)data;
  510.   nettoyerGrille(jeu);
  511.   afficherGrille(jeu);
  512.  
  513.   unsigned int tour = 0;
  514.   while (!estRemplieOuNon (jeu))
  515.     {
  516.       Joueur *joueurCourant = &jeu->joueurs [tour%jeu->nombreDeJoueurs];
  517.       unsigned int x = saisirCoup(jeu, joueurCourant->nom);
  518.       unsigned int y = jeu->remplissage [x]++;
  519.       *(jeu->grille+x+y*jeu->largeur) = tour%jeu->nombreDeJoueurs;
  520.       afficherGrille(jeu);
  521.      
  522.       /** Vérifie si la partie n'est pas terminée. */
  523.       if (partieEstGagneeOuPas (jeu,x,y))
  524.     {
  525.       printf ("Vous avez gagné %s!\n", joueurCourant->nom);
  526.       joueurCourant->score++;
  527.       break;
  528.     }
  529.      
  530.       tour++;
  531.     }
  532.    
  533.   afficherScore (menu, data);
  534. }
  535.  
  536. /** Lance une partie en local. */
  537. void lancerPartieLocal (const Menu *menu, void *data)
  538. {
  539.   Puissance4 *jeu = (Puissance4 *)data;
  540.   lancerJeu (menu, data);
  541. }
  542.  
  543. /** Réceptionne le nom d'un client et l'enregistre
  544.   * auprès du serveur. */
  545. void lireNomDuClient (Puissance4 *jeu, unsigned int pos)
  546. {
  547.   /** Récupère le nom du joueur. */
  548.   char nom[TAILLE_DU_NOM];
  549.   unsigned int n;
  550.   if ((n = recv(jeu->clientSocks [pos], nom, TAILLE_DU_NOM-1, 0)) >= 0)
  551.     {
  552.       nom[n] = '\0';
  553.       strncpy (jeu->joueurs [pos+1].nom, nom, TAILLE_DU_NOM);
  554.       printf ("%s a rejoint la partie.\n", nom);
  555.     }
  556.   else
  557.     perror ("recv()");
  558. }
  559.  
  560. /** Lance un serveur pour une partie en réseau. */
  561. void lancerServeur (const Menu *menu, void *data)
  562. {
  563.   Puissance4 *jeu = (Puissance4 *)data;
  564.   jeu->type = SERVEUR;
  565.  
  566.   #ifdef HAS_SOCKET
  567.   /** Tableaux contenant les sockets et les informations
  568.     * sur les clients. */
  569.   jeu->clientSocks = (int *)malloc(sizeof (*jeu->clientSocks)*(jeu->nombreDeJoueurs-1));
  570.   jeu->clientSins = (struct sockaddr_in *)malloc(sizeof (*jeu->clientSins)*(jeu->nombreDeJoueurs-1));
  571.  
  572.   /** Création du socket pour le serveur. */
  573.   jeu->sock = socket (AF_INET, SOCK_STREAM, 0);
  574.   if (jeu->sock != INVALID_SOCKET)
  575.     {
  576.       struct sockaddr_in sin = {0};
  577.       sin.sin_addr.s_addr = htonl (INADDR_ANY);
  578.       sin.sin_family = AF_INET;
  579.       sin.sin_port = htons (jeu->portServeur);
  580.       if (bind (jeu->sock, (struct sockaddr *)&sin, sizeof (sin)) != SOCKET_ERROR)
  581.     {
  582.       Puissance4Info info;
  583.       unsigned int joueurs;
  584.        
  585.       /** Mise en écoute sur le port jeu->portServeur. */
  586.        if (listen (jeu->sock, jeu->nombreDeJoueurs-1) != SOCKET_ERROR)
  587.         {
  588.           /** Préparation des informations à transmettre
  589.           * aux joueurs. */
  590.           info.largeur = jeu->largeur;
  591.           info.hauteur = jeu->hauteur;
  592.           info.nombreDeJoueurs = jeu->nombreDeJoueurs;
  593.           strncpy (info.noms [0], jeu->joueurs [0].nom, TAILLE_DU_NOM);
  594.          
  595.           printf ("En attente des autres joueurs... (%i)\n", jeu->nombreDeJoueurs-1);
  596.           /** Attend que tous les clients soient connectés. */
  597.           for (joueurs=0; joueurs < jeu->nombreDeJoueurs-1; joueurs++)
  598.         {
  599.           int csock;
  600.           struct sockaddr_in csin = {0};
  601.           socklen_t csocklen = sizeof (struct sockaddr_in);  
  602.           csock = accept (jeu->sock, (struct sockaddr *)&csin, &csocklen);
  603.              
  604.           /** Un nouveau client est accepté. */
  605.           if (csock != INVALID_SOCKET)
  606.             {
  607.               jeu->clientSocks [joueurs] = csock;
  608.               jeu->clientSins [joueurs] = csin;
  609.               lireNomDuClient (jeu, joueurs);
  610.               strncpy (info.noms [joueurs+1], jeu->joueurs [joueurs+1].nom,
  611.                    TAILLE_DU_NOM);
  612.             }
  613.           else
  614.             perror ("accept()");
  615.         }
  616.         }
  617.        
  618.         /** Transmission des informations aux joueurs. */
  619.         for (joueurs=0; joueurs < jeu->nombreDeJoueurs-1; joueurs++)
  620.         if (send (jeu->clientSocks [joueurs], &info, sizeof (Puissance4Info), 0) < 0)
  621.           perror ("send()");
  622.        
  623.         /** Une fois que tous les clients sont prêts, la partie est lancée. */
  624.         lancerJeu (menu, data);
  625.     }
  626.      
  627.       close (jeu->sock);
  628.     }
  629.   else
  630.     perror ("socket()");
  631.  
  632.   /** Ferme les sockets des clients. */
  633.   int pos;
  634.   for (pos=0; pos < jeu->nombreDeJoueurs-1; pos++)
  635.     close (jeu->clientSocks [pos]);
  636.  
  637.   free (jeu->clientSocks);
  638.   free (jeu->clientSins);
  639.   #endif /* HAS_SOCKET */
  640.  
  641.   jeu->type = LOCAL;
  642. }
  643.  
  644. /** Envoie son nom au serveur. */
  645. void envoyerSonNomAuServeur (Puissance4 *jeu)
  646. {
  647.   #ifdef HAS_SOCKET
  648.   char nom [TAILLE_DU_NOM];
  649.   do
  650.     {
  651.       printf ("Entrez votre nom: ");
  652.       get_string (nom, TAILLE_DU_NOM);
  653.     } while (strlen (nom) < 3);
  654.  
  655.   if (send (jeu->sock, nom, TAILLE_DU_NOM, 0) < 0)
  656.     {
  657.       perror ("send()");
  658.     }
  659.   #endif /* HAS_SOCKET */
  660. }
  661.  
  662. /** Lance un client pour une partie en réseau. */
  663. void lancerClient (const Menu *menu, void *data)
  664. {
  665.   Puissance4 *jeu = (Puissance4 *)data;
  666.   jeu->type = CLIENT;
  667.  
  668.   #ifdef HAS_SOCKET
  669.   /** Demande l'url du serveur au joueur. */
  670.   char hostname[TAILLE_MAX_URL];
  671.   printf ("Entrez l'url du serveur: ");
  672.   get_string (hostname, TAILLE_MAX_URL);
  673.  
  674.   /** Création du socket pour le serveur. */
  675.   jeu->sock = socket (AF_INET, SOCK_STREAM, 0);
  676.   if (jeu->sock != INVALID_SOCKET)
  677.     {
  678.       struct hostent *hostinfo = NULL;
  679.       struct sockaddr_in sin = {0};
  680.      
  681.       /** Récupération des informations sur l'hôte. */
  682.       hostinfo = gethostbyname (hostname);
  683.       if (hostinfo != NULL)
  684.     {
  685.       sin.sin_addr = *(struct in_addr *)hostinfo->h_addr;
  686.       sin.sin_port = htons (jeu->portServeur);
  687.       sin.sin_family = AF_INET;
  688.      
  689.       /** Connexion au serveur. */
  690.       printf ("Tentative de connexion à %s...\n", hostname);
  691.       if (connect (jeu->sock, (struct sockaddr *)&sin, sizeof (struct sockaddr)) != SOCKET_ERROR)
  692.         {
  693.           printf ("Connexion établie.\n");
  694.           envoyerSonNomAuServeur (jeu);
  695.          
  696.           /** Réception des informations sur la partie. */
  697.           Puissance4Info info;
  698.           if (recv (jeu->sock, &info, sizeof (Puissance4Info), 0) >= 0)
  699.         {
  700.           jeu->largeur = info.largeur;
  701.           jeu->hauteur = info.hauteur;
  702.           jeu->nombreDeJoueurs = info.nombreDeJoueurs;
  703.          
  704.           /** Récupère le nom des joueurs. */
  705.           unsigned int joueurs;
  706.           for (joueurs=0; joueurs < jeu->nombreDeJoueurs; joueurs++)
  707.             strncpy (jeu->joueurs [joueurs].nom, info.noms [joueurs], TAILLE_DU_NOM);
  708.          
  709.           /** Redimensionne la grille. */
  710.          
  711.           lancerJeu (menu, data);
  712.         }
  713.           else
  714.         perror ("recv()");
  715.         }
  716.       else
  717.         fprintf (stderr, "Échec de la connexion.\n");
  718.     }
  719.       else
  720.     fprintf (stderr, "L'hote %s est inconnu.\n", hostname);
  721.      
  722.       close (jeu->sock);
  723.     }
  724.   else
  725.     perror ("socket()");
  726.   #endif /* HAS_SOCKET */
  727.  
  728.   jeu->type = CLIENT;
  729. }
  730.  
  731. /** Remet à zéro le score de tous les joueurs. */
  732. void reinitialiserLesScores (const Menu *menu, void *data)
  733. {
  734.   Puissance4 *jeu = (Puissance4 *)data;
  735.   int pos;
  736.   for (pos=0; pos < NOMBRE_MAX_DE_JOUEURS; pos++)
  737.       jeu->joueurs [pos].score = 0;
  738.  
  739.   printf ("Les scores ont été remis à zéro.\n");
  740. }
  741.  
  742. /** Change le nombre de joueurs dans la partie. */
  743. void changerNombreDeJoueurs (const Menu *menu, void *data)
  744. {
  745.   Puissance4 *jeu = (Puissance4 *)data;
  746.   printf ("Entrez le nombre de joueurs [%i-%i]: ", NOMBRE_DEFAUT_DE_JOUEURS, NOMBRE_MAX_DE_JOUEURS);
  747.   unsigned int nouveauNombreDeJoueurs = get_int();
  748.  
  749.   if (nouveauNombreDeJoueurs >= NOMBRE_DEFAUT_DE_JOUEURS &&
  750.     nouveauNombreDeJoueurs <= NOMBRE_MAX_DE_JOUEURS)
  751.     jeu->nombreDeJoueurs = nouveauNombreDeJoueurs;
  752.   else
  753.     fprintf (stderr, "Ce nombre de joueurs ne convient pas.\n");
  754.  
  755.   menu_exec (menu);
  756. }
  757.  
  758. /** Demande de choisir un joueur afin de modifier
  759.   * ses paramétres. */
  760. unsigned int choisirUnJoueur (const Puissance4 *jeu)
  761. {
  762.   unsigned int n = 0;
  763.   int pos;
  764.   do
  765.     {
  766.       for(pos=0; pos < NOMBRE_MAX_DE_JOUEURS; pos++)
  767.       {
  768.     const char *statut = (pos < jeu->nombreDeJoueurs ) ? "Actif" : "Inactif";
  769.     const char *typeDeJoueur = (jeu->joueurs [pos].avecIA) ? "IA" : "Humain";
  770.     printf ("[%i]\t%-15s\t %-7s \t %-6s \n", pos+1,
  771.         jeu->joueurs[pos].nom, statut, typeDeJoueur);
  772.       }
  773.      
  774.       printf ("Choisissez le joueur que vous souhaitez modifier [1-%i]: ", pos);
  775.     } while ((n=get_int ()-1) >= NOMBRE_MAX_DE_JOUEURS);
  776.  
  777.   return n;
  778. }
  779.  
  780. /** Change le nom d'un des joueurs. La taille maximale
  781.   * du nom est de 255 caractères. */
  782. void changerNomDuJoueur (const Menu *menu, void *data)
  783. {
  784.   Puissance4 *jeu = (Puissance4 *)data;
  785.   unsigned int n = choisirUnJoueur (jeu);
  786.   printf ("Entrez le nouveau nom de %s: ", jeu->joueurs [n].nom);
  787.   char nouveauNom[TAILLE_DU_NOM];
  788.   get_string (nouveauNom, TAILLE_DU_NOM);
  789.  
  790.   /** Vérifier si le nom n'est pas trop court. */
  791.   if (strlen (nouveauNom) > 3)
  792.     strncpy (jeu->joueurs [n].nom, nouveauNom, TAILLE_DU_NOM);
  793.   else
  794.     fprintf (stderr, "Le nom du joueur est trop court.\n");
  795.  
  796.   menu_exec (menu);
  797. }
  798.  
  799. /** Activer ou désactiver l'IA sur un joueur. */
  800. void activerIADuJoueur (const Menu *menu, void *data)
  801. {
  802.   Puissance4 *jeu = (Puissance4 *)data;
  803.   unsigned int n = choisirUnJoueur (jeu);
  804.   printf ("Activer l'IA de %s [o/n]: ", jeu->joueurs[n].nom);
  805.   char reponse = get_char ();
  806.   jeu->joueurs[n].avecIA = (reponse == 'o') ? true : false;
  807.   menu_exec (menu);
  808. }
  809.  
  810. /** Demande un nouveau caractère pour symboliser le jeton
  811.   * d'un joueur. */
  812. void choisirJetonDuJoueur (const Menu *menu, void *data)
  813. {
  814.   Puissance4 *jeu = (Puissance4 *)data;
  815.   unsigned int n = choisirUnJoueur (jeu);
  816.   printf ("Choisissez un jeton pour %s: ", jeu->joueurs [n].nom);
  817.   char nouveauJeton = get_char();
  818.  
  819.   /** Vérifier si un autre joueur n'a pas déjà le même jeton. */
  820.   bool jetonValide = true;
  821.   int pos;
  822.   for(pos=0; pos < NOMBRE_MAX_DE_JOUEURS; pos++)
  823.     {
  824.       if (jeu->joueurs [pos].jeton == nouveauJeton)
  825.     {
  826.       jetonValide = false;
  827.       break;
  828.     }
  829.     }
  830.    
  831.   if (jetonValide)
  832.     jeu->joueurs [n].jeton = nouveauJeton;
  833.   else
  834.     fprintf (stderr, "Le jeton est déjà pris par un autre joueur.\n");
  835.  
  836.   menu_exec (menu);
  837. }
  838.  
  839. /** Redimensionne la grille avec
  840.   * des valeurs entrées par l'utilisateur. */
  841. void redimensionnerGrille (const Menu *menu, void *data)
  842. {
  843.   Puissance4 *jeu = (Puissance4 *)data;
  844.   printf ("Entrez la largeur de la grille [%i-%i]: ", GRILLE_MIN_TAILLE, GRILLE_MAX_TAILLE);
  845.   unsigned int largeur = get_int();
  846.   printf ("Entrez la hauteur de la grille [%i-%i]: ", GRILLE_MIN_TAILLE, GRILLE_MAX_TAILLE);
  847.   unsigned int hauteur = get_int();
  848.  
  849.   if (largeur > GRILLE_MIN_TAILLE && largeur < GRILLE_MAX_TAILLE &&
  850.     hauteur > GRILLE_MIN_TAILLE && hauteur < GRILLE_MAX_TAILLE)
  851.     {
  852.       jeu->grille = (int *)realloc(jeu->grille, sizeof (*jeu->grille)*largeur*hauteur);
  853.       jeu->remplissage = (short int *)realloc(jeu->remplissage, sizeof (*jeu->remplissage)*largeur);
  854.       jeu->largeur = largeur; jeu->hauteur = hauteur;
  855.     }
  856.   else
  857.     fprintf (stderr, "Taille incorrecte.\n");
  858.  
  859.   menu_exec (menu);
  860. }
  861.  
  862. /** Affiche l'aide de l'application. */
  863. void aProposDe (void)
  864. {
  865.   printf ("Ceci est un logiciel libre.\n");
  866. }
  867.  
  868. /** Termine le programme. */
  869. void fermerJeu (const Menu *menu, void * data)
  870. {
  871.   bool *fini = (bool *)data;
  872.   *fini = true;
  873. }
  874.  
  875. int main (void)
  876. {
  877.   Puissance4 jeu = nouveauPuissance4 ();
  878.   bool fini = false;
  879.  
  880.   #ifdef HAS_SOCKET
  881.     #ifdef WIN32
  882.       WSADATA wsa;
  883.       int err = WSAStartup (MAKEWORD(2, 2), &wsa);
  884.     #endif
  885.   #endif
  886.  
  887.   Menu *menuJeuReseau = menu_new ("Jouer en réseau");
  888.   menu_add_action (menuJeuReseau, "Héberger une partie", CALLBACK(lancerServeur), &jeu);
  889.   menu_add_action (menuJeuReseau, "Rejoindre une partie", CALLBACK(lancerClient), &jeu);
  890.  
  891.   Menu *menuJeu = menu_new ("Jouer une partie");
  892.   menu_add_action (menuJeu, "En local", CALLBACK(lancerPartieLocal), &jeu);
  893.   #ifdef HAS_SOCKET
  894.     menu_add_action (menuJeu, "En réseau", CALLBACK(menu_sub_exec), menuJeuReseau);
  895.   #endif
  896.  
  897.   Menu *menuConfigJoueur = menu_new ("Configuration des joueurs");
  898.   menu_add_action (menuConfigJoueur, "Nom d'un joueur", CALLBACK (changerNomDuJoueur), &jeu);
  899.   menu_add_action (menuConfigJoueur, "Activer l'IA d'un joueur", CALLBACK (activerIADuJoueur), &jeu);
  900.   menu_add_action (menuConfigJoueur, "Choisir le jeton d'un joueur", CALLBACK (choisirJetonDuJoueur), &jeu);
  901.  
  902.   Menu *menuConfig = menu_new ("Configuration");
  903.   menu_add_action (menuConfig, "Nombre de joueurs", CALLBACK (changerNombreDeJoueurs), &jeu);
  904.   menu_add_action (menuConfig, "Paramétrer les joueurs", CALLBACK (menu_sub_exec), menuConfigJoueur);
  905.   menu_add_action (menuConfig, "Taille de la grille", CALLBACK(redimensionnerGrille), &jeu);
  906.    
  907.   Menu *menuPrincipal = menu_new("Bienvenue sur Puissance 4 !");
  908.   menu_add_action (menuPrincipal, "Jouer", CALLBACK(menu_sub_exec), menuJeu);
  909.   menu_add_action (menuPrincipal, "Voir les scores", CALLBACK(afficherScore), &jeu);
  910.   menu_add_action (menuPrincipal, "Réinitialiser les scores", CALLBACK(reinitialiserLesScores), &jeu);
  911.   menu_add_action (menuPrincipal, "Configurer", CALLBACK(menu_sub_exec), menuConfig);
  912.   menu_add_action (menuPrincipal, "À propos de...", CALLBACK(aProposDe), NULL);
  913.   menu_add_action (menuPrincipal, "Quitter", CALLBACK(fermerJeu), &fini);
  914.  
  915.   menu_set_parent (menuJeu, menuPrincipal);
  916.   menu_set_parent (menuConfig, menuPrincipal);
  917.   menu_set_parent (menuConfigJoueur, menuConfig);
  918.   menu_set_parent (menuJeuReseau, menuJeu);
  919.  
  920.   do { menu_exec (menuPrincipal); } while (!fini);
  921.  
  922.   menu_destroy (menuJeuReseau);
  923.   menu_destroy (menuJeu);
  924.   menu_destroy (menuConfig);
  925.   menu_destroy (menuConfigJoueur);
  926.   menu_destroy (menuPrincipal);
  927.  
  928.   #ifdef HAS_SOCKET
  929.     #ifdef WIN32
  930.       WSACleanup();
  931.     #endif
  932.   #endif
  933.  
  934.   libererPuissance4(&jeu);
  935.   return EXIT_SUCCESS;
  936. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement