JavaRush /Blogue Java /Random-PT /Seção "Jogos" no JavaRush: teoria útil

Seção "Jogos" no JavaRush: teoria útil

Publicado no grupo Random-PT
Na seção "Jogos" do JavaRush você encontrará projetos interessantes para escrever jogos de computador populares. Quer criar sua própria versão dos populares “2048”, “Sapper”, “Snake” e outros jogos? É simples. Transformamos a escrita de jogos em um processo passo a passo. CapítuloPara tentar ser um desenvolvedor de jogos, você não precisa ser um programador avançado, mas ainda é necessário um certo conjunto de conhecimentos de Java. Aqui você encontrará informações que serão úteis ao escrever jogos .

1. Herança

Trabalhar com o mecanismo de jogo JavaRush envolve o uso de herança. Mas e se você não souber o que é? Por um lado, você precisa entender este tema: ele é estudado no nível 11 . Por outro lado, o mecanismo foi deliberadamente projetado para ser muito simples, para que você possa conviver com um conhecimento superficial de herança. Então, o que é herança? Simplificando, herança é o relacionamento entre duas classes. Um deles se torna o pai e o segundo se torna o filho (classe sucessora). Nesse caso, a classe pai pode nem saber que possui classes descendentes. Aqueles. ele não recebe nenhum benefício específico da presença de classes herdeiras. Mas a herança oferece muitas vantagens para uma classe descendente. E a principal delas é que todas as variáveis ​​e métodos da classe pai aparecem na classe filha, como se o código da classe pai fosse copiado para a classe filha. Isso não é inteiramente verdade, mas para uma compreensão simplificada da herança servirá. Aqui estão alguns exemplos para entender melhor a herança. Exemplo 1: a herança mais simples.
public class Родитель {

}
A classe Child herda da classe Parent usando a palavra-chave extends .
public class Потомок extends Родитель {

}
Exemplo 2: Usando variáveis ​​de classe pai.
public class Родитель {

   public int age;
   public String name;
}
A classe Child pode usar as variáveis ​​idade e nome da classe Parent como se estivessem declaradas nela.
public class Потомок extends Родитель {

   public void printInfo() {

     System.out.println(name+" "+age);
   }
}
Exemplo 3: Usando métodos de classe pai.
public class Родитель {

   public int age;
   public String name;

   public getName() {
      return name;
   }
}
A classe Child pode usar as variáveis ​​e métodos da classe Parent como se estivessem declarados nela. Neste exemplo estamos usando o método getName ().
public class Потомок extends Родитель {

   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}
Esta é a aparência da classe Descendant do ponto de vista do compilador:
public class Потомок extends Родитель {

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

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

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

2. Substituição de método

Às vezes há situações em que herdamos nossa classe Descendant de alguma classe Parent muito útil, junto com todas as variáveis ​​e métodos, mas alguns métodos não funcionam exatamente da maneira que desejamos. Ou não da maneira que não queremos. O que fazer nessa situação? Podemos substituir um método que não gostamos. Isso é feito de forma muito simples: em nossa classe Descendant simplesmente declaramos um método com a mesma assinatura (cabeçalho) do método da classe Parent e escrevemos nosso código nele. Exemplo 1: Substituição de método.
public class Родитель {

   public String name;

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

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

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

   public void printInfo() {

      setName("Luke");
      System.out.println( getName());
   }
}
Esta é a aparência da classe Descendant do ponto de vista do 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());
   }
}
Exemplo 2: um pouco de magia de herança (e substituição de método).
public class Родитель {

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

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

   public getName() {
      return "I'm your father, Luke";
  }
}
Neste exemplo: se um método printInfo(da classe Parent) não for sobrescrito na classe Descendant, quando este método for chamado em um objeto da classe Descendant, seu método será chamado getName(), e não getName()a classe Parent.
Родитель parent = new Родитель ();
parent.printnInfo();
Este código exibe a inscrição "Luke" na tela .
Потомок child = new Потомок ();
child.printnInfo();
Este código exibe a inscrição “Eu sou seu pai, Luke;” .
Esta é a aparência da classe Descendant do ponto de vista do compilador:
public class Потомок extends Родитель {

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

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

3. Listas

Se você ainda não conheceu o Lists, aqui está uma introdução rápida. Você pode encontrar informações completas nos níveis 6 a 7 do curso JavaRush . As listas têm muito em comum com os arrays:
  • pode armazenar muitos dados de um determinado tipo;
  • permitem recuperar elementos por seu índice/número;
  • os índices dos elementos começam em 0.
Vantagens das listas: Ao contrário dos arrays, as listas podem mudar de tamanho dinamicamente. Imediatamente após a criação, a lista tem tamanho 0. À medida que você adiciona elementos à lista, seu tamanho aumenta. Exemplo de criação de uma lista:
ArrayList<String> myList = new ArrayList<String>(); // создание нового списка типа ArrayList
O valor entre colchetes angulares é o tipo de dados que a lista pode armazenar. Aqui estão alguns métodos para trabalhar com uma lista:
Código Breve descrição do que o código faz
ArrayList<String> list = new ArrayList<String>(); Criando uma nova lista de strings
list.add("name"); Adicione um elemento ao final da lista
list.add(0, "name"); Adicione um elemento ao início da lista
String name = list.get(5); Obtenha um elemento pelo seu índice
list.set(5, "new name"); Alterar elemento pelo seu índice
int count = list.size(); Obtenha o número de elementos em uma lista
list.remove(4); Remover um item de uma lista
Você pode aprender mais sobre listas nestes artigos:
  1. Classe ArrayList
  2. Trabalhando ArrayList em imagens
  3. Removendo um elemento de um ArrayList

4. Matrizes

O que é uma matriz? Uma matriz nada mais é do que uma tabela retangular que pode ser preenchida com dados. Em outras palavras, é uma matriz bidimensional. Como você provavelmente sabe, arrays em Java são objetos. Um tipo de array unidimensional padrão intse parece com isto:
int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
Vamos imaginar isso visualmente:
0 1 2 3 4 5 6 7
12 32 43 54 15 36 67 28
A linha superior indica os endereços das células. Ou seja, para obter o número 67, é necessário acessar o elemento do array com índice 6:
int number = array[6];
Tudo é muito simples aqui. Uma matriz bidimensional é uma matriz de matrizes unidimensionais. Se esta é a primeira vez que você ouve sobre isso, pare e imagine isso em sua cabeça. Uma matriz bidimensional se parece com isto:
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
No 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
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
Para obter o valor 47, você precisa acessar o elemento da matriz em [4][2].
int number = matrix[4][2];
Se você notar, as coordenadas da matriz são diferentes do sistema de coordenadas retangulares clássico (sistema de coordenadas cartesianas). Ao acessar uma matriz, você especifica y primeiro e depois x , enquanto em matemática é comum especificar x(x, y) primeiro. Você pode estar se perguntando: “Por que não inverter a matriz em sua imaginação e acessar os elementos da maneira usual através de (x, y)? Isso não mudará o conteúdo da matriz.” Sim, nada vai mudar. Mas no mundo da programação, é comum referir-se a matrizes na forma “primeiro y, depois x”. Isto deve ser dado como certo. Agora vamos falar sobre projetar a matriz em nosso mecanismo (class Game). Como você sabe, o mecanismo possui muitos métodos que alteram as células do campo de jogo em determinadas coordenadas. Por exemplo, o setCellValue(int x, int y, String value). Ele define uma determinada célula com coordenadas (x, y) para o valor value. Como você notou, este método primeiro utiliza exatamente x, como no sistema de coordenadas clássico. Os demais métodos do mecanismo funcionam de maneira semelhante. Ao desenvolver jogos, muitas vezes será necessário reproduzir o estado da matriz na tela. Como fazer isso? Primeiro, em um loop você precisa iterar todos os elementos da matriz. Segundo, para cada um deles, chame um método para exibir com coordenadas INVERTIDAS. Exemplo:
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, a inversão funciona em duas direções. setCellValueVocê pode passar (i, j) para o método , mas ao mesmo tempo pegar o elemento [j][i] da matriz. A inversão pode parecer um pouco difícil, mas é algo para se ter em mente. E sempre, caso surja algum problema, vale pegar um pedaço de papel com caneta, desenhar uma matriz e reproduzir quais processos estão acontecendo com ela.

5. Números aleatórios

Como trabalhar com um gerador de números aleatórios? A classe Gamedefine um método getRandomNumber(int). Nos bastidores, ele usa uma classe Randomdo pacote java.util, mas isso não altera o princípio de trabalhar com um gerador de números aleatórios. getRandomNumber(int)Toma um número inteiro como argumento . Este número será o limite superior que o gerador pode retornar. O limite inferior é 0. Importante! O gerador NUNCA retornará um número de limite superior. Por exemplo, se for chamado getRandomNumber(3)aleatoriamente, pode retornar 0, 1, 2. Como você pode ver, não pode retornar 3. Este uso de gerador é bastante simples, mas muito eficaz em muitos casos. Você precisa obter um número aleatório dentro de alguns limites: Imagine que você precisa de um número de três dígitos (100..999). Como você já sabe, o número mínimo retornado é 0. Portanto, você precisará adicionar 100. Mas, neste caso, é preciso tomar cuidado para não ultrapassar o limite superior. Para obter 999 como o valor aleatório máximo, você deve chamar o método getRandomNumber(int)com um argumento de 1000. Mas lembramos da adição subsequente de 100: isso significa que o limite superior deve ser reduzido em 100. Ou seja, o código para obter um número aleatório de três dígitos ficaria assim:
int number = 100 + getRandomNumber(900);
Mas para simplificar tal procedimento, o mecanismo fornece um método getRandomNumber(int, int)que leva o número mínimo para retornar como primeiro argumento. Usando este método, o exemplo anterior pode ser reescrito:
int number = getRandomNumber(100, 1000);
Números aleatórios podem ser usados ​​para obter um elemento aleatório da matriz:
String [] names = {"Andrey", "Валентин", "Сергей"};
String randomName = names[getRandomNumber(names.length)]
Disparando certos eventos com uma certa probabilidade. A manhã de uma pessoa começa de acordo com os cenários possíveis: Dormiu demais – 50%; Acordei na hora certa – 40%; Acordei uma hora mais cedo do que o esperado – 10%. Imagine que você está escrevendo um emulador matinal humano. Você precisa desencadear eventos com uma certa probabilidade. Para fazer isso, novamente, você precisa usar um gerador de números aleatórios. As implementações podem ser diferentes, mas a mais simples deve seguir o seguinte algoritmo:
  1. definimos os limites dentro dos quais o número precisa ser gerado;
  2. gerar um número aleatório;
  3. Processamos o número resultante.
Então, nesse caso, o limite será 10. Vamos chamar o método getRandomNumber(10)e analisar o que ele pode nos retornar. Pode retornar 10 dígitos (de 0 a 9) e cada um com a mesma probabilidade - 10%. Agora precisamos combinar todos os resultados possíveis e combiná-los com os nossos eventos possíveis. Pode haver muitas combinações, dependendo da sua imaginação, mas a mais óbvia soa: “Se um número aleatório estiver dentro de [0..4] - chame o evento de “Sono demais”, se o número estiver dentro de [5..8 ] - “Acordar” na hora certa”, e somente se o número for 9, então “Acordei uma hora mais cedo do que o esperado”. Tudo é muito simples: dentro de [0..4] existem 5 números, cada um dos quais pode retornar com uma probabilidade de 10%, que no total será de 50%; dentro de [5..8] existem 4 números e 9 é o único número que aparece com probabilidade de 10%. No código, todo esse design inteligente parece ainda mais simples:
int randomNumber = getRandomNumber(10);
if (randomNumber < 5) {
    System.out.println("Проспал ");
} else if (randomNumber < 9) {
    System.out.println("Встал вовремя ");
} else {
    System.out.println("Встал на час раньше положенного ");
}
Em geral, pode haver muitas opções para usar números aleatórios. Tudo depende apenas da sua imaginação. Mas eles são usados ​​com mais eficácia se você precisar obter algum resultado repetidamente. Então este resultado será diferente do anterior. Com alguma probabilidade, é claro. Isso é tudo! Se você quiser saber mais sobre a seção Jogos, aqui estão algumas documentações úteis que podem ajudar:
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION