1. Meros olish
JavaRush o'yin dvigateli bilan ishlashda meros olishdan foydalanish nazarda tutiladi, lekin bu mavzuni keyinroq ushbu modulda ko'rib chiqamiz. Bir tomondan, bu mavzuni tushunish kerak. Boshqa tomondan, dvigatel juda oddiy qilib loyihalashtirilgan, shuning uchun meros olish haqida yuzaki bilimlar bilan ham ishlash mumkin. Demak, meros olish nima? Agar juda oddiy qilib aytsak, meros olish - bu ikki sinf o'rtasidagi aloqadir. Ulardan biri ota-sinf bo'ladi, ikkinchisi esa farzand (merosxo'r sinf). Shu bilan birga, ota-sinf hatto o'zining farzand sinflari borligini bilmasligi mumkin. Yani merosxo'r sinflarning mavjudligidan u alohida foyda olmaydi. Ammo farzand sinfi uchun meros olish juda ko'p afzalliklarni beradi. Ularning asosiysi shundaki, ota-sinfning barcha o'zgaruvchilari va metodlari farzand sinfda ham paydo bo'ladi, xuddi ota-sinfning kodi farzand sinfga nusxa qilingan kabi. Bu to'liq to'g'ri emas, lekin meros olishni oddiygina tushunish uchun yetarli. Mana, meros olishni yaxshiroq tushunish uchun bir nechta misollar.
Misol 1: eng oddiy meros olish.
public class Ota {
}
|
Farzand sinfi Ota sinfidan extends kalit so'zi yordamida meros olgan. |
public class Farzand extends Ota {
}
|
Misol 2: ota-sinfning o'zgaruvchilaridan foydalanish.
public class Ota {
public int age;
public String name;
}
|
Farzand sinfi Ota sinfining age va name o'zgaruvchilaridan xuddi ularni o'zida e'lon qilingandek foydalanishi mumkin. |
public class Farzand extends Ota {
public void printInfo() {
System.out.println(name+" "+age);
}
}
|
Misol 3: ota-sinfning metodlaridan foydalanish.
public class Ota {
public int age;
public String name;
public getName() {
return name;
}
}
|
Farzand sinfi Ota sinfining o'zgaruvchilari va metodlaridan xuddi ularni o'zida e'lon qilingandek foydalanishi mumkin. Ushbu misolda biz getName() metodidan foydalanamiz. |
public class Farzand extends Ota {
public void printInfo() {
System.out.println(getName()+" "+age);
}
}
|
Mana, kompyuter ko'zida
Farzand sinfi qanday ko'rinadi:
public class Farzand extends Ota {
public int age; // meros qilib olingan o'zgaruvchi
public String name; // meros qilib olingan o'zgaruvchi
public getName() { // meros qilib olingan metod.
return name;
}
public void printInfo() {
System.out.println(getName()+" "+age);
}
}
2. Metodlarni qayta yozish
Ba'zi hollarda, biz farzand sinfimizni foydali ota-sinfdan barcha o'zgaruvchilar va metodlar bilan meros qilib oldik, lekin ba'zi metodlar biz xohlagandek ishlamaydi yoki xatto butunlay boshqacha ishlashadi. Bunday holatda nima qilish kerak? Biz yoqtirmagan metodni qayta yozishimiz mumkin. Bu juda oddiy: farzand sinfimizda ota-sinf metodining bir xil signaturasi (sarlavhasi) bilan metodni e'lon qilamiz va unga o'z kodimizni yozamiz.
Misol 1: metodni qayta yozish.
public class Ota {
public String name;
public void setName (String nameNew) {
name = nameNew;
}
public getName() {
return name;
}
}
|
printInfo() metodi ekranga "Luke, No!!!" so'zlarini chiqaradi |
public class Farzand extends Ota {
public void setName (String nameNew) {
name = nameNew + ",No!!!";
}
public void printInfo() {
setName("Luke");
System.out.println( getName());
}
}
|
Mana, kompyuter ko'zida
Farzand sinfi qanday ko'rinadi:
public Farzand extends Ota {
public String name; // meros qilib olingan o'zgaruvchi
public void setName (String nameNew) { // Qayta yozilgan metod o'rniga meros qilib olingan
name = nameNew + ", No!!!";
}
public getName() { // meros qilib olingan metod. return name; }
public void printInfo() {
setName("Luke");
System.out.println(getName());
}
}
Misol 2: meros olish (va metodlarni qayta yozish)ning biroz mo'jizasi.
public class Ota {
public getName() {
return "Luke";
}
public void printInfo() {
System.out.println(getName());
}
}
|
public class Farzand extends Ota {
public getName() {
return "I'm your father, Luke";
}
}
|
Ushbu misolda: agar
Farzand sinfida
printInfo metodi (ota-sinfdan) qayta yozilmagan bo'lsa,
Farzand sinfi ob'ekti uchun ushbu metod chaqirilganda, uning
getName() metodi, ota-sinfdagi
getName() chaqiriladi.
Ota parent = new Ota ();
parent.printnInfo();
|
Ushbu kod ekranga "Luke" so'zlarini chiqaradi. |
Farzand child = new Farzand ();
child.printnInfo();
|
Ushbu kod ekranga "I'm your father, Luke;" so'zlarini chiqaradi. |
Mana, kompyuter ko'zida
Farzand sinfi qanday ko'rinadi:
public class Farzand extends Ota {
public getName() {
return "I'm your father, Luke";
}
public void printInfo() {
System.out.println(getName());
}
}
3. Ro'yxatlar - qisqacha ma'lumot.
To'liq ma'lumotni keyingi daraja kursida topasiz
.
Ro'yxatlar va massivlar juda ko'p umumiylikka ega:
- bir xil turdagi ko'p ma'lumotlarni saqlash mumkin;
- elementlarni ularning indeks/raqam bo'yicha olish mumkin;
- elementlarning indekslari 0-dan boshlanadi.
Ro'yxatlarning afzalliklari: Massivlardan farqli o'laroq, ro'yxatlar dinamik ravishda o'lchamlarini o'zgartira oladi. Ro'yxat yaratilgandan so'ng, u 0 o'lchamiga ega bo'ladi. Ro'yxatga elementlar qo'shilgan sayin uning o'lchami oshadi. Ro'yxat yaratish misoli:
ArrayList<String> myList = new ArrayList<String>(); // yangi ArrayList turi ro'yxatini yaratish
Burchak qavslar ichidagi qiymat ro'yxat saqlay oladigan ma'lumotlar turini anglatadi. Ro'yxat bilan ishlash uchun ba'zi metodlar:
| Kod |
Koddan kelib chiqadigan harakatlar tavsifi |
ArrayList<String> list = new ArrayList<String>(); |
Yangi satrlar ro'yxatini yaratish |
list.add("name"); |
Elementni ro'yxatning oxiriga qo'shish |
list.add(0, "name"); |
Elementni ro'yxatning boshiga qo'shish |
String name = list.get(5); |
Elementni uning indeks/raqamidan olish |
list.set(5, "new name"); |
Elementni uning indeks/raqamidan o'zgartirish |
int count = list.size(); |
Ro'yxatdagi elementlar sonini olish |
list.remove(4); |
Elementni ro'yxatdan o'chirish |
Ro'yxatlar haqida ko'proq bilib olishingiz mumkin bo'lgan maqolalar:
- ArrayList klassi
- ArrayList ishlashidagi rasmlar
- ArrayList ro'yxatidan elementni o'chirish
4. Massivlar
Matritsa nima? Matritsa - bu boshqa narsa emas, balki to'rtburchakli jadval bo'lib, u ma'lumotlar bilan to'ldirilishi mumkin. Boshqa so'z bilan aytganda, bu ikki o'lchovli massiv. Ehtimol, bilasiz, massivlar Java-da obyektlar hisoblanadi. Standart bir o'lchovli
int turi massivi quyidagicha ko'rinadi:
int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
Buni vizual tasavvur qilamiz:
| 0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
| 12 |
32 |
43 |
54 |
15 |
36 |
67 |
28 |
Yuqoridagi qator hujayralarning manzillarini ko'rsatadi. Shunday qilib, 67 ni olish uchun massivning 6 indeksli elementsiga murojaat qilish kerak:
int number = array[6];
Bu juda oson. Ikki o'lchovli massiv bir o'lchovli massivlarning massivi hisoblanadi. Taxminan ikki o'lchovli massiv quyidagicha ko'rinadi:
| 0 |
Bir o'lchovli massiv |
Bir o'lchovli massiv |
| 1 |
Bir o'lchovli massiv |
| 2 |
Bir o'lchovli massiv |
| 3 |
Bir o'lchovli massiv |
| 4 |
Bir o'lchovli massiv |
| 5 |
Bir o'lchovli massiv |
| 6 |
Bir o'lchovli massiv |
| 7 |
Bir o'lchovli massiv |
Kodda:
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 |
47 qiymatni olish uchun matritsa elementi [4][2] ga murojaat qilish kerak.
int number = matrix[4][2];
Agar sezsangiz, matritsa koordinatlari an'anaviy to'rtburchakli koordinata tizimidan (Dekart tizimi) farq qiladi.
Matritsaga murojaat qilishda avval y, keyin x ni ko'rsatasiz, matematikada esa avval x (x, y) ko'rsatiladi. "Balki matritsani o'z xayolimizda ag'darib tashlab, elementlarga odatiy (x, y) orqali murojaat qilsak qanday bo'lardi? Matritsaning mazmuni o'zgarmaydi-ku". - degan savol tug'ilishi mumkin. Ha, hech narsa o'zgarmaydi. Lekin dasturlash olamida matritsaga "avval y, keyin x" formatida murojaat qilish odati bor. Buni qabul qilish kerak. Endi matritsa ko'rinishini dvigatelimizda (Game klassi) qanday ko'rsatish haqida gaplashamiz. Siz allaqachon bilib olganingizdek, dvigatelda o'yin maydonining hujayralarini berilgan koordinatalar bo'yicha o'zgartiradigan ko'plab metodlar mavjud. Misol uchun,
setCellValue(int x, int y, String value) metodi bor. U berilgan (x, y) koordinatali hujayraga qiymat
value ni o'rnatadi. Bilingki, bu metod aynan x ni birinchi bo'lib qabul qiladi, xuddi an'anaviy koordinata tizimida bo'lgani kabi. Shu tarzda dvigatelning boshqa metodlari ham ishlaydi. O'yinlar ishlab chiqarishda matritsa holatini ekranda ko'rsatish zaruriyati tez-tez yuzaga keladi. Buni qanday amalga oshirish mumkin? Birinchidan, matritsaning barcha elementlarini aylantirib chiqish kerak. Ikkinchidan, har bir element uchun INVERTED koordinatalar bilan chiqarish metodini chaqirish kerak. Misol:
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]));
}
}
}
Albatta, inversiya ikki yo'nalishda ishlaydi.
setCellValue metodiga (i, j) ni uzatish mumkin, lekin matritsadan [j][i] ni olish mumkin. Inversiya biroz murakkab tuyulishi mumkin, lekin uni yodda saqlash kerak. Va har doim, agar biror muammo yuzaga kelsa, bir qog'oz bilan ruchka olib, matritsani chizib ko'ring va unga sodir bo'ladigan jarayonlarni tasavvur qilib ko'ring.
5. Tasodifiy raqamlar
Tasodifiy raqamlar generatoridan qanday foydalanish?
Game klassida
getRandomNumber(int) metodi aniqlangan. Uning asosi
Random klassi (java.util paketidan) ga asoslanadi, lekin tasodifiy raqamlar generatori bilan ishlash prinsipi o'zgarmaydi.
getRandomNumber(int) argument sifatida butun sonni qabul qiladi. Bu son generator qaytarishi mumkin bo'lgan yuqori chegarani belgilaydi. Pastki chegarasi 0 hisoblanadi.
Muhim! Generator HECH QACHON yuqori cheklangan sonni qaytarmaydi. Masalan,
getRandomNumber(3) ni chaqirsak, u tasodifiy ravishda 0, 1, 2 ni qaytarishi mumkin. Ko'rib turganingizdek, 3 ni qaytarishi mumkin emas. Bunday generatorni ishlatish juda oddiy, lekin ko'pgina holatlarda samaralidir.
Agar biror intervallarda tasodifiy raqam olish kerak bo'lsa: Tasavvur qiling, biror uch raqamli son (100..999) kerak. Bildingizki, minimal qaytariladigan son - 0. Demak, unga 100 ni qo'shish kerak bo'ladi. Biroq, bu holda yuqori cheklovni o'tmaslik haqida g'amxo'rlik qilish lozim. Maksimal tasodifiy qiymat 999 bo'lishi uchun
getRandomNumber(int) metodini 1000 argument bilan chaqirish kerak. Lekin biz 100 ni qo'shishni esdan chiqarmaymiz: demak yuqori chegarani 100 ga kamaytirish zarur. Shunday qilib, uch raqamli tasodifiy sonni olish kodi quyidagicha ko'rinadi:
int number = 100 + getRandomNumber(900);
Lekin, bunday jarayonni soddalashtirish uchun dvigatelda
getRandomNumber(int, int) metodi mavjud bo'lib, u minimal qaytariladigan sonni birinchi argument sifatida qabul qiladi. Shu metoddan foydalanib, avvalgi misol quyidagicha yozilishi mumkin:
int number = getRandomNumber(100, 1000);
Tasodifiy raqamlar massivdan tasodifiy element olish uchun ishlatilishi mumkin:
String [] names = {"Andrey", "Valentin", "Sergey"};
String randomName = names[getRandomNumber(names.length)]
Ma'lum ehtimollik bilan aniq voqealarni chaqirish. Insonning ertalabki holati bir necha ssenariyalarga ko'ra boshlanadi: Uhlab qolgan – 50%; O'z vaqtida uyg'ongan – 40%; Bir soat oldin uyg'ongan – 10%. Tasavvur qiling, insonning ertalabki holatini emulyatsiya qilmoqdasiz. Sizga aniq ehtimollik bilan voqealarni chaqirish kerak. Buning uchun yana tasodifiy raqamlar generatoridan foydalanish kerak. Turli xil realizatsiyalar bo'lishi mumkin, lekin eng oddiy algoritm quyidagicha bo'lishi kerak:
- kerakli chegaralarni belgilaymiz, bu yerda sonni yaratish kerak;
- tasodifiy sonni generatsiya qilamiz;
- olingan sonni ishlatamiz.
Demak, bu holatda chegarasi 10 bo'ladi.
getRandomNumber(10) metodini chaqirib, u nima qaytarishini tahlil qilamiz. U 0 dan 9 gacha bo'lgan 10 ta raqamni qaytarishi mumkin va har birini teng ehtimollik bilan — 10%. Endi biz mumkin bo'lgan barcha natijalarni kombinatsiyalashimiz va ularni mumkin bo'lgan voqealarimiz bilan moslashtirishimiz kerak. Sizning tasavvuringizga qarab juda ko'p kombinatsiyalar bo'lishi mumkin, lekin eng aniqrog'i shunday: "Agar tasodifiy son [0..4] oralig'ida bo'lsa — 'Uhlab qolgan' voqeasi chaqiriladi, agar son [5..8] oralig'ida bo'lsa — 'O'z vaqtida uyg'ongan', va faqat son 9 bo'lsa, 'Bir soat oldin uyg'ongan'". Bu juda oddiy: [0..4] oralig'idagi 5 ta son har biri 10% ehtimollik bilan qaytarilishi mumkin, bu esa umumiy 50% ni tashkil etadi; [5..8] oralig'ida 4 ta son bor, va 9 — yagona son, u esa 10% ehtimollik bilan paydo bo'ladi. Kodda esa bu sodda konstruktsiya yanada oson ko'rinadi:
int randomNumber = getRandomNumber(10);
if (randomNumber < 5) {
System.out.println("Uhlab qolgan ");
} else if (randomNumber < 9) {
System.out.println("O'z vaqtida uyg'ongan ");
} else {
System.out.println("Bir soat oldin uyg'ongan ");
}
Umuman, tasodifiy raqamlarni qo'llashning juda ko'p variantlari bo'lishi mumkin. Bu faqat tasavvuringizga bog'liq. Lekin eng samarali, agar biror natijani ko'p marta olish kerak bo'lsa, ularni qo'llashdir. Bu holda, natija oldingi natijadan farq qiladi. Tabiiyki, ma'lum bir ehtimollik bilan. Hozircha hammasi shu!
GO TO FULL VERSION