JavaRush /Blog Java /Random-ES /Sección "Juegos" sobre JavaRush: teoría útil

Sección "Juegos" sobre JavaRush: teoría útil

Publicado en el grupo Random-ES
En la sección "Juegos" de JavaRush encontrará interesantes proyectos para escribir juegos de computadora populares. ¿Quieres crear tu propia versión de los populares juegos “2048”, “Sapper”, “Snake” y otros? Es sencillo. Hemos convertido la escritura de juegos en un proceso paso a paso. CapítuloPara probarse a sí mismo como desarrollador de juegos, no es necesario ser un programador avanzado, pero aún se requiere un cierto conjunto de conocimientos de Java. Aquí encontrarás información que te será útil a la hora de escribir juegos .

1. Herencia

Trabajar con el motor de juego JavaRush implica utilizar la herencia. ¿Pero qué pasa si no sabes qué es? Por un lado, es necesario comprender este tema: se estudia en el nivel 11 . Por otro lado, el motor fue diseñado deliberadamente para ser muy simple, por lo que puedes arreglártelas con un conocimiento superficial de la herencia. Entonces, ¿qué es la herencia? En pocas palabras, la herencia es la relación entre dos clases. Uno de ellos se convierte en padre y el segundo en hijo (clase sucesora). En este caso, es posible que la clase principal ni siquiera sepa que tiene clases descendientes. Aquellos. no recibe ningún beneficio particular de la presencia de clases herederas. Pero la herencia proporciona muchas ventajas a una clase descendiente. Y la principal es que todas las variables y métodos de la clase principal aparecen en la clase secundaria, como si el código de la clase principal se hubiera copiado en la clase secundaria. Esto no es del todo cierto, pero para una comprensión simplificada de la herencia servirá. A continuación se muestran algunos ejemplos para comprender mejor la herencia. Ejemplo 1: la herencia más simple.
public class Родитель {

}
La clase Child hereda de la clase Parent usando la palabra clave extends .
public class Потомок extends Родитель {

}
Ejemplo 2: uso de variables de clase principal.
public class Родитель {

   public int age;
   public String name;
}
La clase Child puede usar las variables de edad y nombre de la clase Parent como si estuvieran declaradas en ella.
public class Потомок extends Родитель {

   public void printInfo() {

     System.out.println(name+" "+age);
   }
}
Ejemplo 3: uso de métodos de clase principal.
public class Родитель {

   public int age;
   public String name;

   public getName() {
      return name;
   }
}
La clase Child puede utilizar las variables y métodos de la clase Parent como si estuvieran declarados en ella. En este ejemplo estamos utilizando el método getName ().
public class Потомок extends Родитель {

   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}
Así es como se ve la clase Dedescendiente desde el punto de vista del compilador:
public class Потомок extends Родитель {

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

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

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

2. Anulación del método

A veces hay situaciones en las que heredamos nuestra clase Dedescendiente de alguna clase Padre muy útil, junto con todas las variables y métodos, pero algunos métodos no funcionan exactamente como queremos. O nada en la forma que no queremos. ¿Qué hacer en esta situación? Podemos anular un método que no nos guste. Esto se hace de manera muy simple: en nuestra clase Dedescendiente simplemente declaramos un método con la misma firma (encabezado) que el método de la clase Padre y escribimos nuestro código en él. Ejemplo 1: anulación de método.
public class Родитель {

   public String name;

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

   public getName() {
      return name;
  }
}
El método printInfo() imprimirá la frase "¡¡¡Luke, no!!!"
public class Потомок extends Родитель {

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

   public void printInfo() {

      setName("Luke");
      System.out.println( getName());
   }
}
Así es como se ve la clase Dedescendiente desde el punto de vista del compilador:
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());
   }
}
Ejemplo 2: un poco de magia de herencia (y anulación de métodos).
public class Родитель {

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

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

   public getName() {
      return "I'm your father, Luke";
  }
}
En este ejemplo: si un método printInfo(de la clase Padre) no se anula en la clase Descendente, cuando se llama a este método en un objeto de la clase Descendente, se llamará a su método getName(), y no getName()a la clase Padre.
Родитель parent = new Родитель ();
parent.printnInfo();
Este código muestra la inscripción "Luke" en la pantalla .
Потомок child = new Потомок ();
child.printnInfo();
Este código muestra la inscripción "Soy tu padre, Luke"; .
Así es como se ve la clase Dedescendiente desde el punto de vista del compilador:
public class Потомок extends Родитель {

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

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

3. Listas

Si aún no te han presentado las Listas, aquí tienes una introducción rápida. Podrás encontrar información completa en los niveles 6-7 del curso JavaRush . Las listas tienen mucho en común con las matrices:
  • puede almacenar una gran cantidad de datos de cierto tipo;
  • le permite recuperar elementos por su índice/número;
  • Los índices de los elementos comienzan en 0.
Ventajas de las listas: a diferencia de las matrices, las listas pueden cambiar de tamaño dinámicamente. Inmediatamente después de su creación, la lista tiene un tamaño de 0. A medida que agrega elementos a la lista, su tamaño aumenta. Ejemplo de creación de una lista:
ArrayList<String> myList = new ArrayList<String>(); // создание нового списка типа ArrayList
El valor entre paréntesis angulares es el tipo de datos que la lista puede almacenar. A continuación se muestran algunos métodos para trabajar con una lista:
Código Breve descripción de lo que hace el código.
ArrayList<String> list = new ArrayList<String>(); Creando una nueva lista de cadenas
list.add("name"); Agregar un elemento al final de la lista
list.add(0, "name"); Añadir un elemento al principio de la lista.
String name = list.get(5); Obtener un elemento por su índice
list.set(5, "new name"); Cambiar elemento por su índice
int count = list.size(); Obtener el número de elementos de una lista
list.remove(4); Eliminar un elemento de una lista
Puede obtener más información sobre las listas en estos artículos:
  1. clase ArrayList
  2. ArrayList de trabajo en imágenes
  3. Eliminar un elemento de una ArrayList

4. matrices

¿Qué es una matriz? Una matriz no es más que una tabla rectangular que se puede llenar con datos. En otras palabras, es una matriz bidimensional. Como probablemente sepas, las matrices en Java son objetos. Un tipo de matriz unidimensional estándar intse ve así:
int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
Imaginemos esto visualmente:
0 1 2 3 4 5 6 7
12 32 43 54 15 36 67 28
La línea superior indica las direcciones de las celdas. Es decir, para obtener el número 67, es necesario acceder al elemento de la matriz con índice 6:
int number = array[6];
Aquí todo es muy sencillo. Una matriz bidimensional es una matriz de matrices unidimensionales. Si es la primera vez que escuchas sobre esto, detente e imagínalo en tu cabeza. Una matriz bidimensional se parece a esto:
0 Matriz unidimensional Matriz unidimensional
1 Matriz unidimensional
2 Matriz unidimensional
3 Matriz unidimensional
4 Matriz unidimensional
5 Matriz unidimensional
6 Matriz unidimensional
7 Matriz unidimensional
En el código:
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
sesenta y cinco 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
sesenta y cinco 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 dieciséis 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
Para obtener el valor 47, debe acceder al elemento de la matriz en [4][2].
int number = matrix[4][2];
Si observa, las coordenadas de la matriz son diferentes del sistema de coordenadas rectangular clásico (sistema de coordenadas cartesiano). Al acceder a una matriz, se especifica y primero y luego x , mientras que en matemáticas es común especificar x(x, y) primero. Quizás te preguntes: “¿Por qué no invertir la matriz en tu imaginación y acceder a los elementos de la forma habitual a través de (x, y)? Esto no cambiará el contenido de la matriz”. Sí, nada cambiará. Pero en el mundo de la programación, es habitual referirse a matrices en la forma "primero y, luego x". Esto debe darse por sentado. Ahora hablemos de proyectar la matriz en nuestro motor (clase Game). Como sabes, el motor tiene muchos métodos que cambian las celdas del campo de juego en unas coordenadas determinadas. Por ejemplo, el setCellValue(int x, int y, String value). Establece una determinada celda con coordenadas (x, y) al valor value. Como habrás notado, este método primero toma exactamente x, como en el sistema de coordenadas clásico. El resto de métodos del motor funcionan de forma similar. Al desarrollar juegos, a menudo será necesario reproducir el estado de la matriz en la pantalla. ¿Como hacer esto? Primero, en un bucle debes recorrer todos los elementos de la matriz. En segundo lugar, para cada uno de ellos, llame a un método para mostrar con coordenadas INVERTIDAS. Ejemplo:
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]));
        }
    }
}
Naturalmente, la inversión funciona en dos direcciones. setCellValuePuedes pasar (i, j) al método , pero al mismo tiempo tomar el elemento [j][i] de la matriz. La inversión puede parecer un poco difícil, pero es algo a tener en cuenta. Y siempre, si surge algún problema, conviene coger un papel con un bolígrafo, dibujar una matriz y reproducir los procesos que le están sucediendo.

5. Números aleatorios

¿Cómo trabajar con un generador de números aleatorios? La clase Gamedefine un método getRandomNumber(int). En el fondo, utiliza una clase Randomdel paquete java.util, pero esto no cambia el principio de trabajar con un generador de números aleatorios. getRandomNumber(int)Toma un número entero como argumento . Este número será el límite superior que el generador puede devolver. El límite inferior es 0. ¡Importante! El generador NUNCA devolverá un número de límite superior. Por ejemplo, si se llama getRandomNumber(3)aleatoriamente, puede devolver 0, 1, 2. Como puede ver, no puede devolver 3. Este uso de un generador es bastante sencillo, pero muy eficaz en muchos casos. Necesita obtener un número aleatorio dentro de algunos límites: imagine que necesita un número de tres dígitos (100..999). Como ya sabes, el número mínimo devuelto es 0. Por lo tanto, deberás agregarle 100. Pero en este caso, debes tener cuidado de no exceder el límite superior. Para obtener 999 como valor aleatorio máximo, debe llamar al método getRandomNumber(int)con un argumento de 1000. Pero recordemos la adición posterior de 100: esto significa que el límite superior debe reducirse en 100. Es decir, el código para obtener un Un número aleatorio de tres dígitos se vería así:
int number = 100 + getRandomNumber(900);
Pero para simplificar dicho procedimiento, el motor proporciona un método getRandomNumber(int, int)que toma el número mínimo a devolver como primer argumento. Usando este método, el ejemplo anterior se puede reescribir:
int number = getRandomNumber(100, 1000);
Se pueden utilizar números aleatorios para obtener un elemento de matriz aleatorio:
String [] names = {"andrey", "Валентин", "Сергей"};
String randomName = names[getRandomNumber(names.length)]
Desencadenar ciertos eventos con una cierta probabilidad. La mañana de una persona comienza según posibles escenarios: Dormido – 50%; Se levantó a tiempo – 40%; Se levantó una hora antes de lo esperado: 10%. Imagina que estás escribiendo un emulador matutino humano. Necesita desencadenar eventos con cierta probabilidad. Para hacer esto, nuevamente, necesitas usar un generador de números aleatorios. Las implementaciones pueden ser diferentes, pero la más sencilla debería seguir el siguiente algoritmo:
  1. establecemos los límites dentro de los cuales necesitamos generar el número;
  2. generar un número aleatorio;
  3. Procesamos el número resultante.
Entonces, en este caso, el límite será 10. Llamemos al método getRandomNumber(10)y analicemos qué nos puede devolver. Puede devolver 10 dígitos (del 0 al 9) y cada uno con la misma probabilidad: 10%. Ahora necesitamos combinar todos los resultados posibles y relacionarlos con nuestros posibles eventos. Puede haber muchas combinaciones, dependiendo de tu imaginación, pero la más obvia suena: “Si un número aleatorio se encuentra dentro de [0..4], llama al evento “Dormimiento”, si el número está dentro de [5..8] ] - “Me desperté a tiempo”, y solo si el número es 9, entonces “Me levanté una hora antes de lo esperado”. Todo es muy simple: dentro de [0..4] hay 5 números, cada uno de los cuales puede regresar con una probabilidad del 10%, que en total será el 50%; dentro de [5..8] hay 4 números, y el 9 es el único número que aparece con una probabilidad del 10%. En código, todo este diseño inteligente parece aún más simple:
int randomNumber = getRandomNumber(10);
if (randomNumber < 5) {
    System.out.println("Проспал ");
} else if (randomNumber < 9) {
    System.out.println("Встал вовремя ");
} else {
    System.out.println("Встал на час раньше положенного ");
}
En general, puede haber muchas opciones para utilizar números aleatorios. Todo depende sólo de tu imaginación. Pero se utilizan con mayor eficacia si necesita obtener algún resultado repetidamente. Entonces este resultado será diferente al anterior. Con cierta probabilidad, claro. ¡Eso es todo! Si desea obtener más información sobre la sección Juegos, aquí tiene documentación útil que puede ayudar:
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION