JavaRush /Java блогы /Random-KK /JavaRush-тегі «Ойындар» бөлімі: Пайдалы теория

JavaRush-тегі «Ойындар» бөлімі: Пайдалы теория

Топта жарияланған
JavaRush бағдарламасының «Ойындар» бөлімінде сіз танымал компьютерлік ойындарды жазуға арналған қызықты жобаларды таба аласыз. Танымал «2048», «Сапер», «Жылан» және басқа да ойындардың өз нұсқасын жасағыңыз келе ме? Бұл оп-оңай. Біз ойын жазуды қадамдық процеске айналдырдық. БөлімӨзіңізді ойын әзірлеушісі ретінде сынап көру үшін сізге озық бағдарламашы болудың қажеті жоқ, бірақ әлі де белгілі бір Java білімі қажет. Мұнда сіз ойын жазу кезінде пайдалы болатын ақпаратты таба аласыз .

1. Мұрагерлік

JavaRush ойын механизмімен жұмыс мұрагерлікті пайдалануды қамтиды. Бірақ оның не екенін білмесеңіз ше? Бір жағынан, сіз бұл тақырыпты түсінуіңіз керек: ол 11 деңгейде зерттеледі . Екінші жағынан, қозғалтқыш өте қарапайым болу үшін әдейі жасалған, сондықтан сіз тұқым қуалаушылық туралы үстірт біліммен өмір сүре аласыз. Сонымен, мұрагерлік дегеніміз не? Қарапайым тілмен айтсақ, мұрагерлік – екі класс арасындағы қатынас. Олардың бірі ата-анаға, екіншісі балаға (мұрагер сынып) айналады. Бұл жағдайда ата-аналық сынып өзінің ұрпақ сыныптары бар екенін білмеуі мүмкін. Анау. ол мұрагер класстардың болуынан ешқандай ерекше пайда алмайды. Бірақ мұрагерлік ұрпақ класына көптеген артықшылықтар береді. Ал ең бастысы, ата-аналық класстың барлық айнымалылары мен әдістері еншілес сыныпта пайда болады, ата-аналық сыныптың codeы еншілес сыныпқа көшірілген сияқты. Бұл мүлдем дұрыс емес, бірақ мұрагерлікті жеңілдетілген түсіну үшін ол жасайды. Міне, мұраны жақсы түсіну үшін бірнеше мысалдар. 1-мысал: ең қарапайым мұра.
public class Родитель {

}
Child класы extensions кілт сөзін пайдаланып Parent класынан мұраланады .
public class Потомок extends Родитель {

}
2-мысал: Негізгі класс айнымалыларын пайдалану.
public class Родитель {

   public int age;
   public String name;
}
Child сыныбы Ата-ана класының жас және атау айнымалы мәндерін оларда жарияланғандай пайдалана алады .
public class Потомок extends Родитель {

   public void printInfo() {

     System.out.println(name+" "+age);
   }
}
3-мысал: Ата-аналық сынып әдістерін қолдану.
public class Родитель {

   public int age;
   public String name;

   public getName() {
      return name;
   }
}
Child класы Parent класының айнымалылары мен әдістерін оларда жарияланғандай пайдалана алады. Бұл мысалда біз getName () әдісін қолданамыз .
public class Потомок extends Родитель {

   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}
Компилятордың көзқарасы бойынша Descendant класы осылай көрінеді:
public class Потомок extends Родитель {

   public int age; //  унаследованная переменная
   public String name; //  унаследованная переменная

   public getName() { //  унаследованный метод.
      return name;
  }
   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}

2. Әдісті қайта анықтау

Кейде біздің Descendant сыныбымызды барлық айнымалылар мен әдістермен бірге өте пайдалы Ата-ана сыныбынан алған жағдайлар болады, бірақ кейбір әдістер дәл біз қалағандай жұмыс істемейді. Немесе мүлде біз қаламайтындай емес. Бұл жағдайда не істеу керек? Біз өзімізге ұнамайтын әдісті жоққа шығара аламыз. Бұл өте қарапайым орындалады: біздің Descendant сыныбымызда біз жай ғана ата-аналық класс әдісімен бірдей қолтаңбасы (тақырып) бар әдісті жариялаймыз және оған codeымызды жазамыз. 1-мысал: әдісті қайта анықтау.
public class Родитель {

   public String name;

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

   public getName() {
      return name;
  }
}
printInfo() әдісі "Luke, No!!!" фразасын басып шығарады.
public class Потомок extends Родитель {

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

   public void printInfo() {

      setName("Luke");
      System.out.println( getName());
   }
}
Компилятордың көзқарасы бойынша Descendant класы осылай көрінеді:
public Потомок extends Родитель {

   public String name; //  унаследованная переменная

   public void setName (String nameNew) { //  Переопределенный метод взамен унаследованного

       name = nameNew + ", No!!!";
   }
   public getName() { //  унаследованный метод.

      return name;
   }
   public void printInfo() {

     setName("Luke");
     System.out.println(getName());
   }
}
2-мысал: мұрагерлік сиқыры (және әдісті қайта анықтау).
public class Родитель {

   public getName() {
      return "Luke";
  }
   public void printInfo() {

     System.out.println(getName());
   }
}
public class Потомок extends Родитель {

   public getName() {
      return "I'm your father, Luke";
  }
}
Бұл мысалда: егер әдіс printInfo(Ата-ана сыныбынан) Descendant сыныбында қайта анықталмаса, бұл әдіс Descendant сыныбының нысанында шақырылғанда, оның әдісі Ата-ана класы getName()емес, деп аталады.getName()
Родитель parent = new Родитель ();
parent.printnInfo();
Бұл code экранда «Лұқа» жазуын көрсетеді .
Потомок child = new Потомок ();
child.printnInfo();
Бұл codeта «Мен сенің әкеңмін, Лука;» деген жазу бар. .
Компилятордың көзқарасы бойынша Descendant класы осылай көрінеді:
public class Потомок extends Родитель {

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

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

3. Тізімдер

Тізімдермен әлі таныспаған болсаңыз, мұнда жылдам праймер бар. Сіз JavaRush курсының 6-7 деңгейлері туралы толық ақпаратты таба аласыз . Тізімдер массивтермен көп ортақ:
  • белгілі бір типтегі көптеген мәліметтерді сақтай алады;
  • элементтерді олардың индексі/саны бойынша алуға мүмкіндік береді;
  • элемент индекстері 0-ден басталады.
Тізімдердің артықшылықтары: массивтерден айырмашылығы, тізімдер өлшемін динамикалық түрде өзгерте алады. Жасалғаннан кейін бірден тізімнің өлшемі 0 болады. Тізімге элементтерді қосқанда оның өлшемі артады. Тізімді құру мысалы:
ArrayList<String> myList = new ArrayList<String>(); // создание нового списка типа ArrayList
Бұрыш жақшаларындағы мән тізім сақтай алатын деректер түрі болып табылады. Тізіммен жұмыс істеудің бірнеше әдістері:
Код Код не істейтінін қысқаша сипаттау
ArrayList<String> list = new ArrayList<String>(); Жолдардың жаңа тізімін жасау
list.add("name"); Тізімнің соңына элемент қосыңыз
list.add(0, "name"); Тізімнің басына элемент қосыңыз
String name = list.get(5); Элементті оның индексі бойынша алыңыз
list.set(5, "new name"); Элементті оның индексі бойынша өзгертіңіз
int count = list.size(); Тізімдегі элементтердің санын алыңыз
list.remove(4); Элементті тізімнен алып тастаңыз
Сіз осы мақалалардан тізімдер туралы көбірек біле аласыз:
  1. ArrayList класы
  2. Суреттердегі жұмыс массивтері тізімі
  3. ArrayList ішінен элементті жою

4. Массивтер

Матрица дегеніміз не? Матрица деректермен толтырылатын төртбұрышты кестеден басқа ештеңе емес. Басқаша айтқанда, бұл екі өлшемді массив. Өздеріңіз білетіндей, Java-дағы массивтер an objectілер болып табылады. Стандартты бір өлшемді массив түрі intкелесідей болады:
int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
Мұны көрнекі түрде елестетіп көрейік:
0 1 2 3 4 5 6 7
12 32 43 54 15 36 67 28
Жоғарғы жол ұяшық мекенжайларын көрсетеді. Яғни, 67 санын алу үшін 6 индексі бар массив элементіне қол жеткізу керек:
int number = array[6];
Мұнда бәрі өте қарапайым. Екі өлшемді массив – бір өлшемді массивтердің массиві. Бұл туралы бірінші рет естіп жатсаңыз, тоқтаңыз және оны басыңызға елестетіңіз. Екі өлшемді массив келесідей көрінеді:
0 Бір өлшемді массив Бір өлшемді массив
1 Бір өлшемді массив
2 Бір өлшемді массив
3 Бір өлшемді массив
4 Бір өлшемді массив
5 Бір өлшемді массив
6 Бір өлшемді массив
7 Бір өлшемді массив
Кодта:
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 мәнін алу үшін [4][2] мекенжайындағы матрица элементіне қол жеткізу керек.
int number = matrix[4][2];
Байқасаңыз, матрица координаталары классикалық тікбұрышты координаталар жүйесінен (декарттық координаттар жүйесі) ерекшеленеді. Матрицаға қатынасу кезінде алдымен y, содан кейін x көрсетіледі , ал математикада алдымен x(x, y) мәнін көрсету әдеттегідей. Сіз өзіңізге сұрақ қоюыңыз мүмкін: «Неліктен қиялыңыздағы матрицаны өзгертіп, элементтерге әдеттегі жолмен (x, y) арқылы қол жеткізбеске? Бұл матрицаның мазмұнын өзгертпейді». Иә, ештеңе өзгермейді. Бірақ бағдарламалау әлемінде матрицаларға «алдымен y, содан кейін х» түрінде сілтеме жасау әдеттегідей. Бұл заңды түрде қабылдануы керек. Енді матрицаны қозғалтқышқа (сыныпқа) проекциялау туралы сөйлесейік Game. Өздеріңіз білетіндей, қозғалтқышта берілген координаттарда ойын өрісінің ұяшықтарын өзгертетін көптеген әдістер бар. Мысалы, setCellValue(int x, int y, String value). Ол координаталары бар белгілі бір ұяшықты (x, y) мәніне орнатады value. Өздеріңіз байқағандай, бұл әдіс алдымен классикалық координаттар жүйесіндегідей дәл х қабылдайды. Қозғалтқыштың қалған әдістері ұқсас түрде жұмыс істейді. Ойындарды әзірлеу кезінде жиі экрандағы матрицаның күйін қайта шығару қажеттілігі туындайды. Мұны қалай жасауға болады? Біріншіден, циклде матрицаның барлық элементтерін қайталау керек. Екіншіден, олардың әрқайсысы үшін INVERTED координаталарымен көрсету әдісін шақырыңыз. Мысалы:
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]));
        }
    }
}
Әрине, инversion екі бағытта жұмыс істейді. (i, j) әдісіне setCellValueөтуге болады , бірақ сонымен бірге матрицадан [j][i] элементін алуға болады. Инversion сәл қиын болып көрінуі мүмкін, бірақ бұл есте сақтау керек нәрсе. Әрқашан, қандай да бір проблемалар туындаса, қаламмен қағаз парағын алып, матрицаны сызып, оған қандай процестер болып жатқанын ойнатқан жөн.

5. Кездейсоқ сандар

Кездейсоқ сандар генераторымен қалай жұмыс істеуге болады? Класс Gameәдісті анықтайды getRandomNumber(int). Сорғыштың астында ол java.util бумасының класын пайдаланады Random, бірақ бұл кездейсоқ сандар генераторымен жұмыс істеу принципін өзгертпейді. Аргумент ретінде getRandomNumber(int)бүтін санды қабылдайды . Бұл сан генератор қайтара алатын жоғарғы шекара болады. Төменгі шегі 0. Маңызды! Генератор ЕШҚАШАН жоғарғы шекаралық санды қайтармайды. Мысалы, егер getRandomNumber(3)кездейсоқ шақырылса, ол 0, 1, 2 қайтара алады. Көріп отырғаныңыздай, ол 3 қайтара алмайды. Бұл генераторды пайдалану өте қарапайым, бірақ көптеген жағдайларда өте тиімді. Кездейсоқ санды кейбір шектерде алу керек: Сізге үш таңбалы сан (100..999) қажет деп елестетіңіз. Өздеріңіз білетіндей, қайтарылатын ең аз сан 0. Сондықтан оған 100 қосу керек.Бірақ бұл жағдайда жоғарғы шектен асып кетпеу үшін абай болу керек. Максималды кездейсоқ мән ретінде 999 алу үшін getRandomNumber(int)1000 аргументі бар әдісті шақыру керек. Бірақ біз 100-ді кейінгі қосу туралы есімізде: бұл жоғарғы шекараны 100-ге төмендету керек дегенді білдіреді. Яғни, codeты алу үшін code. Кездейсоқ үш таңбалы сан келесідей болады:
int number = 100 + getRandomNumber(900);
Бірақ мұндай proceduresаны жеңілдету үшін қозғалтқыш getRandomNumber(int, int)бірінші аргумент ретінде қайтару үшін ең аз санды алатын әдісті ұсынады. Осы әдісті пайдаланып, алдыңғы мысалды қайта жазуға болады:
int number = getRandomNumber(100, 1000);
Кездейсоқ сандарды массивтің кездейсоқ элементін алу үшін пайдалануға болады:
String [] names = {"Andrey", "Валентин", "Сергей"};
String randomName = names[getRandomNumber(names.length)]
Белгілі бір ықтималдықпен белгілі бір оқиғаларды іске қосу. Адамның таңы ықтимал сценарийлер бойынша басталады: Ұйқысы 50%; Уақытында тұру – 40%; Күтілгеннен бір сағат бұрын тұрды – 10%. Сіз адамның таңғы эмуляторын жазып жатырсыз деп елестетіңіз. Белгілі бір ықтималдықпен оқиғаларды бастау керек. Ол үшін тағы да кездейсоқ сандар генераторын пайдалану керек. Іске асыру әртүрлі болуы мүмкін, бірақ ең қарапайымы келесі алгоритмді ұстануы керек:
  1. біз санды құру қажет шектерді белгілейміз;
  2. кездейсоқ санды құру;
  3. Алынған санды өңдейміз.
