====== Reversi I ====== * Poslední konzultace a dokončení úlohy Spam filter. * Lehký úvod do objektů v Javě, rozdíly proti Pythonu * Představení 3. úlohy Reversi ===== Domácí úkol ===== Nadcházející neděli do 23:59:59 je třeba odevzdat finální spam filtr podle [[courses:a4b99rph:cviceni:spam:specifikace#odevzdani_2|specifikací]]. * Dokončit [[courses:a4b99rph:cviceni:reversi:krok1|krok 1]] pro úlohu Reversi, tj.: * Nakonfigurovaný a spustitelný projekt * Vytvořený vlastní hráč ===== Java ===== Poslední semestrální úlohu budete řešit v Javě. Tu už znáte z Programování 1 a tak si jen v rychlosti ukážeme pár rozdílů v syntaxi oproti Pythonu: * deklarace proměnných spolu s jejich typem: int i = 1; * volani konstruktoru pomocí //new//: Object o = new Object(); * deklarace typu návratových hodnot a vstupních parametrů metod * //self/this//: * oboje odkazuje na konkrétní instanci objektu, v Javě se neuvádí //this// jako jeden z parametrů metod * this není potřeba používat pro volání metod třídy a odkazování na proměnné třídy, pokud je volání jednoznačné: void setValue(int value){ this.value = value } * **Specifikátory přístupu** | ^ třída ^ podtřída ^ balík ^ ostatní ^ ^ public | x | x | x | x | ^ protected | x | x | x | | ^ package | x | | x | | ^ private | x | | | | * **final** * třída - nelze od ní dědit * metoda - nelze ji měnit v odděděných třídách * proměnná - po inicializaci nemůže být její hodnota změněna * **static** * Značí že proměnná(nebo metoda) není proměnnou instance, ale proměnnou třídy. * Každá instance třídy (objekt) má vlastní kopii proměnné instance. Proměnná třídy je pouze jedna a instance přistupují stále k té samé proměnné. * Statické metody je možné narozdíl od nestatických volat i tehdy, neexistuje-li žádná instance dané třídy. Podobně se statickými proměnnými. * K proměnným třídy přistupujeme jménem třídy. * Statické metody nemůžou přistupovat k proměnným instance (objektu), protože není definváno k proměnným kterého objektu přistupovat. ===== Pokročilé datové struktury v Javě ===== > {{page>courses:a4b99rph:internal:cviceni:tyden09#struktury}} === Primitivní nativní typy === * Java nativně podporuje 8 primitivních typů - **byte**, **short**, **int**, **long**, **float**, **double**, **boolean**, **char** * Někdy není možné primitivní typy použít. Java poskytuje obalující typy (wrapper types), které jsou plnohodnotné objekty - **Byte**, **Short**, **Integer**, **Long**, **Float**, **Double**, **Boolean**, **Character** === Pokročilé datové struktury === * Java poskytuje množství datových struktur (objektů), které ulehčují základní operace nad základními datovými strukturami (přidávání, odebírání, procházení atd.) * Datové struktury jsou typované - při deklaraci se definuje jaký typ objektu bude v datové struktuře uložen, tzn. jakého typu budou jednotlivé položky. Položka může být opět datová struktura a tím mohou vznikat vícerozměrné datové struktury. * **LinkedList** reprezentuje spojový seznam (seznam položek spojených ukazateli) položek (objektů). Na začátku není třeba definovat velikost - přidáním nové položky se jen přidá ukazatel (link) na nový prvek. Procházení spojového seznamu je sekvenční. Lze přistupovat přímo na prostřední prvky, ale implementace musí projít celý seznam od začátku až po hledaný prvek. Odebírání prvku probíhá efektivně v konstatním čase. ++++ Ukázka metod pro LinkedList | List seznam; // deklarace seznam = new LinkedList(); // vytvoreni seznam.add(14); // pridani prvku 14 na konec seznam.addFirst(9); // pridani prvku 9 na zacatek seznam.add(23); // pridani prvku 23 na konec seznam.addFirst(15); // pridani prvku 15 na zacatek (seznam vypada 15,9,14,23) int size = seznam.size(); // vrati velikost - 4 int i = seznam.get(2); // vrati treti! prvek (neefektivne pruchodem od zacatku) - 14 boolean empty = seznam.isEmpty(); // vrati true, pokud je seznam prazdny seznam.remove(); // smaze prvni prvek seznam.clear(); // smaze vse ++++ * **ArrayList** reprezentuje datovou strukturu pole. U ArrayListu není třeba definovat velikost (možné to ale je), Java vytvoří defaultní velikost a pokud velikost pole nestačí, tak ho automaticky zvětší na dvojnásobek. To může vést ke zbytečné alokaci velkého množství paměti. ArrayList se dá procházet sekvečně, ale dá se také přímo přistupovat na konkrétní prvek jeho indexem v poli. Odebírání prvku je neefektivní, protože po odebrání prvku je nutné zbytek pole posunout. ++++ Ukázka metod pro ArrayList | class Osoba { // defince tridy Osoba } ArrayList pole; // deklarace pole obsahujici osoby. pole = new ArrayList(30); // vytvoreni pole obsahujici osoby. // ArrayList je inicializovan na velikost 30 (ale neni to nutne) pole.add(new Osoba()); // pridani nove osoby na konec pole.add(new Osoba()); // pridani nove osoby na konec int size = pole.size(); // vrati velikost Osoba os = pole.get(1); // vrati druhy! prvek (efektivne primym pristupem) boolean empty = pole.isEmpty(); // vrati true, pokud je pole prazdny pole.set(1, new Osoba()); // nastavi druhy prvek pole na novou hodnotu pole.clear(); // smaze vse ++++ * **HashMap** reprezentuje hashovací tabulku. Hashovací tabulka je seznam dvojic, která přiřazuje zvolenému **klíči** danou **hodnotu**. Klíč musí být v rámci tabulky unikátní. HashMap umožňuje přimý přístup (v konstaním čase) k hodnotě pomocí klíče. Tzn. že se můžeme zeptat jaká je přiřazená hodnota danému klíči a HashMap v konstatním čase vrátí hodnotu nebo oznámí, že klíč není v tabulce. HashMap lze procházet sekvenčně, ale není garantováno pořadí prvků. ++++ Ukázka metod pro HashMap | HashMap mapa; // deklarace mapa = new HashMap(); // vytvoreni mapa.put(2.5, "prvni"); // vlozi do mapy klic 2.5 s hodnotou "prvni" mapa.put(3.5, "prvni"); // vlozi do mapy klic 3.5 s hodnotou "prvni" (hodnota se muze opakovat) mapa.put(4.0, "druhy"); // vlozi do mapy klic 4.0 s hodnotou "druhy" mapa.put(-1.1, null); // vlozi do mapy klic -1.1 s hodnotou null (null muze nahradit libovolny objekt) mapa.put(4.0, "novy"); // vlozi a prepise do mapy klic 4.0 s hodnotou "novy" a tim prepise hodnotu "druhy" (klic se neopakuje) int size = mapa.size(); // vrati velikost boolean empty = mapa.isEmpty(); // vrati true, pokud je mapa prazdna boolean obsahuje = mapa.containsKey(2.5); // vrati true - klic je v mape // ERROR String hodnota = mapa.get(2.5); // vrati String "prvni" obsahuje = mapa.containsKey(6.7); // vrati false - klic neni v mape // ERROR hodnota = mapa.get(6.7); // vrati null - klic neni v mape // ale POZOR obsahuje = mapa.containsKey(-1.1); // vrati true - klic je v mape hodnota = mapa.get(-1.1); // vrati null - hodnota ulozena pod klicem -1.1 mapa.remove(4.0); // odstrani z mapy klic 4.0 a jeho hodnotu Set klice = mapa.keySet(); // vrati mnozinu klicu (podrobneji pozdeji) Collection hodnoty = mapa.values(); // vrati mnozinu hodnot (podrobneji pozdeji) Set> dvojice = mapa.entrySet(); // vrati mnozinu vsech dvojic (klic, hodnota) v mape // ERROR mapa.clear(); // smaze vse ++++ * **LinkedHashMap** je rozšířením struktury HashMap o ukazatele mezi jednotlivými prvky (podobně jako u LinkedListu). Umožňuje snadnější průchod tabulkou podle pořadí vkládání prvků. ++++ Ukázka metod pro LinkedHashMap | LinkedHashMap> mapa; // deklarace mapy cisel, ktera ma jako hodnoty seznamy mapa = new LinkedHashMap>();// vytvoreni mapy LinkedList seznam = new LinkedList(); // vytvoreni noveho seznamu seznam.add("prvni"); // pridani prvku do seznamu mapa.put(35, seznam); // vlozeni seznamu do mapy pod klic 35 seznam.add("druhy"); // pridani dalsiho prvku do seznamu. // projevi se i v mape, protoze je to ukazatel na stale stejny objekt LinkedList seznam2 = new LinkedList(); // vytvoreni noveho seznamu seznam2.add("ahoj"); // pridani prvku do seznamu mapa.put(12, seznam2); // vlozeni noveho seznamu pod klic 12 ++++ === Iterátor === * Konstrukce Javy, která umožňuje snadné procházení kolekcemi - např. LinkedList, ArrayList, LinkedHashMap, Set * Postupně prochází danou kolekci a v každé iteraci vrací jeden prvek * jednoduchý iterátor **foreach** - snadné použití, nelze mazat položky, daný průchod od začátku do konce ++++ Ukázka použití iterátoru | LinkedList seznam = new LinkedList(); seznam.add("prvni"); seznam.add("druhy"); seznam.add("treti"); for (String item : seznam) { // vpravo od dvojtecky musi byt objekt typu Collection System.out.println(item); // vlevo je promenna, ktera je stejneho typu, jakym je typovana kolekce } // cyklus provede pocet iteraci podle poctu prvku v kolekci // a v kazde iteraci vrati do promenne item jednu polozku kolekce LinkedHashMap mapa = new LinkedHashMap(); for (Integer key : mapa.keySet()) { // prochazi mnozinu vsech klicu } for (String value : mapa.values()) { // prochazi mnozinu vsech hodnot } for (Map.Entry entry : mapa.entrySet()) { // prochazi mnozinu vsech dvojic klic/hodnota int key = entry.getKey(); // klic z dvojice String value = entry.getValue(); // hodnota z dvojice } ++++ * komplexní iterátor - univerzálnější použití, lze mazat položky, možnost definice vlastního průchodu ++++ Ukázka použití komplexního iterátoru | LinkedList seznam = new LinkedList(); seznam.add("prvni"); seznam.add("druhy"); seznam.add("treti"); Iterator iter = seznam.iterator(); // zalozi novy iterator pro seznam while (iter.hasNext()) { // pokracuje v cyklu dokud exituji nejake dalsi polozky String item = iter.next(); // do item nacte dalsi polozku if (item.equals("druhy")) { iter.remove(); // smaze polozku, ktera byla prave nactena pomoci funkce next() } // lze pouzit maximalne jednou, pak se musi zavolat znovu next() } ++++ ===== Reversi ===== Třetí semestrální úlohou RPH bude naprogramování hráče pro hru [[courses:a4b99rph:cviceni:reversi:start|Reversi]]. Začneme postupně od začátku a to [[courses:a4b99rph:cviceni:reversi:krok1|krokem 1]]. ===== Hádanka ===== > {{page>courses:a4b99rph:internal:cviceni:tyden09#Hadanka&editbtn}}