CodeGym /Java-blogg /Tilfeldig /Spillseksjonen på CodeGym: Nyttig teori
John Squirrels
Nivå
San Francisco

Spillseksjonen på CodeGym: Nyttig teori

Publisert i gruppen
I «Spill»-delen på CodeGym finner du spennende prosjekter som innebærer å skrive populære dataspill. Vil du lage din egen versjon av de populære spillene 2048, Minesveiper, Snake og andre spill? Det er enkelt. Vi har gjort spillskriving til en trinn-for-trinn-prosess. "Spill"-delen på CodeGym: Nyttig teori - 1For å teste evnene dine som spillutvikler trenger du ikke å være en avansert programmerer, men et spesifikt sett med Java-kunnskap er nødvendig. Her finner du informasjon som vil være nyttig i spillskriving .

1. Arv

Å jobbe med CodeGym-spillmotoren innebærer bruk av arv. Men hva om du ikke vet hva det er? På den ene siden må du forstå dette emnet: det studeres på nivå 11. På den annen side er motoren spesialdesignet for å være veldig enkel, slik at du kan slippe unna med overfladisk kunnskap om arv. Så hva er arv? Enkelt sagt er arv et forhold mellom to klasser. En av dem blir forelder, og den andre blir et barn (etterkommer). Dessuten kan det hende at foreldreklassen ikke en gang vet at den har etterkommere. Den får med andre ord ingen særlig fordel ved å ha etterkommere. Men arv gir en etterkommer mange fordeler. Og den viktigste er at alle foreldreklassens variabler og metoder vises i etterkommeren som om koden til overordnet klasse ble kopiert til etterkommerklassen. Dette er ikke en helt nøyaktig beskrivelse, men det vil være tilstrekkelig for en forenklet forståelse av arv. Eksempel 1: Den enkleste arven.

public class Parent {

}
Child - klassen arver Parent- klassen ved å bruke nøkkelordet extends .

public class Child extends Parent {

}
Eksempel 2: Bruk av foreldreklassens variabler.

public class Parent {

   public int age;
   public String name;
}
Barneklassen kan bruke foreldreklassens alders- og navnevariabler som om de var deklarert i foreldreklassen .

public class Child extends Parent {

   public void printInfo() {

     System.out.println(name+" "+age);
   }
}
Eksempel 3: Bruk av foreldreklassens metoder.

public class Parent {

   public int age;
   public String name;

   public getName() {
      return name;
  }
}
Child - klassen kan bruke Parent- klassens variabler og metoder som om de var deklarert i Child-klassen. I dette eksemplet bruker vi metoden getName() .

public class Child extends Parent {

   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}
Slik ser Child -klassen ut for kompilatoren:

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. Overordnede metoder

Noen ganger er det situasjoner der vi får barneklassen vår til å arve en veldig nyttig overordnet klasse, sammen med alle dens variabler og metoder, men noen av metodene fungerer ikke helt slik vi vil at de skal. Eller ikke i det hele tatt slik vi vil ha dem. Hva kan vi gjøre i denne situasjonen? Vi kan overstyre metoden vi ikke liker. Dette er veldig enkelt å gjøre: i Child-klassen vår erklærer vi ganske enkelt en metode med samme signatur som metoden i Parent-klassen, og så skriver vi vår egen kode i den. Eksempel 1: Overstyre en metode.

public class Parent {

   public String name;

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

   public getName() {
      return name;
  }
}
PrintInfo()-metoden vil vise "Luke, Nei!!!"

public class Child extends Parent{

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

   public void printInfo() {
      setName("Luke");
      System.out.println(getName());
   }
}
Slik ser Child -klassen ut for kompilatoren:

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());
   }
}
Eksempel 2: Noe arvemagi (og metodeoverstyring).

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";
  }
}
I dette eksemplet, hvis printInfometoden (fra Parent-klassen) ikke overstyres i Child-klassen, når denne metoden kalles på et Child-objekt, getName()vil metoden kalles i stedet for Parent-klassens getName()metode.

Parent parent = new Parent ();
parent.printnInfo();
Denne koden viser "Luke" på skjermen.

Child child = new Child ();
child.printnInfo();
Denne koden viser "Luke, jeg er din far" på skjermen.
Slik ser Child -klassen ut for kompilatoren:

public class Child extends Parent {

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

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

3. Lister

Hvis du ennå ikke har møtt lister (List), her er en kort oversikt. Du finner fullstendig informasjon på nivå 6-7 på CodeGym-kurset . Lister har mye til felles med matriser:
  • du kan lagre mye data av en bestemt type;
  • de lar deg få varer etter indeksen deres;
  • elementindekser starter fra 0.
Fordeler med lister: I motsetning til matriser kan lister endre størrelse dynamisk. Når en liste opprettes, er størrelsen 0. Når du legger til elementer i en liste, øker størrelsen. Her er et eksempel på hvordan du lager en liste:

ArrayList<String> myList = new ArrayList<String>(); // Create a new ArrayList
Verdien i vinkelparentesene indikerer datatypen som listen kan lagre. Her er noen metoder for å jobbe med listen:
Kode Kort beskrivelse av hva koden gjør
ArrayList<String> list = new ArrayList<String>(); Lag ny liste over strenger
list.add("name"); Legg til et element på slutten av listen
list.add(0, "name"); Legg til et element i begynnelsen av listen
String name = list.get(5); Få et element etter indeksen
list.set(5, "new name"); Endre et element etter indeksen
int count = list.size(); Få antall elementer i listen
list.remove(4); Slett et element fra listen
Du kan lære mer om lister fra følgende artikler:
  1. ArrayList klasse
  2. ArrayList i bilder
  3. Slette et element fra en ArrayList

4. Matriser

Hva er en matrise? En matrise er ikke annet enn en rektangulær tabell som kan fylles med data. Med andre ord, det er en todimensjonal matrise. Som du sikkert vet, er arrays i Java objekter. En standard endimensjonal intmatrise ser slik ut:

int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
Vi kan visualisere det slik:
0 1 2 3 4 5 6 7
12 32 43 54 15 36 67 28
Den øverste raden angir adressene til cellene. Med andre ord, for å få tallet 67, må du få tilgang til array-elementet med indeks 6:

int number = array[6];
Det hele er veldig enkelt. En todimensjonal matrise er en matrise med endimensjonale matriser. Hvis du hører om dette for første gang, stopp og forestill deg det i hodet ditt. En todimensjonal matrise ser slik ut:
0 En-dimensjonal matrise Endimensjonal matrise
1 Endimensjonal matrise
2 Endimensjonal matrise
3 Endimensjonal matrise
4 Endimensjonal matrise
5 Endimensjonal matrise
6 Endimensjonal matrise
7 Endimensjonal matrise
I koden:

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 1. 3 90 78 98 14 78
7 0 1 2 3 4 5 6 7
20 18 74 91 96 104 105 77
For å få verdien 47, må du referere til matriseelementet ved [4][2].

int number = matrix[4][2];
Du har kanskje lagt merke til at matrisekoordinatene er forskjellige fra det klassiske rektangulære koordinatsystemet (kartesisk koordinatsystem). Når du får tilgang til matrisen, spesifiserer du først y-koordinaten og deretter x-koordinaten. I matematikk er det vanlig å angi x-koordinaten først, altså (x, y). Du lurer kanskje: "Vel, hvorfor ikke rotere representasjonen av matrisen og deretter få tilgang til elementene på vanlig måte ved å bruke (x, y)? Hvis du gjør dette, vil ikke innholdet i matrisen endres". Ja, ingenting ville endre seg. Men i programmeringsverdenen er den aksepterte praksisen å få tilgang til matriser "først av y, så av x". Du bør akseptere dette som den riktige måten. La oss nå snakke om å projisere matrisen til motoren vår (Gameklasse). Som du vet, har motoren mange metoder som endrer cellene på spillefeltet ved spesifikke koordinater. For eksempel setCellValue(int x, int y, String value)metoden. Den setter en spesifikk celle med koordinater (x, y) lik verdiparameteren. Du har kanskje lagt merke til at denne metoden tar x først, akkurat som i det klassiske koordinatsystemet. Motorens andre metoder fungerer på lignende måte. Ved utvikling av spill vil det ofte være nødvendig å gjengi tilstanden til en matrise på skjermen. Hvordan gjør vi det? Først må du iterere gjennom alle matriseelementene i en løkke. For det andre kaller du visningsmetoden for hver av dem ved å bruke REVERSE koordinater. For eksempel:

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]));
        }
    }
}
Naturligvis virker reverseringen i begge retninger. Du kan sende (i, j) til setCellValuemetoden og samtidig ta element [j][i] fra matrisen. Å snu koordinatene kan virke litt vanskelig, men du må huske det. Og alltid, hvis du støter på problemer, bør du ta et stykke papir og en penn, tegne matrisen og reprodusere prosessene som involverer matrisen.

5. Tilfeldige tall

Hvordan jobber du med en tilfeldig tallgenerator? Klassen Gamedefinerer getRandomNumber(int)metoden. Under panseret bruker den Randomklassen fra java.util-pakken, men måten du jobber med tilfeldig tallgeneratoren endres ikke på. getRandomNumber(int)tar et heltall som et argument. Dette tallet vil være den øvre grensen for hva generatoren kan returnere. Nedre grense er 0. Viktig! Generatoren vil ALDRI returnere det øvre grensenummeret. For eksempel, hvis du ringer getRandomNumber(3), vil den tilfeldig returnere 0, 1 eller 2. Som du kan se, kan den ikke returnere 3. Å bruke generatoren på denne måten er ganske enkelt, men svært effektivt i mange tilfeller. Anta at du trenger å få et tilfeldig tall i et eller annet område: Tenk deg at du trenger et tresifret tall i området [100..999]. Som du allerede vet, er minimumstallet returnert 0. Så du må legge til 100. Men i dette tilfellet må du passe på å ikke overskride den øvre grensen. For å få 999 som maksimal tilfeldig verdi, ringgetRandomNumber(int)metode med argumentet 1000. Men nå husker vi at vi legger til 100 til resultatet: dette betyr at den øvre grensen skal reduseres med 100. Med andre ord vil koden for å få vårt tilfeldige tresifrede tall se slik ut :

int number = 100 + getRandomNumber(900);
Men for å forenkle denne prosedyren, gir motoren metoden getRandomNumber(int, int)hvis første parameter er minimumstallet som skal returneres. Ved å bruke denne metoden kan det forrige eksemplet skrives om som følger:

int number = getRandomNumber(100, 1000);
Tilfeldige tall kan brukes for å få et tilfeldig matriseelement:

String [] names = {"Sarah", "Val", "Sergey"};
String randomName = names[getRandomNumber(names.length)]
Genererer visse hendelser med en viss sannsynlighet. For mennesker begynner morgenen med noen få mulige scenarier: Forsov – 50 % sjanse; Våknet i tide – 40 % sjanse; Våknet en time for tidlig – 10 % sjanse. Tenk deg at du skriver en morgenresultatgenerator. Du må generere hendelser med en viss sannsynlighet. For å gjøre dette må du igjen bruke en tilfeldig tallgenerator. Ulike implementeringer er mulige, men den enkleste bør være basert på følgende algoritme:
  1. angi grensene som brukes til å generere et tall;
  2. generere et tilfeldig tall;
  3. behandle det oppnådde nummeret.
I dette tilfellet vil maksimum være 10. RinggetRandomNumber(10)metode og analysere at det kan vi returnere. Den kan returnere 10 tall (fra 0 til 9), hver med samme sannsynlighet - 10%. Nå må vi kombinere alle mulige resultater og kartlegge dem til våre mulige arrangementer. Fantasien din kan tenke opp mange mulige kombinasjoner, men her er den mest åpenbare: "Hvis det tilfeldige tallet er i området [0..4], har vi hendelsen "Overslept"; hvis tallet er i området [5] ..8], har vi «Våknet i tide»-hendelsen; og hvis tallet er 9, så har vi «Våknet en time for tidlig»-hendelsen. Det hele er veldig enkelt. Det er 5 tall i området [0] ..4], som hver kan returneres med en sannsynlighet på 10 %, for totalt 50 %; det er 4 tall i området [5..8], vel, og 9 er bare ett tall som vises med en sannsynlighet på 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");
}
Generelt er det mange måter å bruke tilfeldige tall på. Du er bare begrenset av fantasien din. Men de brukes mest effektivt hvis du gjentatte ganger trenger å få et resultat. Da vil det nye resultatet være annerledes enn det forrige. Med en viss sannsynlighet, selvfølgelig. Det er alt for nå! Hvis du vil lære mer om "Spill"-delen, er her litt nyttig dokumentasjon som kan hjelpe:
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION