JavaRush /Blog Java /Random-FR /Section "Jeux" sur JavaRush : Théorie utile

Section "Jeux" sur JavaRush : Théorie utile

Publié dans le groupe Random-FR
Dans la section « Jeux » de JavaRush, vous trouverez des projets passionnants pour l'écriture de jeux informatiques populaires. Voulez-vous créer votre propre version des jeux populaires « 2048 », « Sapper », « Snake » et d'autres jeux ? C'est simple. Nous avons transformé l'écriture de jeux en un processus étape par étape. ChapitrePour vous essayer en tant que développeur de jeux, vous n'avez pas besoin d'être un programmeur avancé, mais un certain ensemble de connaissances Java est toujours requis. Vous trouverez ici des informations qui vous seront utiles lors de l'écriture de jeux .

1. Héritage

Travailler avec le moteur de jeu JavaRush implique l'utilisation de l'héritage. Mais que faire si vous ne savez pas ce que c'est ? D'une part, il faut comprendre ce sujet : il est étudié au niveau 11 . En revanche, le moteur a été délibérément conçu pour être très simple, afin que vous puissiez vous débrouiller avec une connaissance superficielle de l'héritage. Alors, qu’est-ce que l’héritage ? Pour le dire très simplement, l’héritage est la relation entre deux classes. L'un d'eux devient le parent et le second devient l'enfant (classe successeur). Dans ce cas, la classe parent peut même ne pas savoir qu’elle possède des classes descendantes. Ceux. il ne tire aucun avantage particulier de la présence de classes héritières. Mais l’héritage offre de nombreux avantages à une classe descendante. Et le principal est que toutes les variables et méthodes de la classe parent apparaissent dans la classe enfant, comme si le code de la classe parent était copié dans la classe enfant. Ce n’est pas tout à fait vrai, mais cela fera l’affaire pour une compréhension simplifiée de l’héritage. Voici quelques exemples pour mieux comprendre l’héritage. Exemple 1 : l'héritage le plus simple.
public class Родитель {

}
La classe Child hérite de la classe Parent en utilisant le mot clé extends .
public class Потомок extends Родитель {

}
Exemple 2 : Utilisation de variables de classe parent.
public class Родитель {

   public int age;
   public String name;
}
La classe Child peut utiliser les variables age et name de la classe Parent comme si elles y étaient déclarées.
public class Потомок extends Родитель {

   public void printInfo() {

     System.out.println(name+" "+age);
   }
}
Exemple 3 : Utilisation des méthodes de la classe parent.
public class Родитель {

   public int age;
   public String name;

   public getName() {
      return name;
   }
}
La classe Child peut utiliser les variables et méthodes de la classe Parent comme si elles y étaient déclarées. Dans cet exemple, nous utilisons la méthode getName ().
public class Потомок extends Родитель {

   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}
Voici à quoi ressemble la classe Descendant du point de vue du compilateur :
public class Потомок extends Родитель {

   public int age; //  унаследованная переменная
   public String name; //  унаследованная переменная

   public getName() { //  унаследованный метод.
      return name;
  }
   public void printInfo() {

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

2. Remplacement de méthode

Parfois, il arrive que nous ayons hérité de notre classe Descendant d'une classe Parent très utile, ainsi que de toutes les variables et méthodes, mais certaines méthodes ne fonctionnent pas exactement comme nous le souhaitons. Ou pas du tout comme nous ne le souhaitons pas. que-faire dans cette situation? Nous pouvons remplacer une méthode que nous n’aimons pas. Cela se fait très simplement : dans notre classe Descendant, nous déclarons simplement une méthode avec la même signature (en-tête) que la méthode de la classe Parent et y écrivons notre code. Exemple 1 : remplacement de méthode.
public class Родитель {

   public String name;

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

   public getName() {
      return name;
  }
}
La méthode printInfo() imprimera la phrase "Luke, No !!!"
public class Потомок extends Родитель {

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

   public void printInfo() {

      setName("Luke");
      System.out.println( getName());
   }
}
Voici à quoi ressemble la classe Descendant du point de vue du compilateur :
public Потомок extends Родитель {

   public String name; //  унаследованная переменная

   public void setName (String nameNew) { //  Переопределенный метод взамен унаследованного

       name = nameNew + ", No!!!";
   }
   public getName() { //  унаследованный метод.

      return name;
   }
   public void printInfo() {

     setName("Luke");
     System.out.println(getName());
   }
}
Exemple 2 : un peu de magie de l'héritage (et du remplacement de méthode).
public class Родитель {

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

     System.out.println(getName());
   }
}
public class Потомок extends Родитель {

   public getName() {
      return "I'm your father, Luke";
  }
}
Dans cet exemple : si une méthode printInfo(de la classe Parent) n'est pas surchargée dans la classe Descendant, lorsque cette méthode est appelée sur un objet de la classe Descendant, c'est sa méthode qui sera appelée getName(), et non getName()la classe Parent.
Родитель parent = new Родитель ();
parent.printnInfo();
Ce code affiche l'inscription "Luke" sur l'écran .
Потомок child = new Потомок ();
child.printnInfo();
Ce code affiche l'inscription « Je suis ton père, Luke » ; .
Voici à quoi ressemble la classe Descendant du point de vue du compilateur :
public class Потомок extends Родитель {

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

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

3. Listes

Si vous n'avez pas encore découvert les listes, voici une brève introduction. Vous pouvez trouver des informations complètes sur les niveaux 6-7 du cours JavaRush . Les listes ont beaucoup en commun avec les tableaux :
  • peut stocker beaucoup de données d'un certain type ;
  • vous permettent de récupérer des éléments par leur index/numéro ;
  • les indices des éléments commencent à 0.
Avantages des listes : contrairement aux tableaux, les listes peuvent changer de taille de manière dynamique. Immédiatement après sa création, la liste a une taille de 0. À mesure que vous ajoutez des éléments à la liste, sa taille augmente. Exemple de création d'une liste :
ArrayList<String> myList = new ArrayList<String>(); // создание нового списка типа ArrayList
La valeur entre crochets est le type de données que la liste peut stocker. Voici quelques méthodes pour travailler avec une liste :
Code Brève description de ce que fait le code
ArrayList<String> list = new ArrayList<String>(); Création d'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); Récupère un élément par son index
list.set(5, "new name"); Changer l'élément par son index
int count = list.size(); Obtenir le nombre d'éléments dans une liste
list.remove(4); Supprimer un élément d'une liste
Vous pouvez en savoir plus sur les listes dans ces articles :
  1. Classe ArrayList
  2. ArrayList de travail 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 pouvant être rempli de données. En d’autres termes, il s’agit d’un tableau à deux dimensions. Comme vous le savez probablement, les tableaux en Java sont des objets. Un type de tableau unidimensionnel standard intressemble à ceci :
int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
Imaginons cela visuellement :
0 1 2 3 4 5 6 7
12 32 43 54 15 36 67 28
La ligne supérieure indique les adresses des cellules. Autrement dit, pour obtenir le nombre 67, vous devez accéder à l'élément du tableau avec l'index 6 :
int number = array[6];
Tout est très simple ici. Un tableau à deux dimensions est un tableau de tableaux à une dimension. Si c’est la première fois que vous entendez parler de cela, 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 le 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 accéder à l'élément matriciel en [4][2].
int number = matrix[4][2];
Si vous remarquez, les coordonnées matricielles sont différentes du système de coordonnées rectangulaires classique (système de coordonnées cartésiennes). Lorsque vous accédez à une matrice, vous spécifiez d'abord y puis x , alors qu'en mathématiques, il est courant de spécifier x(x, y) en premier. Vous vous demandez peut-être : « Pourquoi ne pas inverser la matrice dans votre imagination et accéder aux éléments de la manière habituelle via (x, y) ? Cela ne changera pas le contenu de la matrice. Oui, rien ne changera. Mais dans le monde de la programmation, il est d’usage de faire référence aux matrices sous la forme « d’abord y, puis x ». Cela doit être pris pour acquis. Parlons maintenant de la projection de la matrice sur notre moteur (classe Game). Comme vous le savez, le moteur dispose de nombreuses méthodes qui modifient les cellules du terrain de jeu à des coordonnées données. Par exemple, le setCellValue(int x, int y, String value). Il définit une certaine cellule avec les coordonnées (x, y) à la valeur value. Comme vous l'avez remarqué, cette méthode prend d'abord exactement x, comme dans le système de coordonnées classique. Les autres méthodes du moteur fonctionnent de la même manière. Lors du développement de jeux, il sera souvent nécessaire de reproduire l’état de la matrice à l’écran. Comment faire cela ? Tout d’abord, dans une boucle, vous devez parcourir tous les éléments de la matrice. Deuxièmement, pour chacun d’eux, appelez une méthode à afficher avec des coordonnées INVERSÉES. 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 deux directions. setCellValueVous pouvez passer (i, j) à la méthode , mais en même temps prendre l'élément [j][i] de la matrice. L'inversion peut paraître un peu difficile, mais c'est quelque chose à garder à l'esprit. Et toujours, si des problèmes surviennent, cela vaut la peine de prendre un morceau de papier avec un stylo, de dessiner une matrice et de reproduire les processus qui s'y déroulent.

5. Nombres aléatoires

Comment travailler avec un générateur de nombres aléatoires ? La classe Gamedéfinit une méthode getRandomNumber(int). Sous le capot, il utilise une classe Randomdu package java.util, mais cela ne change rien au principe de travail avec un générateur de nombres aléatoires. getRandomNumber(int)Prend un entier comme argument . Ce nombre sera la limite supérieure que le générateur peut renvoyer. La limite inférieure est 0. Important! Le générateur ne renverra JAMAIS un nombre limite supérieur. Par exemple, s’il est appelé getRandomNumber(3)de manière aléatoire, il peut renvoyer 0, 1, 2. Comme vous pouvez le voir, il ne peut pas renvoyer 3. Cette utilisation d’un générateur est assez simple, mais très efficace dans de nombreux cas. Vous devez obtenir un nombre aléatoire dans certaines limites : Imaginez que vous ayez besoin d'un nombre à trois chiffres (100..999). Comme vous le savez déjà, le nombre minimum renvoyé est 0. Vous devrez donc y 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, vous devez appeler la méthode getRandomNumber(int)avec un argument de 1000. Mais nous nous souvenons de l'ajout ultérieur de 100 : cela signifie que la limite supérieure doit être abaissée de 100. C'est-à-dire le code pour obtenir un Un nombre aléatoire à trois chiffres ressemblerait à ceci :
int number = 100 + getRandomNumber(900);
Mais pour simplifier une telle procédure, le moteur fournit une méthode getRandomNumber(int, int)qui prend le nombre minimum à renvoyer comme premier argument. En utilisant cette méthode, l'exemple précédent peut être réécrit :
int number = getRandomNumber(100, 1000);
Des nombres aléatoires peuvent être utilisés pour obtenir un élément de tableau aléatoire :
String [] names = {"Andrey", "Валентин", "Сергей"};
String randomName = names[getRandomNumber(names.length)]
Déclencher certains événements avec une certaine probabilité. La matinée d’une personne commence selon des scénarios possibles : Dormir trop longtemps – 50 % ; Je me suis levé à l'heure – 40 % ; Je me suis levé une heure plus tôt que prévu – 10 %. Imaginez que vous écrivez un émulateur matinal humain. Vous devez déclencher des événements avec une certaine probabilité. Pour ce faire, vous devez encore une fois utiliser un générateur de nombres aléatoires. Les implémentations peuvent être différentes, mais la plus simple doit suivre l'algorithme suivant :
  1. nous fixons les limites dans lesquelles nous devons générer le nombre ;
  2. générer un nombre aléatoire ;
  3. Nous traitons le nombre résultant.
Donc, dans ce cas, la limite sera de 10. Appelons la méthode getRandomNumber(10)et analysons ce qu'elle peut nous retourner. Il peut renvoyer 10 chiffres (de 0 à 9) et chacun avec la même probabilité - 10 %. Nous devons maintenant combiner tous les résultats possibles et les faire correspondre à nos événements possibles. Il peut y avoir de nombreuses combinaisons, selon votre imagination, mais la plus évidente sonne : "Si un nombre aléatoire se situe entre [0..4] - appelez l'événement "Sursommeil", si le nombre est compris entre [5..8". ] - "Réveillez-vous" à l'heure ", et seulement si le chiffre est 9, alors" Je me suis levé une heure plus tôt que prévu. Tout est très simple : à l'intérieur de [0..4] il y a 5 nombres, dont chacun peut revenir avec une probabilité de 10 %, ce qui au total sera de 50 % ; dans [5..8], il y a 4 nombres, et 9 est le seul nombre qui apparaît avec une probabilité de 10 %. Dans le code, toute cette conception intelligente semble encore plus simple :
int randomNumber = getRandomNumber(10);
if (randomNumber < 5) {
    System.out.println("Проспал ");
} else if (randomNumber < 9) {
    System.out.println("Встал вовремя ");
} else {
    System.out.println("Встал на час раньше положенного ");
}
En général, il existe de nombreuses options pour utiliser des nombres aléatoires. Tout dépend uniquement de votre imagination. Mais ils sont utilisés plus efficacement si vous avez besoin d'obtenir un résultat à plusieurs reprises. Ce résultat sera alors différent du précédent. Avec une certaine probabilité, bien sûr. C'est tout! 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