Construire un jeu de puzzle glissant avec JavaScript

JavaScriptJavaScriptBeginner
Pratiquer maintenant

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Bienvenue dans ce projet de construction d'un jeu de puzzle glissant simple en utilisant JavaScript. À la fin de ce guide, vous aurez un jeu de puzzle glissant 3x3 fonctionnel que vous pourrez jouer dans votre navigateur. Le jeu présentera des tuiles numérotées, un minuteur et des contrôles pour démarrer, mettre en pause et réinitialiser le jeu.

Aucune expérience antérieure n'est requise, mais une compréhension de base de JavaScript et d'HTML serait utile. Plongeons-y!

👀 Aperçu

Aperçu du jeu de puzzle glissant

🎯 Tâches

Dans ce projet, vous allez apprendre :

  • Comment concevoir la mise en page du jeu en HTML
  • Comment écrire les styles CSS pour le jeu
  • Comment initialiser les variables de jeu en JavaScript
  • Comment implémenter la fonction de déplacement pour gérer les mouvements des tuiles
  • Comment déterminer les mouvements possibles des tuiles
  • Comment implémenter le minuteur du jeu
  • Comment contrôler le flux du jeu avec les fonctions de démarrage, de pause et de réinitialisation
  • Comment mélanger aléatoirement les tuiles au début ou lors de la réinitialisation
  • Comment initialiser le jeu au chargement de la page

🏆 Réalisations

Après avoir terminé ce projet, vous serez capable de :

  • Concevoir la mise en page d'un jeu en utilisant HTML
  • Styliser des éléments à l'aide de CSS
  • Implémenter la logique du jeu en utilisant JavaScript
  • Gérer l'entrée utilisateur et effectuer des actions en fonction de celle-ci
  • Manipuler le DOM pour mettre à jour l'état du jeu et afficher des informations

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL javascript(("JavaScript")) -.-> javascript/DOMManipulationGroup(["DOM Manipulation"]) javascript(("JavaScript")) -.-> javascript/BasicConceptsGroup(["Basic Concepts"]) javascript/BasicConceptsGroup -.-> javascript/variables("Variables") javascript/BasicConceptsGroup -.-> javascript/data_types("Data Types") javascript/BasicConceptsGroup -.-> javascript/cond_stmts("Conditional Statements") javascript/BasicConceptsGroup -.-> javascript/loops("Loops") javascript/BasicConceptsGroup -.-> javascript/functions("Functions") javascript/BasicConceptsGroup -.-> javascript/array_methods("Array Methods") javascript/DOMManipulationGroup -.-> javascript/dom_select("DOM Selection") javascript/DOMManipulationGroup -.-> javascript/dom_manip("DOM Manipulation") javascript/DOMManipulationGroup -.-> javascript/event_handle("Event Handling") subgraph Lab Skills javascript/variables -.-> lab-445694{{"Construire un jeu de puzzle glissant avec JavaScript"}} javascript/data_types -.-> lab-445694{{"Construire un jeu de puzzle glissant avec JavaScript"}} javascript/cond_stmts -.-> lab-445694{{"Construire un jeu de puzzle glissant avec JavaScript"}} javascript/loops -.-> lab-445694{{"Construire un jeu de puzzle glissant avec JavaScript"}} javascript/functions -.-> lab-445694{{"Construire un jeu de puzzle glissant avec JavaScript"}} javascript/array_methods -.-> lab-445694{{"Construire un jeu de puzzle glissant avec JavaScript"}} javascript/dom_select -.-> lab-445694{{"Construire un jeu de puzzle glissant avec JavaScript"}} javascript/dom_manip -.-> lab-445694{{"Construire un jeu de puzzle glissant avec JavaScript"}} javascript/event_handle -.-> lab-445694{{"Construire un jeu de puzzle glissant avec JavaScript"}} end

Conception de la mise en page du jeu en HTML

Concevez la mise en page du jeu dans index.html comme indiqué dans la décomposition précédente.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Puzzle</title>
    <link rel="stylesheet" type="text/css" href="puzzle.css" />
    <script type="text/javascript" src="puzzle.js"></script>
  </head>
  <body>
    <div id="container">
      <!-- DIV le plus externe, utilisé pour contenir la structure interne -->
      <div id="game">
        <!-- Zone de jeu, qui est le grand bloc DIV -->
        <div id="d1" onclick="move(1)">1</div>
        <!-- Petits DIV, qui sont les 8 petits blocs. Lorsqu'ils sont cliqués, la fonction move() est exécutée. Le paramètre est le nombre affiché, donc on sait quel bloc a été cliqué -->
        <div id="d2" onclick="move(2)">2</div>
        <div id="d3" onclick="move(3)">3</div>
        <div id="d4" onclick="move(4)">4</div>
        <div id="d5" onclick="move(5)">5</div>
        <div id="d6" onclick="move(6)">6</div>
        <div id="d7" onclick="move(7)">7</div>
        <div id="d8" onclick="move(8)">8</div>
      </div>
      <div id="control">
        <!-- Zone de contrôle du jeu -->
        <p>
          <rowspan id="timeText">Temps total</rowspan>
          <!--  "Temps total" -->
          <rowspan id="timer"></rowspan>
        </p>
        <!-- Zone d'affichage du temps de jeu -->
        <p>
          <rowspan id="start" onclick="start()">Démarrer</rowspan>
          <!--  "Démarrer" -->
          <rowspan id="reset" onclick="reset()">Réessayer</rowspan>
          <!--  "Réessayer" -->
        </p>
        <!-- Zone d'affichage des boutons de contrôle -->
      </div>
    </div>
  </body>
</html>
✨ Vérifier la solution et pratiquer

Écriture des styles CSS

Une fois la structure de mise en page terminée, il est temps de beautifier notre jeu avec des styles CSS. Pendant cette phase, vous avez la liberté de personnaliser et de concevoir le jeu selon vos goûts, en ajoutant des touches et des détails uniques. Vous pouvez également introduire plus d'éléments décoratifs pour améliorer l'esthétique du jeu. Cependant, une remarque importante : si vous changez la taille du DIV principal du jeu, assurez-vous d'ajuster le code JavaScript associé. Nous en discuterons plus en détail bientôt.

Dans puzzle.css, ajoutez :

* {
  padding: 0;
  margin: 0;
  border: 0;
}
/* Le '*' est un joker, supprimant les styles par défaut pour tous les éléments car certains navigateurs peuvent ajouter des styles par défaut, ce qui pourrait créer des problèmes de mise en page. */

body {
  width: 100%;
  height: 100%;
}
/* Fixe la hauteur et la largeur du corps à 100 %, de sorte qu'il s'adapte automatiquement à la taille de l'écran du navigateur. */

#container {
  position: relative;
  width: 620px;
  height: 450px;
  margin: 0 auto;
  margin-top: 100px;
  border-radius: 1px;
}
/* C'est le DIV qui enveloppe tous les éléments. Fixé à une largeur de 620px et une hauteur de 450px. Cette taille peut être augmentée, mais pas diminuée. Elle doit être suffisamment grande pour contenir tous les éléments internes. */

#game {
  position: absolute;
  width: 450px;
  height: 450px;
  border-radius: 5px;
  display: inline-block;
  background-color: #ffe171;
  box-shadow: 0 0 10px #ffe171;
}
/* C'est le DIV de la zone de jeu. La taille est calculée en fonction de la taille des blocs plus petits. Ici, les blocs sont définis sur 150px de largeur et 150px de hauteur, donc la zone de jeu est de 150px * 3, soit 450px. */

#game div {
  position: absolute;
  width: 149px;
  height: 149px;
  box-shadow: 1px 1px 2px #777;
  background-color: #20a6fa;
  color: white;
  text-align: center;
  font-size: 150px;
  line-height: 150px;
  cursor: pointer;
  -webkit-transition: 0.3s; /* Préfixe pour la compatibilité Chrome */
  -moz-transition: 0.3s; /* Pour Firefox */
  -ms-transition: 0.3s; /* Pour IE */
  -o-transition: 0.3s; /* Pour Opera */
  transition: 0.3s;
}
/* Cela définit la taille des petits blocs. Positionnés en absolu, les changements de position n'affecteront pas les positions des autres éléments. La largeur et la hauteur sont toutes deux de 149px. Notamment, il y a une ombre de boîte, ajoutant à ses dimensions générales. La propriété 'transition:0.3s' rend les changements apparents sous forme d'animation, de sorte que lorsque la position du bloc change, une animation joue automatiquement. */

#game div:hover {
  color: #ffe171;
}
/* Définit l'animation au survol de la souris pour les blocs. Lorsque la souris survole un élément, ces propriétés remplacent les précédentes et elle revient à l'état initial lorsque la souris s'éloigne. Ici, nous changeons la couleur de la police. */

#control {
  width: 150px;
  height: 450px;
  display: inline-block;
  float: right;
}
/* Section de contrôle. 'display:inline-block' permet à l'élément de maintenir les propriétés de bloc tout en ne prenant pas toute une ligne, et 'float:right' le positionne sur le côté droit. */

#control rowspan {
  height: 25px;
  font-size: 20px;
  color: #222;
  margin-top: 10px;
}
/* Styles communs pour les boutons dans la zone de contrôle. */

#start {
  display: inline-block;
  font-size: 28px;
  width: 100px;
  height: 28px;
  background-color: #20a6fa;
  color: #ffe171;
  text-shadow: 1px 1px 2px #ffe171;
  border-radius: 5px;
  box-shadow: 2px 2px 5px #4c98f5;
  text-align: center;
  cursor: pointer;
}
/* Styles pour le bouton 'Démarrer'. 'cursor:pointer' fait que le curseur change en symbole de main lorsqu'on le survole. */

#reset {
  display: inline-block;
  font-size: 28px;
  width: 100px;
  height: 28px;
  background-color: #20a6fa;
  color: #ffe171;
  text-shadow: 1px 1px 2px #ffe171; /* Ombre de police */
  border-radius: 5px; /* Bords arrondis */
  box-shadow: 2px 2px 5px #4c98f5; /* Ombre de boîte */
  text-align: center; /* Texte centré */
  cursor: pointer;
}
/* Styles pour le bouton 'Réinitialiser'. */

#d1 {
  left: 0px;
}
#d2 {
  left: 150px;
}
#d3 {
  left: 300px;
}
#d4 {
  top: 150px;
}
#d5 {
  top: 150px;
  left: 150px;
}
#d6 {
  top: 150px;
  left: 300px;
}
#d7 {
  top: 300px;
}
#d8 {
  left: 150px;
  top: 300px;
}
/* Positions prédéfinies pour chacun des blocs dans l'ordre. */

Avoir les styles définis est une étape importante. Ensuite, nous passerons à la logique JavaScript pour animer notre jeu de puzzle. Il est recommandé de commencer par styler selon les instructions ci-dessus. Une fois la fonctionnalité du jeu bien comprise, vous êtes libre d'exhiber votre créativité et de personnaliser davantage les styles. Cependant, effectuer des changements non avisés au début pourrait entraîner des bogues imprévus.

✨ Vérifier la solution et pratiquer

Initialiser les variables de jeu en JavaScript

Avant d'ajouter la fonctionnalité du jeu, initialisez les variables d'état essentiellement du jeu.

Dans puzzle.js, ajoutez :

// puzzle.js

var time = 0;
// Enregistre le temps écoulé
var pause = true;
// Drapeau indiquant si le jeu est en pause, vrai signifie qu'il est en pause
var set_timer;
// Fonction du minuteur
var d = new Array(10);
// Stocke le numéro du petit DIV actuellement dans le grand DIV
var d_direct = new Array(
  [0],
  [2, 4], // Le grand DIV avec le numéro 1 peut aller aux positions 2 et 4
  [1, 3, 5],
  [2, 6],
  [1, 5, 7],
  [2, 4, 6, 8],
  [3, 5, 9],
  [4, 8],
  [5, 7, 9],
  [6, 8]
);
// Enregistre les positions de déplacement possibles pour les grands DIV
var d_posXY = new Array(
  [0],
  [0, 0], // Le premier nombre représente la gauche, le second représente le haut. Par exemple, la position du premier bloc est gauche:0px, haut:0px
  [150, 0],
  [300, 0],
  [0, 150],
  [150, 150],
  [300, 150],
  [0, 300],
  [150, 300],
  [300, 300]
);
// Position des grands DIV
d[1] = 1;
d[2] = 2;
d[3] = 3;
d[4] = 4;
d[5] = 5;
d[6] = 6;
d[7] = 7;
d[8] = 8;
d[9] = 0;
// Agrangement par défaut, le neuvième grand DIV est vide, donc c'est 0. Nous utilisons 0 pour représenter la tuile vide.
✨ Vérifier la solution et pratiquer

Implémenter la fonction de déplacement

Créez une fonction permettant aux tuiles de se déplacer en fonction de l'interaction de l'utilisateur.

Ajoutez à puzzle.js :

// puzzle.js

function move(id) {
  // Fonction de déplacement
  var i = 1;
  for (i = 1; i < 10; ++i) {
    if (d[i] == id) break;
  }
  // Cette boucle trouve la position du petit DIV dans le grand DIV
  var target_d = 0;
  // Enregistre les positions possibles pour le petit DIV, 0 signifie qu'il ne peut pas bouger
  target_d = whereCanTo(i);
  // Découvre où le petit DIV peut se déplacer. Si elle renvoie 0, cela signifie qu'il ne peut pas bouger, sinon, elle renvoie le numéro de la position cible
  if (target_d != 0) {
    d[i] = 0;
    // Définit le numéro du grand DIV actuel sur 0 car le petit DIV s'est déplacé, donc le grand DIV actuel est maintenant vide
    d[target_d] = id;
    // Définit le grand DIV cible au numéro du petit DIV cliqué
    document.getElementById("d" + id).style.left = d_posXY[target_d][0] + "px";
    document.getElementById("d" + id).style.top = d_posXY[target_d][1] + "px";
    // Enfin, définit la position du petit DIV cliqué sur la position du grand DIV cible
  }

  var finish_flag = true;
  // Drapeau indiquant si le jeu est terminé, vrai signifie qu'il est terminé
  for (var k = 1; k < 9; ++k) {
    if (d[k] != k) {
      finish_flag = false;
      break;
    }
  }
  // Itère à partir de 1, vérifie chaque numéro de grand DIV. Si ils ne sont pas dans l'ordre, le jeu n'est pas terminé.
  if (finish_flag == true) {
    if (!pause) start();
    alert("Félicitations!");
  }
  // Si vrai, le jeu est terminé. Si il n'est pas en pause, appelle la fonction de pause et affiche un message de réussite.
}
✨ Vérifier la solution et pratiquer

Déterminer les déplacements possibles des tuiles

Créez une fonction pour déterminer où une tuile peut se déplacer en fonction de sa position actuelle.

Ajoutez à puzzle.js :

// puzzle.js

function whereCanTo(cur_div) {
  // Fonction pour déterminer si un DIV donné peut se déplacer et vers quelle position
  var j = 0;
  var move_flag = false;
  for (j = 0; j < d_direct[cur_div].length; ++j) {
    if (d[d_direct[cur_div][j]] == 0) {
      move_flag = true;
      break;
    }
  }
  if (move_flag == true) {
    return d_direct[cur_div][j];
  } else {
    return 0;
  }
  // Si elle peut se déplacer, renvoie le numéro de la position cible, sinon renvoie 0
}
✨ Vérifier la solution et pratiquer

Implémenter le minuteur du jeu

Ajoutez une fonction de minuteur pour suivre le temps écoulé pendant le jeu.

Ajoutez à puzzle.js :

// puzzle.js

function timer() {
  // Fonction de minuteur, s'exécute toutes les secondes
  time += 1;
  var min = parseInt(time / 60); // Convertit les secondes en minutes
  var sec = time % 60; // Obtient les secondes restantes
  document.getElementById("timer").innerHTML =
    min + " minutes " + sec + " seconds";
}
✨ Vérifier la solution et pratiquer

Contrôler le déroulement du jeu

Implémentez des fonctions pour démarrer, mettre en pause ou réinitialiser le jeu en fonction de l'entrée de l'utilisateur.

Ajoutez à puzzle.js :

// puzzle.js

function start() {
  // Démarrer ou mettre en pause le jeu
  if (pause) {
    document.getElementById("start").innerHTML = "Pause";
    pause = false;
    set_timer = setInterval(timer, 1000);
  } else {
    document.getElementById("start").innerHTML = "Start";
    pause = true;
    clearInterval(set_timer);
  }
}
function reset() {
  // Réinitialiser le jeu
  time = 0;
  random_d();
  if (pause) start();
}
✨ Vérifier la solution et pratiquer

Mélanger aléatoirement les tuiles

Créez une fonction pour mélanger aléatoirement les tuiles au début ou lors d'une réinitialisation.

Ajoutez à puzzle.js :

// puzzle.js

function random_d() {
  // Mélanger aléatoirement les tuiles
  for (var i = 9; i > 1; --i) {
    var to = parseInt(Math.random() * (i - 1) + 1);
    if (d[i] != 0) {
      document.getElementById("d" + d[i]).style.left = d_posXY[to][0] + "px";
      document.getElementById("d" + d[i]).style.top = d_posXY[to][1] + "px";
    }
    if (d[to] != 0) {
      document.getElementById("d" + d[to]).style.left = d_posXY[i][0] + "px";
      document.getElementById("d" + d[to]).style.top = d_posXY[i][1] + "px";
    }
    var tem = d[to];
    d[to] = d[i];
    d[i] = tem;
  }
}
✨ Vérifier la solution et pratiquer

Initialiser le jeu lors du chargement de la page

Enfin, assurez-vous que lorsque la page web est chargée, les tuiles du jeu sont affichées et prêtes à être jouées.

Ajoutez à puzzle.js :

// puzzle.js

// Initialiser le jeu lors du chargement de la page
window.onload = function () {
  reset();
};
✨ Vérifier la solution et pratiquer

Exécution de l'application

  • Ouvrez index.html dans un navigateur web.
    open web

  • L'effet de la page est le suivant :
    puzzle game page preview

✨ Vérifier la solution et pratiquer

Sommaire

Vous avez maintenant réussi à construire un jeu de puzzle glissant en utilisant JavaScript de manière structurée et organisée! La présentation étape par étape devrait faciliter la compréhension des différents composants de la logique du jeu pour les apprenants. Rappelez-vous, il s'agit juste d'une version de base et il y a beaucoup de possibilités d'améliorations et d'ajout de fonctionnalités. Plongez-y et personnalisez-le. Bonne programmation!