CodeGym /Blog Java /Random-FR /Rubrique jeux sur CodeGym : Théorie utile
John Squirrels
Niveau 41
San Francisco

Rubrique jeux sur CodeGym : Théorie utile

Publié dans le groupe Random-FR
Dans la section "Jeux" de CodeGym, vous trouverez des projets passionnants qui impliquent l'écriture de jeux informatiques populaires. Vous voulez créer votre propre version des jeux populaires 2048, Minesweeper, Snake et d'autres jeux ? C'est simple. Nous avons transformé l'écriture de jeu en un processus étape par étape. Rubrique "Jeux" sur CodeGym : Théorie utile - 1Pour tester vos capacités en tant que développeur de jeux, vous n'avez pas besoin d'être un programmeur avancé, mais un ensemble spécifique de connaissances Java est nécessaire. Vous trouverez ici des informations qui seront utiles à l'écriture de jeux .

1. Héritage

Travailler avec le moteur de jeu CodeGym implique d'utiliser l'héritage. Mais que faire si vous ne savez pas ce que c'est ? D'une part, vous devez comprendre ce sujet : il est étudié au niveau 11. D'autre part, le moteur a été spécialement conçu pour être très simple, vous pouvez donc vous en sortir avec une connaissance superficielle de l'héritage. Qu'est-ce donc que l'héritage ? En termes très simples, l'héritage est une relation entre deux classes. L'un d'eux devient le parent et l'autre devient un enfant (descendant). De plus, la classe parent peut même ne pas savoir qu'elle a des descendants. En d'autres termes, il ne tire aucun avantage particulier d'avoir des descendants. Mais l'héritage donne à un descendant de nombreux avantages. Et le plus important est que toutes les variables et méthodes de la classe parent apparaissent dans le descendant comme si le code de la classe parent était copié dans la classe descendante. Ce n'est pas une description tout à fait exacte, mais elle suffira pour une compréhension simplifiée de l'héritage. Exemple 1 : L'héritage le plus simple.

public class Parent {

}
La classe Child hérite de la classe Parent à l'aide du mot clé extend .

public class Child extends Parent {

}
Exemple 2 : Utilisation des variables de la classe parent.

public class Parent {

   public int age;
   public String name;
}
La classe Child peut utiliser les variables age et name de la classe Parent comme si elles étaient déclarées dans la classe Parent .

public class Child extends Parent {

   public void printInfo() {

     System.out.println(name+" "+age);
   }
}
Exemple 3 : Utilisation des méthodes de la classe parent.

public class Parent {

   public int age;
   public String name;

   public getName() {
      return name;
  }
}
La classe Child peut utiliser les variables et les méthodes de la classe Parent comme si elles étaient déclarées dans la classe Child. Dans cet exemple, nous utilisons la méthode getName() .

public class Child extends Parent {

   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}
Voici à quoi ressemble la classe Child pour le compilateur :

public class Child extends Parent{

   public int age;  // Inherited variable
   public String name;  // Inherited variable

   public getName() {  // Inherited method.
      return name;
  }
   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}

2. Remplacer les méthodes

Parfois, il y a des situations où nous faisons hériter notre classe Child d'une classe Parent très utile, avec toutes ses variables et méthodes, mais certaines méthodes ne fonctionnent pas tout à fait comme nous le souhaitons. Ou pas du tout comme nous le voulons. Que pouvons-nous faire dans cette situation ? Nous pouvons remplacer la méthode que nous n'aimons pas. C'est très simple à faire : dans notre classe Child, nous déclarons simplement une méthode avec la même signature que la méthode de la classe Parent, puis nous y écrivons notre propre code. Exemple 1 : redéfinition d'une méthode.

public class Parent {

   public String name;

   public void setName(String nameNew) {
       name = nameNew;
  }

   public getName() {
      return name;
  }
}
La méthode printInfo() affichera "Luke, No!!!"

public class Child extends Parent{

   public void setName(String nameNew) {
       name = nameNew + ", No!!!";
  }

   public void printInfo() {
      setName("Luke");
      System.out.println(getName());
   }
}
Voici à quoi ressemble la classe Child pour le compilateur :

public Child extends Parent {

   public String name;  // Inherited variable

   public void setName(String nameNew)  // Overridden method instead of the inherited method {

       name = nameNew + ", No!!!";
   }
   public getName() {  // Inherited method.

      return name;
   }
   public void printInfo() {

     setName("Luke");
     System.out.println( getName());
   }
}
Exemple 2 : Un peu de magie d'héritage (et de remplacement de méthode).

public class Parent {

   public getName() {
      return "Luke";
  }
   public void printInfo() {

     System.out.println(getName());
   }
}

public class Child extends Parent {

   public getName() {
      return "Luke, I am your father";
  }
}
Dans cet exemple, si la printInfométhode (de la classe Parent) n'est pas redéfinie dans la classe Child, lorsque cette méthode est appelée sur un objet Child, sa getName()méthode sera appelée à la place de la getName()méthode de la classe Parent.

Parent parent = new Parent ();
parent.printnInfo();
Ce code affiche "Luke" sur l'écran.

Child child = new Child ();
child.printnInfo();
Ce code affiche "Luke, je suis ton père" à l'écran.
Voici à quoi ressemble la classe Child pour le compilateur :

public class Child extends Parent {

   public getName() {
      return "Luke, I am your father";
   }
   public void printInfo() {

     System.out.println(getName());
   }
}

3. Listes

Si vous n'avez pas encore rencontré de listes (Liste), voici un bref aperçu. Vous pouvez trouver des informations complètes dans les niveaux 6-7 du cours CodeGym . Les listes ont beaucoup en commun avec les tableaux :
  • vous pouvez stocker beaucoup de données d'un type spécifique ;
  • ils vous permettent d'obtenir des éléments par leur index ;
  • les indices d'éléments commencent à 0.
Avantages des listes : contrairement aux tableaux, les listes peuvent changer de taille de manière dynamique. Lorsqu'une liste est créée, sa taille est 0. Au fur et à mesure que vous ajoutez des éléments à une liste, sa taille augmente. Voici un exemple de création de liste :

ArrayList<String> myList = new ArrayList<String>(); // Create a new ArrayList
La valeur entre crochets indique le type de données que la liste peut stocker. Voici quelques méthodes pour travailler avec la liste :
Code Brève description de ce que fait le code
ArrayList<String> list = new ArrayList<String>(); Créer une nouvelle liste de chaînes
list.add("name"); Ajouter un élément à la fin de la liste
list.add(0, "name"); Ajouter un élément au début de la liste
String name = list.get(5); Obtenir un élément par son index
list.set(5, "new name"); Changer un élément par son index
int count = list.size(); Obtenir le nombre d'éléments dans la liste
list.remove(4); Supprimer un élément de la liste
Pour en savoir plus sur les listes, consultez les articles suivants :
  1. Classe ArrayListArrayList class
  2. ArrayList en images
  3. Supprimer un élément d'une ArrayList

4. Tableaux

Qu'est-ce qu'une matrice ? Une matrice n'est rien de plus qu'un tableau rectangulaire qui peut être rempli de données. En d'autres termes, c'est un tableau à deux dimensions. Comme vous le savez probablement, les tableaux en Java sont des objets. Un tableau unidimensionnel standard intressemble à ceci :

int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
Nous pouvons le visualiser ainsi :
0 1 2 3 4 5 6 7
12 32 43 54 15 36 67 28
La ligne du haut indique les adresses des cellules. En d'autres termes, pour obtenir le nombre 67, vous devez accéder à l'élément de tableau d'index 6 :

int number = array[6];
Tout est très simple. Un tableau à deux dimensions est un tableau de tableaux à une dimension. Si vous en entendez parler pour la première fois, arrêtez-vous et imaginez-le dans votre tête. Un tableau à deux dimensions ressemble à ceci :
0 Tableau unidimensionnel Tableau unidimensionnel
1 Tableau unidimensionnel
2 Tableau unidimensionnel
3 Tableau unidimensionnel
4 Tableau unidimensionnel
5 Tableau unidimensionnel
6 Tableau unidimensionnel
7 Tableau unidimensionnel
Dans du code:

int [][] matrix = {
{65, 99, 87, 90, 156, 75, 98, 78}, {76, 15, 76, 91, 66, 90, 15, 77}, {65, 96, 17, 25, 36, 75, 54, 78}, {59, 45, 68, 14, 57, 1, 9, 63}, {81, 74, 47, 52, 42, 785, 56, 96}, {66, 74, 58, 16, 98, 140, 55, 77}, {120, 99, 13, 90, 78, 98, 14, 78}, {20, 18, 74, 91, 96, 104, 105, 77} }
0 0 1 2 3 4 5 6 7
65 99 87 90 156 75 98 78
1 0 1 2 3 4 5 6 7
76 15 76 91 66 90 15 77
2 0 1 2 3 4 5 6 7
65 96 17 25 36 75 54 78
3 0 1 2 3 4 5 6 7
59 45 68 14 57 1 9 63
4 0 1 2 3 4 5 6 7
81 74 47 52 42 785 56 96
5 0 1 2 3 4 5 6 7
66 74 58 16 98 140 55 77
6 0 1 2 3 4 5 6 7
120 99 13 90 78 98 14 78
7 0 1 2 3 4 5 6 7
20 18 74 91 96 104 105 77
Pour obtenir la valeur 47, vous devez vous référer à l'élément de matrice en [4][2].

int number = matrix[4][2];
Vous avez peut-être remarqué que les coordonnées de la matrice sont différentes du système de coordonnées rectangulaire classique (système de coordonnées cartésien). Lorsque vous accédez à la matrice, vous spécifiez d'abord la coordonnée y, puis la coordonnée x. En mathématiques, il est d'usage de spécifier d'abord la coordonnée x, c'est-à-dire (x, y). Vous vous demandez peut-être : "Eh bien, pourquoi ne pas faire pivoter votre représentation de la matrice, puis accéder aux éléments de la manière habituelle en utilisant (x, y) ? Cela ne changerait pas le contenu de la matrice". Oui, rien ne changerait. Mais dans le monde de la programmation, la pratique acceptée est d'accéder aux matrices "d'abord par y, puis par x". Vous devez accepter cela comme la bonne manière. Parlons maintenant de la projection de la matrice sur notre moteur (Gameclasse). Comme vous le savez, le moteur dispose de nombreuses méthodes qui modifient les cellules du terrain de jeu à des coordonnées spécifiques. Par exemple, la setCellValue(int x, int y, String value)méthode. Il définit une cellule spécifique avec des coordonnées (x, y) égales au paramètre de valeur. Vous avez peut-être remarqué que cette méthode prend x en premier, tout comme dans le système de coordonnées classique. Les autres méthodes du moteur fonctionnent de manière similaire. Lors du développement de jeux, il sera souvent nécessaire de reproduire l'état d'une matrice à l'écran. Comment fait-on cela? Tout d'abord, vous devez parcourir tous les éléments de la matrice dans une boucle. Deuxièmement, appelez la méthode d'affichage pour chacun d'eux, en utilisant les coordonnées REVERSED. Par exemple:

private void drawScene() {
    for (int i = 0; i < matrix.length; i++) {
        for (int j = 0; j < matrix[i].length; j++) {
            setCellValue(j, i, String.valueOf(matrix[i][j]));
        }
    }
}
Naturellement, l'inversion fonctionne dans les deux sens. Vous pouvez passer (i, j) à la setCellValueméthode et prendre simultanément l'élément [j][i] de la matrice. Inverser les coordonnées peut sembler un peu difficile, mais vous devez vous en souvenir. Et toujours, si vous rencontrez des problèmes, vous devez saisir un morceau de papier et un stylo, dessiner la matrice et reproduire les processus impliquant la matrice.

5. Numéros aléatoires

Comment travaillez-vous avec un générateur de nombres aléatoires ? La Gameclasse définit la getRandomNumber(int)méthode. Sous le capot, il utilise la Randomclasse du package java.util, mais la façon dont vous travaillez avec le générateur de nombres aléatoires ne change pas. getRandomNumber(int)prend un entier comme argument. Ce nombre sera la limite supérieure de ce que le générateur peut retourner. La limite inférieure est 0. Important! Le générateur ne renverra JAMAIS le nombre limite supérieur. Par exemple, si vous appelez getRandomNumber(3), il renverra au hasard 0, 1 ou 2. Comme vous pouvez le voir, il ne peut pas renvoyer 3. Utiliser le générateur de cette manière est assez simple, mais très efficace dans de nombreux cas. Supposons que vous ayez besoin d'obtenir un nombre aléatoire dans une plage : Imaginez que vous ayez besoin d'un nombre à trois chiffres dans la plage [100..999]. Comme vous le savez déjà, le nombre minimum renvoyé est 0. Vous devrez donc ajouter 100. Mais dans ce cas, vous devez faire attention à ne pas dépasser la limite supérieure. Pour obtenir 999 comme valeur aléatoire maximale, appelez legetRandomNumber(int)méthode avec l'argument 1000. Mais maintenant, nous nous souvenons que nous ajoutons 100 au résultat : cela signifie que la limite supérieure doit être réduite de 100. En d'autres termes, le code pour obtenir notre nombre aléatoire à trois chiffres ressemblera à ceci :

int number = 100 + getRandomNumber(900);
Mais pour simplifier cette procédure, le moteur fournit la getRandomNumber(int, int)méthode dont le premier paramètre est le nombre minimum à retourner. En utilisant cette méthode, l'exemple précédent peut être réécrit comme suit :

int number = getRandomNumber(100, 1000);
Des nombres aléatoires peuvent être utilisés pour obtenir un élément de tableau aléatoire :

String [] names = {"Sarah", "Val", "Sergey"};
String randomName = names[getRandomNumber(names.length)]
Générer certains événements avec une certaine probabilité. Pour les humains, les matins commencent par quelques scénarios possibles : Sommeil trop long – 50 % de chance ; Je me suis réveillé à l'heure – 40 % de chance ; Réveil une heure plus tôt – 10% de chance. Imaginez que vous écrivez un générateur de résultats du matin. Vous devez générer des événements avec une certaine probabilité. Pour ce faire, vous devez à nouveau utiliser un générateur de nombres aléatoires. Différentes implémentations sont possibles, mais la plus simple devrait être basée sur l'algorithme suivant :
  1. définir les limites utilisées pour générer un nombre ;
  2. générer un nombre aléatoire ;
  3. traiter le nombre obtenu.
Dans ce cas, le maximum sera de 10. Appelez legetRandomNumber(10)méthode et analyser que nous pouvons revenir. Il peut renvoyer 10 nombres (de 0 à 9), chacun avec la même probabilité — 10 %. Nous devons maintenant combiner tous les résultats possibles et les mapper à nos événements possibles. Votre imagination peut imaginer de nombreuses combinaisons possibles, mais voici la plus évidente : "Si le nombre aléatoire est dans la plage [0..4], nous avons l'événement "Overslept" ; si le nombre est dans la plage [5 ..8], nous avons l'événement "Réveil à l'heure" ; et si le nombre est 9, alors nous avons l'événement "Réveil une heure plus tôt". Tout est très simple. Il y a 5 chiffres dans la plage [0 ..4], dont chacun peut être renvoyé avec une probabilité de 10 %, pour un total de 50 % ; il y a 4 nombres dans la plage [5..8], eh bien, et 9 n'est qu'un seul nombre qui apparaît avec une probabilité de 10 %.

int randomNumber = getRandomNumber(10);
if (randomNumber < 5) {
    System.out.println("Overslept");
} else if (randomNumber < 9) {
    System.out.println("Woke up on time");
} else {
    System.out.println("Woke up an hour early");
}
En général, il existe des tonnes de façons d'utiliser des nombres aléatoires. Vous n'êtes limité que par votre imagination. Mais ils sont plus efficacement utilisés si vous avez besoin d'obtenir à plusieurs reprises un résultat. Le nouveau résultat sera alors différent du précédent. Avec une certaine probabilité, bien sûr. C'est tout pour le moment! Si vous souhaitez en savoir plus sur la section "Jeux", voici une documentation utile qui peut vous aider :
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION