CodeGym /Blog Java /rawak /Bahagian permainan pada CodeGym: Teori berguna
John Squirrels
Tahap
San Francisco

Bahagian permainan pada CodeGym: Teori berguna

Diterbitkan dalam kumpulan
Dalam bahagian "Permainan" di CodeGym, anda akan menemui projek menarik yang melibatkan penulisan permainan komputer yang popular. Mahu mencipta versi anda sendiri bagi permainan popular 2048, Minesweeper, Snake dan permainan lain? Mudah sahaja. Kami telah mengubah penulisan permainan menjadi proses langkah demi langkah. Bahagian "Permainan" pada CodeGym: Teori berguna - 1Untuk menguji kebolehan anda sebagai pembangun permainan, anda tidak perlu menjadi pengaturcara lanjutan, tetapi set pengetahuan Java yang khusus diperlukan. Di sini anda akan menemui maklumat yang berguna dalam penulisan permainan .

1. Warisan

Bekerja dengan enjin permainan CodeGym melibatkan penggunaan warisan. Tetapi bagaimana jika anda tidak tahu apa itu? Di satu pihak, anda perlu memahami topik ini: ia dipelajari di Tahap 11. Sebaliknya, enjin itu direka khas untuk menjadi sangat mudah, jadi anda boleh lari dengan pengetahuan cetek tentang warisan. Jadi apa itu warisan? Secara ringkasnya, warisan ialah hubungan antara dua kelas. Seorang daripada mereka menjadi ibu bapa, dan seorang lagi menjadi anak (keturunan). Lebih-lebih lagi, kelas induk mungkin tidak tahu bahawa ia mempunyai keturunan. Dalam erti kata lain, ia tidak mendapat apa-apa kelebihan tertentu dengan mempunyai keturunan. Tetapi warisan memberi banyak kelebihan kepada keturunan. Dan yang paling penting ialah semua pembolehubah dan kaedah kelas induk muncul dalam keturunan seolah-olah kod kelas induk telah disalin ke kelas keturunan. Ini bukanlah huraian yang tepat sepenuhnya, tetapi ia akan mencukupi untuk pemahaman yang dipermudahkan tentang warisan. Contoh 1: Warisan yang paling mudah.

public class Parent {

}
Kelas Anak mewarisi kelas Induk menggunakan kata kunci lanjutan .

public class Child extends Parent {

}
Contoh 2: Menggunakan pembolehubah kelas induk.

public class Parent {

   public int age;
   public String name;
}
Kelas Anak boleh menggunakan pembolehubah umur dan nama kelas Induk seolah - olah ia diisytiharkan dalam kelas Induk .

public class Child extends Parent {

   public void printInfo() {

     System.out.println(name+" "+age);
   }
}
Contoh 3: Menggunakan kaedah kelas induk.

public class Parent {

   public int age;
   public String name;

   public getName() {
      return name;
  }
}
Kelas Kanak -kanak boleh menggunakan pembolehubah dan kaedah kelas Induk seolah-olah ia diisytiharkan dalam kelas Anak. Dalam contoh ini, kami menggunakan kaedah getName() .

public class Child extends Parent {

   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}
Inilah rupa kelas Kanak-kanak kepada pengkompil:

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. Kaedah mengatasi

Kadangkala terdapat situasi di mana kami menjadikan kelas Anak kami mewarisi beberapa kelas Induk yang sangat berguna, bersama dengan semua pembolehubah dan kaedahnya, tetapi beberapa kaedah tidak berfungsi seperti yang kami mahukannya. Atau tidak sama sekali seperti yang kita mahukan. Apa yang boleh kita lakukan dalam keadaan ini? Kita boleh mengatasi kaedah yang kita tidak suka. Ini sangat mudah dilakukan: dalam kelas Anak kami, kami hanya mengisytiharkan kaedah dengan tandatangan yang sama seperti kaedah dalam kelas Induk, dan kemudian kami menulis kod kami sendiri di dalamnya. Contoh 1: Mengatasi kaedah.

public class Parent {

   public String name;

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

   public getName() {
      return name;
  }
}
Kaedah printInfo() akan memaparkan "Lukas, Tidak!!!"

public class Child extends Parent{

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

   public void printInfo() {
      setName("Luke");
      System.out.println(getName());
   }
}
Inilah rupa kelas Kanak-kanak kepada pengkompil:

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());
   }
}
Contoh 2: Beberapa sihir warisan (dan kaedah mengatasi).

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";
  }
}
Dalam contoh ini, jika printInfokaedah (dari kelas Induk) tidak ditindih dalam kelas Anak, apabila kaedah ini dipanggil pada objek Anak, kaedahnya getName()akan dipanggil dan bukannya getName()kaedah kelas Induk.

Parent parent = new Parent ();
parent.printnInfo();
Kod ini memaparkan "Lukas" pada skrin.

Child child = new Child ();
child.printnInfo();
Kod ini memaparkan "Luke, saya bapa kamu" pada skrin.
Inilah rupa kelas Kanak-kanak kepada pengkompil:

public class Child extends Parent {

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

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

3. Senarai

Jika anda masih belum menemui senarai (Senarai), berikut ialah gambaran keseluruhan ringkas. Anda boleh mendapatkan maklumat lengkap dalam Tahap 6-7 kursus CodeGym . Senarai mempunyai banyak persamaan dengan tatasusunan:
  • anda boleh menyimpan banyak data daripada jenis tertentu;
  • mereka membenarkan anda mendapatkan item mengikut indeks mereka;
  • indeks elemen bermula dari 0.
Faedah senarai: Tidak seperti tatasusunan, senarai boleh menukar saiz secara dinamik. Apabila senarai dibuat, saiznya ialah 0. Apabila anda menambah item pada senarai, saiznya bertambah. Berikut ialah contoh membuat senarai:

ArrayList<String> myList = new ArrayList<String>(); // Create a new ArrayList
Nilai dalam kurungan sudut menunjukkan jenis data yang boleh disimpan oleh senarai. Berikut ialah beberapa kaedah untuk bekerja dengan senarai:
Kod Penerangan ringkas tentang apa yang dilakukan oleh kod
ArrayList<String> list = new ArrayList<String>(); Buat senarai rentetan baharu
list.add("name"); Tambahkan elemen pada penghujung senarai
list.add(0, "name"); Tambahkan elemen pada permulaan senarai
String name = list.get(5); Dapatkan elemen mengikut indeksnya
list.set(5, "new name"); Tukar elemen dengan indeksnya
int count = list.size(); Dapatkan bilangan elemen dalam senarai
list.remove(4); Padamkan elemen daripada senarai
Anda boleh mengetahui lebih lanjut tentang senarai daripada artikel berikut:
  1. Kelas ArrayList
  2. ArrayList dalam gambar
  3. Memadamkan elemen daripada ArrayList

4. Tatasusunan

Apakah matriks? Matriks tidak lebih daripada jadual segi empat tepat yang boleh diisi dengan data. Dalam erti kata lain, ia adalah tatasusunan dua dimensi. Seperti yang anda ketahui, tatasusunan dalam Java adalah objek. Tatasusunan satu dimensi standard intkelihatan seperti ini:

int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
Kita boleh memvisualisasikannya seperti ini:
0 1 2 3 4 5 6 7
12 32 43 54 15 36 67 28
Baris atas menunjukkan alamat sel. Dengan kata lain, untuk mendapatkan nombor 67, anda perlu mengakses elemen tatasusunan dengan indeks 6:

int number = array[6];
Semuanya sangat mudah. Tatasusunan dua dimensi ialah tatasusunan tatasusunan satu dimensi. Jika anda mendengar tentang perkara ini buat kali pertama, berhenti dan bayangkan dalam kepala anda. Tatasusunan dua dimensi kelihatan seperti ini:
0 Tatasusunan satu dimensi Tatasusunan satu dimensi
1 Tatasusunan satu dimensi
2 Tatasusunan satu dimensi
3 Tatasusunan satu dimensi
4 Tatasusunan satu dimensi
5 Tatasusunan satu dimensi
6 Tatasusunan satu dimensi
7 Tatasusunan satu dimensi
Dalam kod:

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
Untuk mendapatkan nilai 47, anda perlu merujuk kepada elemen matriks di [4][2].

int number = matrix[4][2];
Anda mungkin perasan bahawa koordinat matriks adalah berbeza daripada sistem koordinat segi empat tepat klasik (sistem koordinat Cartesian). Apabila anda mengakses matriks, anda mula-mula menentukan koordinat y dan kemudian koordinat x. Dalam matematik, adalah kebiasaan untuk menentukan koordinat x dahulu, iaitu (x, y). Anda mungkin tertanya-tanya: "Nah, mengapa tidak putar perwakilan matriks anda dan kemudian akses elemen dengan cara biasa menggunakan (x, y)? Melakukan ini tidak akan mengubah kandungan matriks". Ya, tiada apa yang akan berubah. Tetapi dalam dunia pengaturcaraan, amalan yang diterima adalah untuk mengakses matriks "mula-mula dengan y, kemudian dengan x". Anda harus menerima ini sebagai cara yang betul. Sekarang mari kita bercakap tentang mengunjurkan matriks ke enjin kita (Gamekelas). Seperti yang anda ketahui, enjin mempunyai banyak kaedah yang mengubah sel-sel medan permainan pada koordinat tertentu. Sebagai contoh, setCellValue(int x, int y, String value)kaedah. Ia menetapkan sel tertentu dengan koordinat (x, y) sama dengan parameter nilai. Anda mungkin perasan bahawa kaedah ini mengambil x dahulu, sama seperti dalam sistem koordinat klasik. Kaedah lain enjin berfungsi dengan cara yang sama. Apabila membangunkan permainan, selalunya perlu menghasilkan semula keadaan matriks pada skrin. Bagaimana kita melakukannya? Pertama, anda perlu mengulangi semua elemen matriks dalam gelung. Kedua, panggil kaedah paparan untuk setiap daripada mereka, menggunakan koordinat TERBALIK. Sebagai contoh:

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]));
        }
    }
}
Sememangnya, pembalikan berfungsi dalam kedua-dua arah. Anda boleh menghantar (i, j) kepada setCellValuekaedah dan pada masa yang sama mengambil elemen [j][i] daripada matriks. Membalikkan koordinat mungkin kelihatan agak sukar, tetapi anda perlu mengingatinya. Dan selalu, jika anda menghadapi sebarang masalah, anda harus mengambil sekeping kertas dan pen, melukis matriks, dan menghasilkan semula proses yang melibatkan matriks.

5. Nombor rawak

Bagaimanakah anda bekerja dengan penjana nombor rawak? Kelas Gamementakrifkan getRandomNumber(int)kaedah. Di bawah tudung, ia menggunakan Randomkelas daripada pakej java.util, tetapi cara anda bekerja dengan penjana nombor rawak tidak berubah. getRandomNumber(int)mengambil integer sebagai hujah. Nombor ini akan menjadi had atas apa yang boleh dipulangkan oleh penjana. Had bawah ialah 0. Penting! Penjana TIDAK akan mengembalikan nombor had atas. Contohnya, jika anda memanggil getRandomNumber(3), ia akan mengembalikan 0, 1 atau 2 secara rawak. Seperti yang anda lihat, ia tidak boleh mengembalikan 3. Menggunakan penjana dengan cara ini agak mudah, tetapi sangat berkesan dalam banyak kes. Katakan anda perlu mendapatkan nombor rawak dalam beberapa julat: Bayangkan anda memerlukan nombor tiga digit dalam julat [100..999]. Seperti yang anda sedia maklum, nombor minimum yang dikembalikan ialah 0. Jadi anda perlu menambah 100. Tetapi dalam kes ini, anda perlu berhati-hati untuk tidak melebihi had atas. Untuk mendapatkan 999 sebagai nilai rawak maksimum, hubungigetRandomNumber(int)kaedah dengan hujah 1000. Tetapi sekarang kita ingat bahawa kita menambah 100 pada hasilnya: ini bermakna sempadan atas harus dikurangkan sebanyak 100. Dengan kata lain, kod untuk mendapatkan nombor tiga digit rawak kita akan kelihatan seperti ini :

int number = 100 + getRandomNumber(900);
Tetapi untuk memudahkan prosedur ini, enjin menyediakan getRandomNumber(int, int)kaedah yang parameter pertamanya ialah nombor minimum untuk dikembalikan. Menggunakan kaedah ini, contoh sebelumnya boleh ditulis semula seperti berikut:

int number = getRandomNumber(100, 1000);
Nombor rawak boleh digunakan untuk mendapatkan elemen tatasusunan rawak:

String [] names = {"Sarah", "Val", "Sergey"};
String randomName = names[getRandomNumber(names.length)]
Menjana peristiwa tertentu dengan beberapa kebarangkalian. Bagi manusia, pagi bermula dengan beberapa senario yang mungkin: Terlalu tidur – 50% peluang; Bangun tepat pada masanya - 40% peluang; Bangun sejam lebih awal – 10% peluang. Bayangkan anda sedang menulis penjana hasil pagi. Anda perlu menjana peristiwa dengan kebarangkalian tertentu. Untuk melakukan ini, anda sekali lagi perlu menggunakan penjana nombor rawak. Pelaksanaan yang berbeza mungkin, tetapi yang paling mudah harus berdasarkan algoritma berikut:
  1. tetapkan had yang digunakan untuk menjana nombor;
  2. menjana nombor rawak;
  3. memproses nombor yang diperolehi.
Dalam kes ini, maksimum ialah 10. HubungigetRandomNumber(10)kaedah dan menganalisis bahawa ia boleh kita kembalikan. Ia boleh mengembalikan 10 nombor (dari 0 hingga 9), setiap satu dengan kebarangkalian yang sama — 10%. Sekarang kita perlu menggabungkan semua hasil yang mungkin dan memetakannya kepada acara yang mungkin berlaku. Imaginasi anda mungkin memikirkan banyak kemungkinan kombinasi, tetapi inilah yang paling jelas: "Jika nombor rawak berada dalam julat [0..4], kita mempunyai peristiwa "Terlebih Tidur"; jika nombor itu berada dalam julat [5 ..8], kita mempunyai acara "Bangun tepat pada masanya"; dan jika nombornya ialah 9, maka kita mempunyai acara "Bangun sejam lebih awal". Semuanya sangat mudah. ​​Terdapat 5 nombor dalam julat [0 ..4], setiap satunya boleh dikembalikan dengan kebarangkalian 10%, untuk jumlah 50%; terdapat 4 nombor dalam julat [5..8], baik, dan 9 hanyalah satu nombor yang muncul dengan kebarangkalian 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");
}
Secara umum, terdapat banyak cara untuk menggunakan nombor rawak. Anda hanya terhad oleh imaginasi anda. Tetapi mereka paling berkesan digunakan jika anda perlu berulang kali mendapatkan beberapa hasil. Kemudian hasil baru akan berbeza daripada yang sebelumnya. Dengan beberapa kebarangkalian, sudah tentu. Itu sahaja buat masa ini! Jika anda ingin mengetahui lebih lanjut tentang bahagian "Permainan", berikut ialah beberapa dokumentasi berguna yang boleh membantu:
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION