1. Introduction

Au Moyen Âge, les chevaliers prouvaient leur honneur et leur bravoure en brandissant leurs épées et en abattant tous ceux qui les opposaient. De nos jours, les plus preuses âmes démontrent leur force dans un duel tout aussi intense, le puissance 4. Tour à tour, les combattants échangent des coups en déposant un pion de leur couleur dans une des sept colonnes de la grille. Le pion glisse jusqu'à la position la plus basse dans la colonne. Le but ultime de ce jeu est d'être le premier joueur à former une ligne de quatre pions de sa couleur respective dans la grille, qu'elle soit horizontale, verticale en en diagonale. Ce jeu d'intelligence et de réflexion demande un esprit vif capable de, si l'on reste dans l'analogie faite avant, parer les coups de l'adversaire et ne pas se faire parer.

Premièrement apparu en 1974, ce jeu de société bien-aimé peux également être vu comme un simple problème mathématique, constitué de combinatoire et de beaucoup de calculs informatiques. Simple n'est ici rien qu'une expression vulgaire; le problème sous forme mathématiques est extrêmement loin d'être facile. Mais, en 1988, James D. Allen, en trouve la solution exacte, c'est-à-dire la manière de jouer qui permettra au joueur qui commence de TOUJOURS gagner, qu'elle que soit les coups joués par son adversaire. Bien sûr, mémoriser cette solution est un travail long et ardu, mais pas impossible. Un ordinateur quant à lui, grâce à un algorithme adapté, est capable de faire ceci relativement facilement. Ceci crée une limite à ce jeu, de sorte à ce qu'il ne puisse pas être compétitif (un des deux joueurs gagnerait forcément). Or, pour nous amateurs de jeu de société facilement abordables, ce jeu est un passe-temps agréable (et intense!).

Intense, dès que l'on commence à jouer, bien sûr. En effet, préparer le plateau et trier les pions par couleur est de loin pas la chose la plus captivante au monde. Porter avec soi la boîte avec la grille et tous les pions, qui se perdent d'ailleurs facilement, est aussi embêtant. Voici donc où intervient mon projet. Pour maximiser l'émotion ressentie durant le jeu, et en prenant avantage de quelques choses très utiles que nous avons aujourd'hui (c'est-à-dire des ordinateurs, internet et des bases de stockage de données), il faut transférer tout le jeu en ligne, afin d'éviter pièces détachées et préparations ennuyeuses.

Les limitations de ce travail se trouvent principalement dans l'interaction avec la database. En effet, comme le site web sera programmé en PHP, pour mettre à jour sa version du jeu avec celle présente sur la base de données, il faut constamment actualiser la page. De plus,

Les enjeux principaux de ce projet printemps seraient de créer un site internet qui permettrait à un utilisateur de s'inscrire et de se connecter à son compte, qui figurerait sur une nouvelle page. Ici, il pourrait soit créer une partie, soit en rejoindre une, grâce à un nome de partie et un mot de passe. L'utilisateur serait ensuite redirigé sur une nouvelle page, sur laquelle il pourrait jouer son coup, puis attendre que son adversaire joue le sien, et ainsi de suite jusqu'à ce que l'un des deux joueurs crée une ligne de quatre pions de sa couleur respective. Lorsque ceci arrive, les deux utilisateurs seront redirigés sur une dernière page qui propose au créateur de la partie de relancer une nouvelle partie ou de quitter le jeu, retournant ainsi à la page principale, celle qui figure le compte.

L'objectif final est donc de créer un site internet permettant à deux joueurs

2. Matériel et Méthode

2.1 Matériel

  • Ordinateur ayant accès à internet
  • Accès à une base de données MySQL
  • Logiciel de permettant de coder en PHP, HTML, CSS et JavaScript

2.2 Méthode

Pour pouvoir créer un site internet dynamique, il faut la coder en PHP, et il faut donc une structure en HTML/CSS. La base de donnée contenant les utilisateurs et les parties sera gérée par MySQL. Le plan du site web est montré sur la Figure 1, avec l’accueil d'un utilisateur qui n'a pas le cookie du site dans son cache sur la page de connexion, qui permet aussi de se rediriger vers la page de création du compte (si l'utilisateur n'a pas encore de compte).

Dessin sans titre.jpg, mai 2021
Figure 1 - Structure du site internet


2.2.1 Préparation de la table MySQL

Pour pouvoir avoir un aspect multijoueur sur un site internet, il nous faut une base de données accessible à tout moment, qui peut être modifiée au suivi de la partie, afin de faire le lien d'informations entre les deux joueurs. Cette base de données peut être en ligne sur un serveur ou sur en Localhost, c'est-à-dire sur l'ordinateur en question. Après s'être connecté, il faut créer deux tables (appuyer sur bouton "New table"), une nommée users et l'autre games. La table users sera constituée de 5 colonnes : id, user_id, user_name, user_password et date, comme sur la Figure 2.

Capture.PNG, mai 2021
Figure 2 - Table users dans phpmyadmin


La table games aura 57 colonnes : id, game_id, game_name, game_password, game_user1, game_user2, player_turn, les 42 cases de la grille de jeu, que l'on nommera 'i_j' avec i la ligne et j la colonne (cela nous donnera les valeurs selon les indices d'une matrice), la hauteur de la colonne, nommée 'coli' avec 0<i<8, et la date. Les sept valeurs de la hauteur de la colonne sont nécessaire car il faut stocker si un pion a déjà été mis dans cette colonne avant (afin de ne pas avoir des pions qui flottent avec rien en dessous). Cette table est représentée sur les Figures 3 et 4.

php1.PNG, mai 2021
Figure 3 - Table games partie 1
php2.PNG, mai 2021
Figure 4 - Table games partie 2


Lors de la création des tables, il faut spécifier certains paramètres supplémentaire.

  1. La colonne 'id' sera de type 'INT' (pour integer, un nombre entier) et comme taille 10 (codés sur 10 bits), aura l'attribut d'être 'UNSIGNED' (pas de valeurs négatives), aura comme index 'PRIMARY' et il faut cocher le carré sous A_I (auto_increment, qui fera augmenter de 1 cette valeur à chaque nouvelle entrée dans la table).
  2. Les colonnes 'user_id' et 'game_id' seront de type 'BIGINT' et une taille de 20, et auront également l'attribut 'UNSIGNED'.
  3. Les colonnes 'user_name', 'user_password', 'game_name' et 'game_password' seront de type 'VARCHAR' (text court) et de taille 30 (30 carctères maximum)
  4. Les colonnes 'game_user1', 'game_user2' et 'player_turn' seront du type 'BIGINT' et de taille 20, et auront l'attribut 'UNSIGNED'.
  5. Les colonnes 'i_j' avec 0 < i < 7 et 0 < j< 8 seront du type 'INT' et de taille 2, et auront l'attribut 'UNSIGNED' (ces variables ne prendront que 0, 1 ou 2 comme valeur).
  6. Les colonnes 'coli' avec 0< i < 8 seront du type 'INT' et de taille 3, et auront l'attribut 'UNSIGNED' (ces variables ne prendront que des valeurs entre 0 et 7).
  7. Les colonnes 'date' auront 'TIMESTAMP' comme type et auront une valeur par défaut de 'CURRENT_TIMESTAMP' et l'attribut 'on update CURRENT_TIMESTAMP' (ces colonnes se rempliront toutes seules et donneront l'heure exacte de la création de l'entrée).

2.2.2 Points important du code

2.2.2.1 $_SESSION

Cette variable est accessible seulement lorsque la fonction session_start() est appelée au début du code. Cette fonction crée un cookie stocké dans le cache du navigateur web de l'utilisateur avec la liste de variables $_SESSION' '. Cette variable est appelée super global variable, c'est-à-dire qu'elle est accessible dans n'importe quelle page de code où la fonction session_start() est appelée, sans que les différentes page de code ait soit incluses les unes dans les autres avec la fonction include("Nom_du_fichier.php"). Cette variable est donc extrêmement utile pour sauvegarder des valeur comme le nom de l'utilisateur, son numéro d'identification dans la base MySQL, etc.

2.2.2.2 Rafraichissement régulier de la page

Afin d'éviter le problème devoir continuellement recharger la page pour voir si son adversaire a joué, il est plus pertinent de la faire se rafraichir toute seule à intervalle régulier, bien que cela demandera plus de ressources. Il y a deux manières de faire ceci, l'une consiste à faire un petit script en JavaScript et l'autre (bien plus facile à mon avis) consiste à écrire le code suivant dans le header :

 <html>
           <head>
                      <meta http-equiv="refresh" content="5" />
           </head>
           <body>
 ...

qui fait donc se rafraichir la page toutes les 5 secondes.

2.2.2.3 Regarder si un joueur a gagné

La partie la plus compliquée de ce projet est sans doute de détecter la fin de la partie. En effet, la vérification de si l'un des deux joueurs a formé une ligne de 4 pièces de sa couleur ou non est plus compliquée que l'on pourrait le croire. Une des solutions possibles à ce problème est de créer un algorithme brute force qui vérifie toutes les possibilités de lignes de pièces, à chaque fois que la page est rechargée. Or, cette solution demande une quantité énorme de calcul, et abouti une grande majorité du temps au message d'erreur suivant :

 Fatal error: Maximum execution time of 60 seconds exceeded

Cette erreur est due au fait que le script PHP s'exécutait depuis une minute sans résultat et, ayant atteint la limite de temps disponible, il fut donc terminé. Il est possible de rallonger cette limite de temps, et même de l'enlever complètement, en changeant certaines valeurs sur son serveur ou sur son ordinateur, mais cela ne ferai que enlever le message d'erreur, sans raccourcir la durée d'attente pour le calcul.

Une autre solution, que j'ai commencé à implémenter dans mon code, sans réussite, faute de temps, est de garder en mémoire le dernière pièce jouée, et de regarder autour de cette pièce toutes les pièces de la même couleur ainsi que les directions dans lesquelles une ligne de quatre pièces pourrait aller (si la dernière pièce jouée se trouve dans le coin inférieur gauche de la grille, les lignes possibles sont vers la droite et en diagonale vers le haut et la droite par exemple). Si il y a une pièce de même couleur dans l'entourage, il faut aller regarder la pièce d'encore après dans la même direction, et si celle-ci est également de la même couleur, il faut aller regarder la quatrième pièce dans la direction, suite à quoi on saura si le dernier coup joué est gagnant ou non. Cette solution est plus économe en terme de calculs informatique, mais plus longue à écrire et déboguer.

3. Résultats

3.1 Illustration de l'utilisation

Figure 5 - Vidéo illustrant l'utilisation du site

3.2 Comptes, inscription et connexion

Cette partie du projet est globalement réussie, permettant à un utilisateur de créer son compte avec son mot de passe et d'ensuite se connecter à ce même compte. Il a également la possibilité de se déconnecter de se compte pour se connecter à un autre, par exemple. Cette partie est grandement inspirée et basée sur une vidéo expliquant comment créer un système de comptes en PHP et MySQL. Cette partie du projet est nécessaire pour obtenir un aspect multijoueur, mais n'est pas centrale.

3.3 Jeu et parties

Le jeu et la création/connexion à une partie est également réussie, sauf pour la détection et la reconnaissance de la fin du jeu, qui requiert l'analyse d'une matrice longue et difficile à coder. Cette partie comporte une annonce des deux adversaire, indique à chaque joueur s'il s'agit de son tour de jeu ou non et désactive ou active les sept boutons en fonction de ceci. Ceci l'empêche ainsi de jouer lorsque ce n'est pas son tour.

3.4 Fin du jeu et possibilité de rejouer

Le code permettant de détecter si l'un des deux joueurs a gagné n'est pas fonctionnel, faute de temps. Ainsi, comme le jeu ne peux techniquement jamais se finir, j'ai jugé plus important la documentation de ce projet que la dernière page, qui ne verrait ainsi pas le jour. Je pense que le problème de vérification de la fin de la partie est la partie la plus compliquée de ce projet. En effet, il faut faire de nombreuses requêtes SQL, qui peuvent à tout moment ne pas fonctionner sans donner de message d'erreur, ce qui rend le débogage difficile. Cette partie était cependant la plus intéressante d'un point de vue de l'apprentissage, et j'aurais voulu avoir le temps de plus m'y plonger.

4. Discussion

4.1 Problèmes rencontrés

4.1.1 Post/Redirect/Get

En PHP, lorsqu'un utilisateur appuie sur un bouton (input de type submit), le bouton reste activé jusuq'à une redirection vers une autre page. Il est également impossible de le désactiver le bouton grâce à une fonction comme

 unset()

par exemple. Pour détecter si le bouton est activé, il faut utiliser la fonction

 isset()

et dans une boucle

 if(isset($_POST('bouton')))

qui contient une requête MySQL comme

 mysqli_query($con, $query)

il se peut que le code dans la boucle soit exécuté plusieurs fois à la suite. Ceci est problématique car ces multiples envoi engendrent des bugs comme permettre à un joueur de jouer plusieurs fois du suite.

Pour régler ce problème, qui est un problème récurrent dans les requêtes HTTP POST vers un serveur, il faut utiliser la méthode du Post/Redirect/Get (article en annexe) est de pas directement recharger la page, mais de rediriger vers une autre page. Après une requête POST, au lieu de simplement recharger la page, on utilise le code

 Header("Location: Game_page.php");

Ce bout de code nous redirige vers notre page de jeu, mais réinitialise les requêtes POST, de sorte à ne pas en envoyer plusieurs.

4.1.2 Méthode brute force

Un autre problème rencontré au long de ce projet était lors de la vérification de la fin de la partie, après une analyse de la matrice dans la base de données. La première tentative à créer un algorithme qui testait si l'un des deux joueurs avait fait une ligne de 4 pions était en suivant une méthode de brute force. C'est-à-dire que l'algorithme teste TOUTES les possibilités de chaîne de quatre pions de la même couleur possible, et peut donc arrêter le jeu et annoncer le vainqueur. Or, cette méthode requiert une grande quantité de calculs informatiques, et abouti très souvent au message d'erreur

 Fatal error: Maximum execution time of 60 seconds exceeded

Le script prend plus d'une minute à charger la page! Pas le jeu de société le plus captivant, s'il faut attendre plus de deux minutes entre chaque fois que l'on joue...

La solution que j'ai imaginé, mais dont le code ne fonctionne pas, est de regarder la position de la dernière pièce jouée, et de regarder dans toutes les directions si ce coup a créé une ligne de quatre pions de la même couleur. Cette solution nous semble très simple en tant que humains, qui voyons cette méthode avec du recul et qui nous disons : "Oui, alors ici, il n'y a pas une ligne de quatre pions, mais ici oui, et donc le joueur 1 a gagné". Pour créer un code qui fait la même chose pour l'ordinateur, il faut se rappeler que les requêtes SQL en PHP ne font pas de message d'erreur si la syntaxe est fausse. Comme il faut répéter le code dans les sept directions DEUX fois (une pour le premier joueur, une autre pour le deuxième), le code devient long et difficile syntaxiquement.

4.2 Limitations du projet

Ce projet est en général une réussite, le jeu est jouable et résous le problème des pièces détachées encombrantes. Or, le projet a certaines limitations et pourrait, comme tout projet, être grandement amélioré. Voici donc certaines des améliorations possibles.

4.2.1 Multijoueur restreint

Le site internet dépend du fait que les deux joueurs aient un lien hors du site, qui leur permet de communiquer des informations comme le nom et le mot de passe de la partie créé par l'un des deux. Ainsi, un joueur seul, ne peut pas jouer contre une personne aléatoire, car il n'a aucune manière de connaître le nom et le mot de passe de la partie d'une personne aléatoire.

Une solution à ce problème serait de rajouter un bouton 'Multiplayer game against random player' qui regarderait sur la base de données si une partie aléatoire est en route et est disponible et où il n'y a pour le moment qu'un seul joueur. Si une telle partie existe, le code connecterait l'utilisateur à ce jeu, et si il n'en existe pas une, ou qu'elle sont toutes remplies de deux joueurs, alors le code créerait une nouvelle entrée dans la base de donnée, et attendrait pour un deuxième utilisateur.

4.3 Apprentissage

Malgré la fin décevante de ce projet, il faut tout de même mettre en valeur le parcours et les nombreuses choses apprises au long du travail. Ce projet printemps m'a permis d'apprendre à coder en PHP, en HTML et en CSS ainsi que d'utiliser et de gérer une base de données MySQL. Il faut également noter que les bases de données sont entièrement gérée par le code PHP.

Comme au projet précédent, ce travail m'a fait réaliser l'étendue du travail qui m'est demandé, en particulier dû à la recherche d'informations en ligne, ainsi que de la résolution de bugs. Par rapport au dernier projet, un aspect s'est nettement amélioré, le débogage. En effet, dans ce projet, j'ai pu très rapidement identifier le problème et le résoudre adéquatement. La méthode utilisée est de visualiser beaucoup de variable, en les écrivant sur la page grâce à

 print($variable);

De cette manière, on peut rapidement voir si une variable est vide ou si elle contient une valeur, et si elle a l'effet que l'on veut ou non. Un exemple de ceci est lors du problème de multiple envoi d'une requête POST. Après avoir explicitement écrit la position de la dernière pièce jouée, et avoir attentivement scruté les changements dans la base de données, j'ai remarqué que le code semblait s'exécuter plusieurs fois. Sur internet, j'ai pu trouver de nombreux article expliquant ce problème et ses résolution.

Ce projet m'a également permis de mieux visualiser le fonctionnement du protocole HTTP, grâce justement à des problèmes comme le Post/Redirect/Get.

5. Conclusion

Les objectifs de ce projet, c'est-à-dire créer un site internet permettant à un utilisateur de jouer au Puissance 4 contre un autre utilisateur, sont réussis. En effet, les utilisateurs peuvent se connecter à leur compte respectif et soit créent, soit rejoignent une partie gérée par une base de données MySQL. Ce site dépend cependant de la bonne volonté des utilisateurs. Ils peuvent d'une part ne pas s'arrêter lorsqu'un des deux a gagné, et peuvent saboter le site le jeu en jouant dans une colonnes déjà remplie.

Malgré l'absence de fin de partie, je considère ce travail comme une réussite, car il m'a non seulement permis de gagner de nombreuses connaissances en PHP, HTML et CSS ainsi qu'en gestion de bases de données MySQL, et car il fonctionne bon sang! On peut jouer au Puissance 4 sans être encombré avec des tas de pièces détachées et une longue installation.

Références

  1. https://www.php.net/manual/fr/index.php --- Documentation PHP
  2. https://www.php.net/manual/fr/book.mysql.php --- Documentation PHP des fonction mysql
  3. https://www.php.net/manual/fr/book.mysqli.php --- Documentation PHP des fonction mysqli
  4. https://www.youtube.com/watch?v=WYufSGgaCZ8 --- Vidéo de création de système de comptes en PHP/MySQL
  5. https://fr.wikipedia.org/wiki/Post-redirect-get --- Post/Redirect/Get
  6. https://html.com/ --- Documentation HTML
  7. https://devdocs.io/css/ --- Documentation CSS