Сонымен, бұл жағдайда шек 10 болады. Әдісті шақырайық getRandomNumber(10)және ол бізге не қайтара алатынын талдап көрейік. Ол 10 цифрды (0-ден 9-ға дейін) және әрқайсысының ықтималдығы бірдей - 10% қайтара алады. Енді біз барлық ықтимал нәтижелерді біріктіріп, оларды мүмкін оқиғаларымызбен сәйкестендіруіміз керек. Сіздің қиялыңызға байланысты комбинациялар көп болуы мүмкін, бірақ ең айқын дыбыстар: «Егер кездейсоқ сан [0..4] шегінде жатса - «Ұйқысыз» оқиғасын шақырыңыз, егер нөмір [5..8] ішінде болса. ] - «Уақытында ояныңыз» және егер сан 9 болса, «Мен күткеннен бір сағат бұрын тұрдым». Барлығы өте қарапайым: [0..4] ішінде 5 сан бар, олардың әрқайсысы 10% ықтималдықпен қайтара алады, олардың барлығы 50% болады; [5..8] ішінде 4 сан бар, ал 9 - 10% ықтималдықпен шығатын жалғыз сан. Кодта бұл ақылды дизайн одан да қарапайым көрінеді:
int randomNumber = getRandomNumber(10);
if (randomNumber < 5) {
    System.out.println("Проспал ");
} else if (randomNumber < 9) {
    System.out.println("Встал вовремя ");
} else {
    System.out.println("Встал на час раньше положенного ");
}
Жалпы, кездейсоқ сандарды пайдаланудың көптеген нұсқалары болуы мүмкін. Мұның бәрі тек сіздің қиялыңызға байланысты. Бірақ бірнеше рет нәтиже алу қажет болса, олар ең тиімді қолданылады. Сонда бұл нәтиже алдыңғысынан өзгеше болады. Әрине, белгілі бір ықтималдықпен. Бар болғаны! Ойындар бөлімі туралы көбірек білгіңіз келсе, мына жерде көмектесе алатын пайдалы құжат бар:
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION