JavaRush /Java Blog /Random EN /Section "Games" on JavaRush: Useful theory

Section "Games" on JavaRush: Useful theory

Published in the Random EN group
In the “Games” section of JavaRush you will find exciting projects for writing popular computer games. Do you want to create your own version of the popular “2048”, “Sapper”, “Snake” and other games? It's simple. We've turned game writing into a step-by-step process. ChapterTo try yourself as a game developer, you don’t have to be an advanced programmer, but a certain set of Java knowledge is still required. Here you will find information that will be useful when writing games .

1. Inheritance

Working with the JavaRush game engine involves using inheritance. But what if you don't know what it is? On the one hand, you need to understand this topic: it is studied at level 11 . On the other hand, the engine was deliberately designed to be very simple, so you can get by with a superficial knowledge of inheritance. So, what is inheritance? To put it very simply, inheritance is the relationship between two classes. One of them becomes the parent, and the second becomes the child (successor class). In this case, the parent class may not even know that it has descendant classes. Those. it does not receive any particular benefit from the presence of inheritor classes. But inheritance provides many advantages to a descendant class. And the main one is that all the variables and methods of the parent class appear in the child class, as if the code of the parent class was copied into the child class. This is not entirely true, but for a simplified understanding of inheritance it will do. Here are some examples to better understand inheritance. Example 1: the simplest inheritance.
public class Родитель {

}
The Child class inherits from the Parent class using the extends keyword .
public class Потомок extends Родитель {

}
Example 2: Using parent class variables.
public class Родитель {

   public int age;
   public String name;
}
The Child class can use the age and name variables of the Parent class as if they were declared in it.
public class Потомок extends Родитель {

   public void printInfo() {

     System.out.println(name+" "+age);
   }
}
Example 3: Using parent class methods.
public class Родитель {

   public int age;
   public String name;

   public getName() {
      return name;
   }
}
The Child class can use the variables and methods of the Parent class as if they were declared in it. In this example we are using the getName () method.
public class Потомок extends Родитель {

   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}
This is what the Descendant class looks like from the compiler's point of view:
public class Потомок extends Родитель {

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

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

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

2. Method overriding

Sometimes there are situations that we inherited our Descendant class from some very useful Parent class, along with all the variables and methods, but some methods do not work exactly the way we want. Or not at all in the way we don’t want. What to do in this situation? We can override a method we don’t like. This is done very simply: in our Descendant class we simply declare a method with the same signature (header) as the Parent class method and write our code in it. Example 1: Method overriding.
public class Родитель {

   public String name;

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

   public getName() {
      return name;
  }
}
The printInfo() method will print the phrase "Luke, No!!!"
public class Потомок extends Родитель {

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

   public void printInfo() {

      setName("Luke");
      System.out.println( getName());
   }
}
This is what the Descendant class looks like from the compiler's point of view:
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());
   }
}
Example 2: a little magic of inheritance (and method overriding).
public class Родитель {

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

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

   public getName() {
      return "I'm your father, Luke";
  }
}
In this example: if a method printInfo(from the Parent class) is not overridden in the Descendant class, when this method is called on an object of the Descendant class, its method will be called getName(), and not getName()the Parent class.
Родитель parent = new Родитель ();
parent.printnInfo();
This code displays the inscription "Luke" on the screen .
Потомок child = new Потомок ();
child.printnInfo();
This code displays the inscription "I'm your father, Luke;" .
This is what the Descendant class looks like from the compiler's point of view:
public class Потомок extends Родитель {

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

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

3. Lists

If you haven't met Lists yet, here's a quick primer. You can find complete information on levels 6-7 of the JavaRush course . Lists have a lot in common with arrays:
  • can store a lot of data of a certain type;
  • allow you to retrieve elements by their index/number;
  • element indices start at 0.
Advantages of lists: Unlike arrays, lists can change size dynamically. Immediately after creation, the list has a size of 0. As you add elements to the list, its size increases. Example of creating a list:
ArrayList<String> myList = new ArrayList<String>(); // создание нового списка типа ArrayList
The value in the angle brackets is the type of data the list can store. Here are some methods for working with a list:
Code Brief description of what the code does
ArrayList<String> list = new ArrayList<String>(); Creating a new list of strings
list.add("name"); Add an element to the end of the list
list.add(0, "name"); Add an element to the beginning of the list
String name = list.get(5); Get an element by its index
list.set(5, "new name"); Change element by its index
int count = list.size(); Get the number of elements in a list
list.remove(4); Remove an item from a list
You can learn more about lists from these articles:
  1. ArrayList class
  2. Working ArrayList in pictures
  3. Removing an element from an ArrayList

4. Arrays

What is a matrix? A matrix is ​​nothing more than a rectangular table that can be filled with data. In other words, it is a two-dimensional array. As you probably know, arrays in Java are objects. A standard one-dimensional array type intlooks like this:
int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
Let's imagine this visually:
0 1 2 3 4 5 6 7
12 32 43 54 15 36 67 28
The top line indicates the cell addresses. That is, to get the number 67, you need to access the array element with index 6:
int number = array[6];
Everything is very simple here. A two-dimensional array is an array of one-dimensional arrays. If this is your first time hearing about this, stop and picture it in your head. A two-dimensional array looks something like this:
0 One-dimensional array One-dimensional array
1 One-dimensional array
2 One-dimensional array
3 One-dimensional array
4 One-dimensional array
5 One-dimensional array
6 One-dimensional array
7 One-dimensional array
In the 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
To get the value 47, you need to access the matrix element at [4][2].
int number = matrix[4][2];
If you notice, the matrix coordinates are different from the classical rectangular coordinate system (Cartesian coordinate system). When accessing a matrix, you specify y first and then x , whereas in mathematics it is common to specify x(x, y) first. You may be asking yourself, “Why not reverse the matrix in your imagination and access the elements in the usual way through (x, y)? This will not change the contents of the matrix.” Yes, nothing will change. But in the programming world, it is customary to refer to matrices in the form “first y, then x.” This must be taken for granted. Now let's talk about projecting the matrix onto our engine (class Game). As you know, the engine has many methods that change the cells of the playing field at given coordinates. For example, the setCellValue(int x, int y, String value). It sets a certain cell with coordinates (x, y) to the value value. As you noticed, this method first takes exactly x, as in the classical coordinate system. The rest of the engine methods work in a similar way. When developing games, there will often be a need to reproduce the state of the matrix on the screen. How to do this? First, in a loop you need to iterate through all the elements of the matrix. Second, for each of them, call a method to display with INVERTED coordinates. Example:
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]));
        }
    }
}
Naturally, inversion works in two directions. setCellValueYou can pass (i, j) to the method , but at the same time take the element [j][i] from the matrix. The inversion may seem a little difficult, but it's something to keep in mind. And always, if any problems arise, it’s worth taking a piece of paper with a pen, drawing a matrix and reproducing what processes are happening to it.

5. Random numbers

How to work with a random number generator? The class Gamedefines a method getRandomNumber(int). Under the hood, it uses a class Randomfrom the java.util package, but this does not change the principle of working with a random number generator. getRandomNumber(int)Takes an integer as an argument . This number will be the upper bound that the generator can return. The lower limit is 0. Important! The generator will NEVER return an upper bound number. For example, if called getRandomNumber(3)randomly it can return 0, 1, 2. As you can see, it cannot return 3. This use of a generator is quite simple, but very effective in many cases. You need to get a random number within some limits: Imagine that you need some three-digit number (100..999). As you already know, the minimum number returned is 0. So, you will need to add 100 to it. But in this case, you need to take care not to exceed the upper limit. To get 999 as the maximum random value, you should call the method getRandomNumber(int)with an argument of 1000. But we remember about the subsequent addition of 100: this means that the upper bound should be lowered by 100. That is, the code to get a random three-digit number would look like this:
int number = 100 + getRandomNumber(900);
But to simplify such a procedure, the engine provides a method getRandomNumber(int, int)that takes the minimum number to return as the first argument. Using this method, the previous example can be rewritten:
int number = getRandomNumber(100, 1000);
Random numbers can be used to obtain a random array element:
String [] names = {"Andrey", "Валентин", "Сергей"};
String randomName = names[getRandomNumber(names.length)]
Triggering certain events with a certain probability. A person’s morning begins according to possible scenarios: Overslept – 50%; Got up on time – 40%; Got up an hour earlier than expected – 10%. Imagine that you are writing a human morning emulator. You need to trigger events with a certain probability. To do this, again, you need to use a random number generator. Implementations may be different, but the simplest one should follow the following algorithm:
  1. we set the limits within which the number needs to be generated;
  2. generate a random number;
  3. We process the resulting number.
So, in this case, the limit will be 10. Let's call the method getRandomNumber(10)and analyze what it can return to us. It can return 10 digits (from 0 to 9) and each with the same probability - 10%. Now we need to combine all the possible outcomes and match them with our possible events. There can be a lot of combinations, depending on your imagination, but the most obvious sounds: “If a random number lies within [0..4] - call the event “Overslept”, if the number is within [5..8] - “Wake up” on time,” and only if the number is 9, then “I got up an hour earlier than expected.” Everything is very simple: within [0..4] there are 5 numbers, each of which can return with a probability of 10%, which in total will be 50%; within [5..8] there are 4 numbers, and 9 is the only number that appears with a probability of 10%. In code, this whole clever design looks even simpler:
int randomNumber = getRandomNumber(10);
if (randomNumber < 5) {
    System.out.println("Проспал ");
} else if (randomNumber < 9) {
    System.out.println("Встал вовремя ");
} else {
    System.out.println("Встал на час раньше положенного ");
}
In general, there can be a lot of options for using random numbers. It all depends only on your imagination. But they are most effectively used if you need to get some result repeatedly. Then this result will be different from the previous one. With some probability, of course. That's all! If you want to learn more about the Games section, here is some useful documentation that can help:
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION