CodeGym /Java Blog /Random-IT /Sezione giochi su CodeGym: Teoria utile
John Squirrels
Livello 41
San Francisco

Sezione giochi su CodeGym: Teoria utile

Pubblicato nel gruppo Random-IT
Nella sezione "Giochi" di CodeGym troverai progetti entusiasmanti che prevedono la scrittura di famosi giochi per computer. Vuoi creare la tua versione dei popolari giochi 2048, Minesweeper, Snake e altri giochi? È semplice. Abbiamo trasformato la scrittura di giochi in un processo graduale. Sezione "Giochi" su CodeGym: Teoria utile - 1Per mettere alla prova le tue capacità di sviluppatore di giochi, non devi essere un programmatore avanzato, ma è necessario un insieme specifico di conoscenze Java. Qui troverai informazioni che ti saranno utili nella scrittura del gioco .

1. Ereditarietà

Lavorare con il motore di gioco CodeGym comporta l'utilizzo dell'ereditarietà. Ma cosa succede se non sai cos'è? Da un lato, devi capire questo argomento: è studiato al livello 11. D'altra parte, il motore è stato appositamente progettato per essere molto semplice, quindi puoi farla franca con una conoscenza superficiale dell'ereditarietà. Quindi cos'è l'eredità? In parole povere, l'ereditarietà è una relazione tra due classi. Uno di loro diventa il genitore e l'altro diventa un figlio (discendente). Inoltre, la classe genitore potrebbe anche non sapere di avere discendenti. In altre parole, non trae alcun vantaggio particolare dall'avere discendenti. Ma l'eredità offre molti vantaggi a un discendente. E il più importante è che tutte le variabili ei metodi della classe genitore appaiono nel discendente come se il codice della classe genitore fosse stato copiato nella classe discendente. Questa non è una descrizione del tutto accurata, ma sarà sufficiente per una comprensione semplificata dell'ereditarietà. Esempio 1: L'eredità più semplice.

public class Parent {

}
La classe Child eredita la classe Parent utilizzando la parola chiave extends .

public class Child extends Parent {

}
Esempio 2: utilizzo delle variabili della classe genitore.

public class Parent {

   public int age;
   public String name;
}
La classe Child può usare le variabili age e name della classe Parent come se fossero dichiarate nella classe Parent .

public class Child extends Parent {

   public void printInfo() {

     System.out.println(name+" "+age);
   }
}
Esempio 3: utilizzo dei metodi della classe genitore.

public class Parent {

   public int age;
   public String name;

   public getName() {
      return name;
  }
}
La classe Child può utilizzare le variabili ei metodi della classe Parent come se fossero dichiarati nella classe Child. In questo esempio, utilizziamo il metodo getName() .

public class Child extends Parent {

   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}
Ecco come appare la classe Child al compilatore:

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. Metodi di override

A volte ci sono situazioni in cui facciamo ereditare alla nostra classe Child una classe Parent molto utile, insieme a tutte le sue variabili e metodi, ma alcuni metodi non funzionano esattamente come vorremmo. O per niente come vorremmo che lo facessero. Cosa possiamo fare in questa situazione? Possiamo sovrascrivere il metodo che non ci piace. Questo è molto facile da fare: nella nostra classe Child, dichiariamo semplicemente un metodo con la stessa firma del metodo nella classe Parent, e poi scriviamo il nostro codice al suo interno. Esempio 1: sostituzione di un metodo.

public class Parent {

   public String name;

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

   public getName() {
      return name;
  }
}
Il metodo printInfo() visualizzerà "Luke, No!!!"

public class Child extends Parent{

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

   public void printInfo() {
      setName("Luke");
      System.out.println(getName());
   }
}
Ecco come appare la classe Child al compilatore:

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());
   }
}
Esempio 2: alcune magie di ereditarietà (e override del metodo).

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";
  }
}
In questo esempio, se il printInfometodo (della classe Parent) non viene sovrascritto nella classe Child, quando questo metodo viene chiamato su un oggetto Child, getName()verrà chiamato il suo metodo invece del getName()metodo della classe Parent.

Parent parent = new Parent ();
parent.printnInfo();
Questo codice visualizza "Luke" sullo schermo.

Child child = new Child ();
child.printnInfo();
Questo codice visualizza "Luke, io sono tuo padre" sullo schermo.
Ecco come appare la classe Child al compilatore:

public class Child extends Parent {

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

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

3. Liste

Se non hai ancora incontrato le liste (Lista), ecco una breve panoramica. Puoi trovare informazioni complete nei livelli 6-7 del corso CodeGym . Le liste hanno molto in comune con gli array:
  • puoi memorizzare molti dati di un tipo specifico;
  • ti permettono di ottenere gli elementi in base al loro indice;
  • gli indici degli elementi iniziano da 0.
Vantaggi degli elenchi: a differenza degli array, gli elenchi possono cambiare dimensione in modo dinamico. Quando viene creato un elenco, la sua dimensione è 0. Man mano che aggiungi elementi a un elenco, la sua dimensione aumenta. Ecco un esempio di creazione di un elenco:

ArrayList<String> myList = new ArrayList<String>(); // Create a new ArrayList
Il valore tra parentesi angolari indica il tipo di dati che l'elenco può memorizzare. Ecco alcuni metodi per lavorare con l'elenco:
Codice Breve descrizione di cosa fa il codice
ArrayList<String> list = new ArrayList<String>(); Crea un nuovo elenco di stringhe
list.add("name"); Aggiungi un elemento alla fine dell'elenco
list.add(0, "name"); Aggiungi un elemento all'inizio dell'elenco
String name = list.get(5); Ottieni un elemento dal suo indice
list.set(5, "new name"); Cambia un elemento in base al suo indice
int count = list.size(); Ottieni il numero di elementi nell'elenco
list.remove(4); Elimina un elemento dall'elenco
Puoi saperne di più sugli elenchi dai seguenti articoli:
  1. Classe ArrayList
  2. ArrayList nelle immagini
  3. Eliminazione di un elemento da un ArrayList

4. Matrici

Cos'è una matrice? Una matrice non è altro che una tabella rettangolare che può essere riempita di dati. In altre parole, è un array bidimensionale. Come probabilmente saprai, gli array in Java sono oggetti. Un array unidimensionale standard intsi presenta così:

int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
Possiamo visualizzarlo così:
0 1 2 3 4 5 6 7
12 32 43 54 15 36 67 28
La riga superiore indica gli indirizzi delle celle. In altre parole, per ottenere il numero 67, è necessario accedere all'elemento dell'array con indice 6:

int number = array[6];
È tutto molto semplice. Un array bidimensionale è un array di array unidimensionali. Se ne senti parlare per la prima volta, fermati e immaginalo nella tua testa. Un array bidimensionale ha questo aspetto:
0 Matrice unidimensionale Matrice unidimensionale
1 Matrice unidimensionale
2 Matrice unidimensionale
3 Matrice unidimensionale
4 Matrice unidimensionale
5 Matrice unidimensionale
6 Matrice unidimensionale
7 Matrice unidimensionale
Nel codice:

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
Per ottenere il valore 47, è necessario fare riferimento all'elemento della matrice in [4][2].

int number = matrix[4][2];
Potresti aver notato che le coordinate della matrice sono diverse dal classico sistema di coordinate rettangolari (sistema di coordinate cartesiane). Quando si accede alla matrice, si specifica prima la coordinata y e poi la coordinata x. In matematica, è consuetudine specificare prima la coordinata x, cioè (x, y). Forse ti starai chiedendo: "Beh, perché non ruotare la tua rappresentazione della matrice e quindi accedere agli elementi nel solito modo usando (x, y)? Facendo questo non cambierebbe il contenuto della matrice". Sì, non cambierebbe nulla. Ma nel mondo della programmazione, la pratica accettata è quella di accedere alle matrici "prima per y, poi per x". Dovresti accettare questo come il modo corretto. Ora parliamo della proiezione della matrice sul nostro motore (Gameclasse). Come sai, il motore ha molti metodi che cambiano le celle del campo di gioco a coordinate specifiche. Ad esempio, il setCellValue(int x, int y, String value)metodo. Imposta una cella specifica con coordinate (x, y) uguali al parametro value. Potresti aver notato che questo metodo richiede prima x, proprio come nel classico sistema di coordinate. Gli altri metodi del motore funzionano in modo simile. Durante lo sviluppo di giochi, sarà spesso necessario riprodurre sullo schermo lo stato di una matrice. Come lo facciamo? Innanzitutto, devi scorrere tutti gli elementi della matrice in un ciclo. In secondo luogo, chiama il metodo di visualizzazione per ciascuno di essi, utilizzando le coordinate REVERSED. Per esempio:

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, l'inversione funziona in entrambe le direzioni. Puoi passare (i, j) al setCellValuemetodo e contemporaneamente prendere l'elemento [j][i] dalla matrice. Invertire le coordinate può sembrare un po' difficile, ma devi ricordartelo. E sempre, se incontri qualche problema, dovresti prendere un pezzo di carta e una penna, disegnare la matrice e riprodurre i processi che coinvolgono la matrice.

5. Numeri casuali

Come lavori con un generatore di numeri casuali? La Gameclasse definisce il getRandomNumber(int)metodo. Sotto il cofano, utilizza la Randomclasse del pacchetto java.util, ma il modo in cui lavori con il generatore di numeri casuali non cambia. getRandomNumber(int)accetta un numero intero come argomento. Questo numero sarà il limite massimo su ciò che il generatore può restituire. Il limite inferiore è 0. Importante! Il generatore non restituirà MAI il numero limite superiore. Ad esempio, se chiami getRandomNumber(3), restituirà casualmente 0, 1 o 2. Come puoi vedere, non può restituire 3. Usare il generatore in questo modo è abbastanza semplice, ma molto efficace in molti casi. Supponiamo di dover ottenere un numero casuale in un intervallo: immagina di aver bisogno di un numero di tre cifre nell'intervallo [100..999]. Come già sai, il numero minimo restituito è 0. Quindi dovrai aggiungere 100. Ma in questo caso, devi fare attenzione a non superare il limite massimo. Per ottenere 999 come valore casuale massimo, chiama thegetRandomNumber(int)metodo con l'argomento 1000. Ma ora ricordiamo che stiamo aggiungendo 100 al risultato: ciò significa che il limite superiore dovrebbe essere ridotto di 100. In altre parole, il codice per ottenere il nostro numero casuale di tre cifre sarà simile a questo :

int number = 100 + getRandomNumber(900);
Ma per semplificare questa procedura, il motore fornisce il getRandomNumber(int, int)metodo il cui primo parametro è il numero minimo da restituire. Utilizzando questo metodo, l'esempio precedente può essere riscritto come segue:

int number = getRandomNumber(100, 1000);
I numeri casuali possono essere utilizzati per ottenere un elemento dell'array casuale:

String [] names = {"Sarah", "Val", "Sergey"};
String randomName = names[getRandomNumber(names.length)]
Generazione di determinati eventi con una certa probabilità. Per gli umani, le mattine iniziano con alcuni possibili scenari: Dormito troppo – 50% di possibilità; Svegliato in orario – 40% di possibilità; Mi sono svegliato un'ora prima: 10% di possibilità. Immagina di scrivere un generatore di risultati mattutini. Devi generare eventi con una certa probabilità. Per fare ciò, devi nuovamente utilizzare un generatore di numeri casuali. Sono possibili diverse implementazioni, ma la più semplice dovrebbe basarsi sul seguente algoritmo:
  1. impostare i limiti utilizzati per generare un numero;
  2. generare un numero casuale;
  3. elaborare il numero ottenuto.
In questo caso, il massimo sarà 10. Chiama ilgetRandomNumber(10)metodo e analizzare che possiamo tornare. Può restituire 10 numeri (da 0 a 9), ciascuno con la stessa probabilità: 10%. Ora dobbiamo combinare tutti i possibili risultati e mapparli ai nostri possibili eventi. La tua immaginazione potrebbe pensare a molte combinazioni possibili, ma ecco la più ovvia: "Se il numero casuale è nell'intervallo [0..4], abbiamo l'evento "Overslept"; se il numero è nell'intervallo [5 ..8], abbiamo l'evento "Svegliato in orario" e se il numero è 9, allora abbiamo l'evento "Svegliato un'ora prima". È tutto molto semplice. Ci sono 5 numeri nell'intervallo [0 ..4], ognuno dei quali può essere restituito con una probabilità del 10%, per un totale del 50%; ci sono 4 numeri nell'intervallo [5..8], beh, e 9 è solo un numero che appare con una probabilità del 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");
}
In generale, ci sono tantissimi modi per usare i numeri casuali. Sei limitato solo dalla tua immaginazione. Ma sono utilizzati in modo più efficace se è necessario ottenere ripetutamente qualche risultato. Quindi il nuovo risultato sarà diverso dal precedente. Con una certa probabilità, ovviamente. È tutto per ora! Se vuoi saperne di più sulla sezione "Giochi", ecco una documentazione utile che può aiutarti:
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION