CodeGym /Blog Java /Aleatoriu /Secțiunea de jocuri pe CodeGym: teorie utilă
John Squirrels
Nivel
San Francisco

Secțiunea de jocuri pe CodeGym: teorie utilă

Publicat în grup
În secțiunea „Jocuri” de pe CodeGym, veți găsi proiecte interesante care implică scrierea unor jocuri populare pe computer. Doriți să vă creați propria versiune a popularelor jocuri 2048, Minesweeper, Snake și alte jocuri? E simplu. Am transformat scrierea jocurilor într-un proces pas cu pas. Secțiunea „Jocuri” de pe CodeGym: Teorie utilă - 1Pentru a-ți testa abilitățile ca dezvoltator de jocuri, nu trebuie să fii un programator avansat, dar este necesar un set specific de cunoștințe Java. Aici veți găsi informații care vă vor fi utile în scrierea jocurilor .

1. Moștenirea

Lucrul cu motorul de joc CodeGym implică utilizarea moștenirii. Dar dacă nu știi ce este asta? Pe de o parte, trebuie să înțelegeți acest subiect: este studiat la nivelul 11. Pe de altă parte, motorul a fost special conceput pentru a fi foarte simplu, astfel încât să poți scăpa de cunoștințe superficiale despre moștenire. Deci, ce este moștenirea? Pune foarte simplu, moștenirea este o relație între două clase. Unul dintre ei devine părinte, iar celălalt devine copil (descendent). Mai mult decât atât, clasa părinte poate nici măcar să nu știe că are descendenți. Cu alte cuvinte, nu câștigă niciun avantaj anume având descendenți. Dar moștenirea oferă unui descendent multe avantaje. Și cel mai important este că toate variabilele și metodele clasei părinte apar în descendent ca și cum codul clasei părinte a fost copiat în clasa descendentă. Aceasta nu este o descriere complet exactă, dar va fi suficientă pentru o înțelegere simplificată a moștenirii. Exemplul 1: Cea mai simplă moștenire.

public class Parent {

}
Clasa Child moștenește clasa Parent folosind cuvântul cheie extins .

public class Child extends Parent {

}
Exemplul 2: Utilizarea variabilelor clasei părinte.

public class Parent {

   public int age;
   public String name;
}
Clasa Child poate folosi variabilele de vârstă și nume ale clasei Părinte ca și cum ar fi fost declarate în clasa Părinte .

public class Child extends Parent {

   public void printInfo() {

     System.out.println(name+" "+age);
   }
}
Exemplul 3: Utilizarea metodelor clasei părinte.

public class Parent {

   public int age;
   public String name;

   public getName() {
      return name;
  }
}
Clasa Child poate folosi variabilele și metodele clasei Parent ca și cum ar fi fost declarate în clasa Child. În acest exemplu, folosim metoda getName() .

public class Child extends Parent {

   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}
Iată cum arată clasa Child pentru compilator:

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. Metode de suprascriere

Uneori există situații în care facem ca clasa noastră Child să moștenească o clasă Parent foarte utilă, împreună cu toate variabilele și metodele sale, dar unele dintre metode nu funcționează așa cum ne dorim noi. Sau deloc cum vrem noi. Ce putem face în această situație? Putem trece peste metoda care nu ne place. Acest lucru este foarte ușor de făcut: în clasa noastră Child, pur și simplu declarăm o metodă cu aceeași semnătură ca metoda din clasa Părinte și apoi scriem propriul cod în ea. Exemplul 1: Suprascrierea unei metode.

public class Parent {

   public String name;

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

   public getName() {
      return name;
  }
}
Metoda printInfo() va afișa „Luke, Nu!!!”

public class Child extends Parent{

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

   public void printInfo() {
      setName("Luke");
      System.out.println(getName());
   }
}
Iată cum arată clasa Child pentru compilator:

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());
   }
}
Exemplul 2: Unele magie de moștenire (și depășirea metodei).

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";
  }
}
În acest exemplu, dacă printInfometoda (din clasa Parent) nu este suprascrisă în clasa Child, atunci când această metodă este apelată pe un obiect Child, metoda getName()sa va fi apelată în locul metodei clasei Parent getName().

Parent parent = new Parent ();
parent.printnInfo();
Acest cod afișează „Luke” pe ecran.

Child child = new Child ();
child.printnInfo();
Acest cod afișează pe ecran „Luke, eu sunt tatăl tău” .
Iată cum arată clasa Child pentru compilator:

public class Child extends Parent {

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

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

3. Liste

Dacă nu ați întâlnit încă liste (Lista), iată o scurtă prezentare generală. Puteți găsi informații complete în Nivelurile 6-7 ale cursului CodeGym . Listele au multe în comun cu tablourile:
  • puteți stoca o mulțime de date de un anumit tip;
  • vă permit să obțineți articole după indexul lor;
  • indicii elementului încep de la 0.
Avantajele listelor: Spre deosebire de matrice, listele pot schimba dimensiunea în mod dinamic. Când este creată o listă, dimensiunea acesteia este 0. Pe măsură ce adăugați elemente la o listă, dimensiunea acesteia crește. Iată un exemplu de creare a unei liste:

ArrayList<String> myList = new ArrayList<String>(); // Create a new ArrayList
Valoarea dintre parantezele unghiulare indică tipul de date pe care lista îl poate stoca. Iată câteva metode de lucru cu lista:
Cod Scurtă descriere a ceea ce face codul
ArrayList<String> list = new ArrayList<String>(); Creați o nouă listă de șiruri
list.add("name"); Adăugați un element la sfârșitul listei
list.add(0, "name"); Adăugați un element la începutul listei
String name = list.get(5); Obțineți un element după indexul său
list.set(5, "new name"); Schimbați un element după indexul său
int count = list.size(); Obțineți numărul de elemente din listă
list.remove(4); Ștergeți un element din listă
Puteți afla mai multe despre liste din următoarele articole:
  1. Clasa ArrayList
  2. ArrayList în imagini
  3. Ștergerea unui element dintr-o ArrayList

4. Matrice

Ce este o matrice? O matrice nu este altceva decât un tabel dreptunghiular care poate fi umplut cu date. Cu alte cuvinte, este o matrice bidimensională. După cum probabil știți, matricele în Java sunt obiecte. O matrice standard unidimensională intarată astfel:

int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
O putem vizualiza astfel:
0 1 2 3 4 5 6 7
12 32 43 54 15 36 67 28
Rândul de sus indică adresele celulelor. Cu alte cuvinte, pentru a obține numărul 67, trebuie să accesați elementul de matrice cu indicele 6:

int number = array[6];
Totul este foarte simplu. O matrice bidimensională este o matrice de matrice unidimensionale. Dacă auziți despre asta pentru prima dată, opriți-vă și imaginați-vă în capul vostru. O matrice bidimensională arată astfel:
0 Matrice unidimensională Matrice unidimensională
1 Matrice unidimensională
2 Matrice unidimensională
3 Matrice unidimensională
4 Matrice unidimensională
5 Matrice unidimensională
6 Matrice unidimensională
7 Matrice unidimensională
În cod:

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
Pentru a obține valoarea 47, trebuie să vă referiți la elementul matricei la [4][2].

int number = matrix[4][2];
Poate ați observat că coordonatele matricei sunt diferite de sistemul de coordonate dreptunghiular clasic (sistemul de coordonate cartezian). Când accesați matricea, mai întâi specificați coordonatele y și apoi coordonatele x. În matematică, se obișnuiește să specificați mai întâi coordonatele x, adică (x, y). S-ar putea să vă întrebați: „Ei bine, de ce să nu rotiți reprezentarea matricei și apoi să accesați elementele în mod obișnuit folosind (x, y)? Făcând acest lucru nu ar schimba conținutul matricei”. Da, nimic nu s-ar schimba. Dar în lumea programării, practica acceptată este de a accesa matrice „întâi prin y, apoi prin x”. Ar trebui să accepți asta ca pe calea potrivită. Acum să vorbim despre proiectarea matricei la motorul nostru (Gameclasă). După cum știți, motorul are multe metode care modifică celulele terenului de joc la anumite coordonate. De exemplu, setCellValue(int x, int y, String value)metoda. Setează o celulă specifică cu coordonatele (x, y) egale cu parametrul valoare. Poate ați observat că această metodă ia mai întâi x, la fel ca în sistemul de coordonate clasic. Celelalte metode ale motorului funcționează în mod similar. Când dezvoltați jocuri, va fi adesea necesar să reproduceți starea unei matrice pe ecran. Cum facem asta? În primul rând, trebuie să iterați prin toate elementele matricei într-o buclă. În al doilea rând, apelați metoda de afișare pentru fiecare dintre ele, folosind coordonatele INVERSATE. De exemplu:

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]));
        }
    }
}
Desigur, inversarea funcționează în ambele direcții. Puteți trece (i, j) la setCellValuemetodă și, simultan, puteți lua elementul [j][i] din matrice. Inversarea coordonatelor poate părea puțin dificilă, dar trebuie să vă amintiți. Și întotdeauna, dacă întâmpinați probleme, ar trebui să luați o bucată de hârtie și un pix, să desenați matricea și să reproduceți procesele care implică matricea.

5. Numere aleatorii

Cum lucrezi cu un generator de numere aleatorii? Clasa Gamedefinește getRandomNumber(int)metoda. Sub capotă, folosește Randomclasa din pachetul java.util, dar modul în care lucrați cu generatorul de numere aleatorii nu se schimbă. getRandomNumber(int)ia un număr întreg ca argument. Acest număr va fi limita superioară a ceea ce poate returna generatorul. Limita inferioară este 0. Important! Generatorul nu va returna NICIODATĂ numărul limită superioară. De exemplu, dacă apelați getRandomNumber(3), va returna aleatoriu 0, 1 sau 2. După cum puteți vedea, nu poate returna 3. Utilizarea generatorului în acest mod este destul de simplă, dar foarte eficientă în multe cazuri. Să presupunem că trebuie să obțineți un număr aleatoriu într-un anumit interval: Imaginați-vă că aveți nevoie de un număr de trei cifre în intervalul [100..999]. După cum știți deja, numărul minim returnat este 0. Deci va trebui să adăugați 100. Dar, în acest caz, trebuie să aveți grijă să nu depășiți limita superioară. Pentru a obține 999 ca valoare maximă aleatorie, apelațigetRandomNumber(int)metoda cu argumentul 1000. Dar acum ne amintim că adăugăm 100 la rezultat: aceasta înseamnă că limita superioară ar trebui redusă cu 100. Cu alte cuvinte, codul pentru a obține numărul nostru aleatoriu de trei cifre va arăta astfel :

int number = 100 + getRandomNumber(900);
Dar pentru a simplifica această procedură, motorul oferă metoda getRandomNumber(int, int)al cărei prim parametru este numărul minim de returnat. Folosind această metodă, exemplul anterior poate fi rescris după cum urmează:

int number = getRandomNumber(100, 1000);
Numerele aleatoare pot fi folosite pentru a obține un element de matrice aleatoriu:

String [] names = {"Sarah", "Val", "Sergey"};
String randomName = names[getRandomNumber(names.length)]
Generarea anumitor evenimente cu o oarecare probabilitate. Pentru oameni, diminețile încep cu câteva scenarii posibile: adormit excesiv – șanse de 50%; M-am trezit la timp – șanse de 40%; M-am trezit cu o oră mai devreme – șanse de 10%. Imaginați-vă că scrieți un generator de rezultate de dimineață. Trebuie să generați evenimente cu o anumită probabilitate. Pentru a face acest lucru, trebuie să utilizați din nou un generator de numere aleatorii. Sunt posibile implementări diferite, dar cele mai simple ar trebui să se bazeze pe următorul algoritm:
  1. stabiliți limitele folosite pentru a genera un număr;
  2. generează un număr aleator;
  3. procesează numărul obţinut.
În acest caz, maximul va fi 10. Apelați lagetRandomNumber(10)metoda și analizați că o putem întoarce. Poate returna 10 numere (de la 0 la 9), fiecare cu aceeași probabilitate - 10%. Acum trebuie să combinăm toate rezultatele posibile și să le mapam cu posibilele noastre evenimente. Imaginația ta poate gândi o mulțime de combinații posibile, dar iată cea mai evidentă: „Dacă numărul aleatoriu este în intervalul [0..4], avem evenimentul „Overslept”; dacă numărul este în intervalul [5 ..8], avem evenimentul „Trezit la timp”; iar dacă numărul este 9, atunci avem evenimentul „Trezit cu o oră mai devreme”. Totul este foarte simplu. Sunt 5 numere în intervalul [0 ..4], dintre care fiecare poate fi returnat cu o probabilitate de 10%, pentru un total de 50%; sunt 4 numere în intervalul [5..8], ei bine, iar 9 este doar un număr care apare cu o probabilitate de 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");
}
În general, există o mulțime de moduri de a folosi numere aleatorii. Ești limitat doar de imaginația ta. Dar ele sunt utilizate cel mai eficient dacă trebuie să obțineți în mod repetat un rezultat. Atunci noul rezultat va fi diferit de cel anterior. Cu o oarecare probabilitate, desigur. Asta este tot pentru acum! Dacă doriți să aflați mai multe despre secțiunea „Jocuri”, iată o documentație utilă care vă poate ajuta:
Comentarii
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION