====== 2 - Vlastní příkazy a proměnné ====== Vytvoření vlastních příkazů (metod) a použití proměnných. * zdrojové kódy ke stažení: {{courses:A0B36PR1:tutorials:03:pr1-lab03.zip|}} * pro vyučující: [[courses:A0B36PR1:internal:tutorials:03:start]] ===== Úkoly ===== - vytvořte příkaz ''step'', který nahradí příkaz ''move'' (jeden krok) a dále v programu příkaz move nepoužívejte - dále vytvořte příkaz ''doSteps'' s parametrem, kolik kroků má provést * nápověda: ''void doSteps(int numberOfSteps)'' - rozšiřte robota tak, aby uměl spočítat celkový počet provedených kroků * nápověda: využijte vámi vytvořený příkaz ''step'' - vyřešte úlohu z domácího úkolu z 1. cvičení (přesun značek od stěn) tak, aby program fungoval pro obecné tvary místností (nikoliv pouze obdélník) ==== Nápověda ==== Abyste mohli splnit úkol 4., je potřeba umět zjistit (relativní) pozici robota. K tomu si potřebujete vytvořit vlastní souřadný systém a kdykoliv se robot pohne anebo pootočí, tak měnit příslušné hodnoty. K tomu je dobré použít příkaz step a také si vytvořit příkaz ''rotateLeft'', který "nahradí" ''turnLeft''. V těchto příkazech pak bude i kód změny souřadnic. /* === Vlastní příkaz === Vytvoření nového příkazu ''doFiveSteps'', který provede pět kroků robota. void doFiveSteps() { for (int i = 0; i < 5; i++) { move(); } } Jak vypadá celý program resp. definice našeho vlastního robota, rozšířená o nový príkaz: package cz.cvut.fel; import kareltherobot.FelKarel; public class MujKarel extends FelKarel { // Definice našeho nového příkazu (metody) void doFiveSteps() { for (int i = 0; i < 5; i++) { move(); } } @Override public void execute() { // Zavolání našeho nového příkazu doFiveSteps(); } } */ === Vytvoření a použití proměnné === Proměnné mohou být různého typu. V našich přikladech zatím vystačíme s typem "int", reprezentující celá čísla. O dalších typech a detailních informacích o proměnných se dozvíte na přednášce a v průběhu semestru na dalších cvičeních. Vytvoření proměnné typu ''int'': // typ názevProměnné int stepCounter; Název proměnné by měl vystihovat to, k čemu je proměnná použita. Pokud slouží např. k počítání počtu kroků robota, nazveme ji ''int stepCounter''. Rozhodně NE např. ''int aaa'' !!! Funkce programu se sice nezmění, ale program přestává být čitelný a do budoucna je těžko srozumitelný a rozšiřitelný. Pro pojmenování proměnných, funkcí atd. volte jako jazyk angličtinu. Česky pište maximálně v komentářích a i tam se tomu snažte vyhnout. Celý program s použitím proměnných: package cz.cvut.fel; import kareltherobot.FelKarel; public class Lab03Karel extends FelKarel { int stepCounter = 0; // proměnná, která patří robotovi a je přístupná ze všech našich metod (příkazů) // Definice nového příkazu, který provede dva kroky a aktualizuje počítadlo void twoSteps() { move(); move(); stepCounter = stepCounter + 2; // Aktuzalizace počtu provedených kroků } @Override public void execute() { int repeats = 2; // proměnná, která je přístupná pouze uvnitř "execute" (tzv. lokální proměnná) // V příkazu "for" můžeme číslo nahradit proměnnou for (int i = 0; i < repeats; i++) { twoSteps(); } } } ===== Domácí úkol ===== Robot bude procházet bludiště pomocí pravidla pravé ruky, dokud nenajde první beeper, ten pak sebere, a vrátí se na startovní pozici, kde beeper položí. Poté se robot vypne. Pravidlo pravé ruky v tomto kontextu znamená, že robot jde tak, aby měl po pravé ruce vždy stěnu. Jestliže ji po pravé ruce nemá, otočí se doprava a udělá krok. Předpokládejte, že bludiště má řešení. Robot svoji startovní ani aktuální pozici nezná, proto musí počítat ušlé kroky. ==== Instrukce ==== Program pište do připravené šablony ze cvičení ''Lab03Karel.java''. Stejně jako v předchozím úkolu, je třeba přepnout svět. Toho docílíte zakomentováním řádku 12 v ''Lab03Task.java'' a odkomentováním řádků 13 a 14. Změníte tedy obsah z: World.readWorld("lab.klwd"); //World.readWorld("maze.klwd"); //World.placeBeepers(4, 2, 1); na: //World.readWorld("lab.klwd"); World.readWorld("maze.klwd"); World.placeBeepers(4, 2, 1); Doporučení: úlohu vhodně rozdělte na jednotlivé podúlohy - např. příkaz pro otestování přítomnosti zdi po pravé resp. levé ruce (''boolean wallOnRight()'' resp. ''boolean wallOnLeft()''). Narozdíl od předchozího domácího úkolu není zadáno, na jaké podúlohy program rozdělit. Je to čistě na vás. Odevzdávejte zazipovaný soubor ''Lab03Karel.java'' === Upozornění === To, že váš program funguje na vzorovém bludišti neznamená, že funguje obecně. Pokud chcete modifikovat šablonu pro otestování různých pozic robota, případně různých pozic beeperu, můžete tak učinit změnou metody ''task()'' v souboru ''Lab03Task.java''. Pomocí ''setDelay'' můžete upravit rychlost běhu programu (nižší číslo => rychlejší běh). World.placeBeepers(6, 6, 1); World.setDelay(5); UrRobot karel = new UrRobot(3, 1, North, 0); Pozor na speciální případ, např. kdy robot přišel z východu směrem na západ jak ukazuje šipka a právě sebral beeper. Nyní by se tedy měl otočit a podle pravidla levé ruky dojít zpět stejný počet kroků jako šel tam. Problém je, že když se otočí a rozběhne se podle pravidla levé ruky, tak první co udělá bude, že se otočí doleva, tedy směrem na sever. {{courses:A0B36PR1:tutorials:03:karel.png?260|}} Tuto situaci testuje test ''singularity1''. Jednoduchá oprava řešení této singularity může vést k zanesení chyby, která způsobí, že neprojde test ''singularity2''. Dobře si vaše řešení rozmyslete. /* * řešení: [[courses:A0B36PR1:tutorials:solutions:03:start]] * pro vyučující: [[courses:A0B36PR1:internal:tutorials:03:start]] ===== Náplň cvičení ===== Procvičení aritmetických operátorů +,-,*,/,%, výpočet součtu, rozdílu, součinu a podílu dvou čísel, problém vyhodnocení výrazů v System.out.println(a+b). Výpočet obvodu a obsahu čtverce, kruhu. Výpočet povrchu a objemu krychle, kvádru, jehlanu, vrchlíku. Cílem tohoto cvičení je seznámení studentů s proměnnými, s výrazy a vstupem a výstupem. ===== Formátovaný vstup ===== Pro vstup dat z klávesnice se s výhodou používá třída Scanner: Scanner scan = new Scanner(System.in); System.out.println("Zadej cislo:"); int cislo = scan.nextInt(); System.out.println("Zadej desetinne cislo:"); double d = scan.nextDouble(); System.out.println("Zadej slovo:"); String s = scan.next(); System.out.println("Cely radek:"); String r = scan.nextLine(); **Poznámky:** * desetinné číslo se zadává s desetinnou tečkou, pokud ji OS vyžaduje (např. Solaris, či MS Windows s lokalizací anglickou) nebo s desetinnou čárkou, pokud OS běží v češtině. * System.in je bufrovaný proud, aby se cokoli do něj předalo, musí se zmáčknout enter. ===== Formátovaný výstup ===== public static void main(String[] args) { String str = "Pepa"; char ch = 'x'; int i = 12; float f = 4.5F; Date date = new Date(); System.out.printf("%b%n", str); System.out.printf("%c%n", ch); System.out.printf("%03d%n", i); System.out.printf("%e%n", f); System.out.printf("%03f%n", f); System.out.printf("%.2f%n", f); System.out.printf("{%07.3f}%n", f); System.out.printf("%f%n", f); System.out.printf("%g%n", f); System.out.printf("%h%n", f); System.out.printf("%s%n", 5); System.out.printf("%s://%s/%s%n", str, str, str); System.out.printf("%1$s...%n", str); System.out.printf("%5s%n", str); System.out.printf("%-5s%n", str); System.out.printf("%-10.10s %s%n", str, 3); System.out.printf("%.5s%n", str); System.out.printf("%s%n", date); System.out.printf("%tc%n", date); //(lowercase t, lowercase c) System.out.printf("%tC%n", date); //(lowercase t, uppercase C) System.out.printf("%tD%n", date); System.out.printf("%tF%n", date); System.out.printf("%tr%n", date); System.out.printf("%tR%n", date); System.out.printf("%tT%n", date); System.out.printf("%tz%n", date); System.out.printf("%Tc%n", date); System.out.printf("%1$x, %1$X%n", 0xCAFE); System.out.printf(Locale.CHINA, "%tc%n", date); System.out.printf(Locale.ITALIAN, "%tc%n", date); System.out.printf(Locale.getDefault(), "%tc%n", date); } **Podívejte se na přehled [[courses:A0B36PR1:literature:printf:start|formátových specifikátorů a speciálních znaků]].** ===== Úlohy ===== - Napište program, který vypíše součet čísel 1 234 567 890 a 2 000 000 000. Výpočet proveďte v proměnné typu int. Je výsledek správný? Zdůvodněte. - Napište program, který vypočte a zobrazí faktoriál čísla 9. Nepoužívejte cyklus. - Co bude výsledkem operace a = 5 + 3 * 4? - Co bude výsledkem operace a = 5 / 3 pro a typu int? Jak se změní výsledek, pokud bude a typu double. - Co bude výsledkem operace a = 7 / 0 pro a typu int? Jak se změní výsledek, pokud bude a typu double. - Napište program, který pro kruh zadaný poloměrem r vypočte jeho obvod a obsah. Výsledek zobrazte na 3 desetinná místa (formátování výstupu je popsáno v přednáškách, hledejte metodu printf). - Pro následující výrazy, které jsou součástí příkazů určete typ výrazu, pokuste se jej vyhodnotit a výsledek ověřte programem: - a=7; - b=(b2=7); - c=(c2==7); - int d = 5; d+= 4; - e = 15+6/2*3; - d = 1.56E30; - 1.2E4 + 15; - 5.2E3 * 5E-1 - Napište program, který přečte řetězec a tento řetězec vypíše dvakrát do řádku. - Napište program, který přečte dvě čísla a vypíše jejich součet, rozdíl, součin a podíl. Formát výstupu pro čísla 15 a 7 a součin bude následující: Součin: 15 * 7 = 105. - Napište program, který vypočte povrch a obsah hranolu zadaného velikostmi jednotlivých stran. - Napište program, který vypočte povrch a objem válce zadaného poloměrem podstavy a výškou. ===== Složitější úlohy ===== - Napište program, který vypočte povrch a obsah kuželu zadaného poloměrem podstavy a výškou. Výsledek zaokrouhlete na 3 desetinná místa. - V čase 0 vyrazil Pepa rychlostí v1 na zábavu. Za dobu t po Pepovi vyrazil z téhož místa stejnou cestou i Vašek. Vašek měl delší nohy a tak šel rychlostí v2, v2>v1. Určete vzdálenost od startu, kterou potřebuje Vašek, aby se přiblížil k Pepovi natolik, aby na něj mohl účinně zavolat: "Pepíkůů, počkej na mne." Pepa uslyší Vaška na vzdálenost 250 metrů, hodnoty t, v1 a v2 budou zadány. ===== Další úlohy ===== ==== I. ==== Realizujte program, který přečte ze svého vstupu dva časové údaje (hodina, minuta) a vypočte kolik mezi nimi uběhlo hodin a minut. Příklad použití: Zadej hodinu 1: 12 Zadej minutu 1: 34 Zadej hodinu 2: 18 Zadej minutu 2: 15 Mezi 12:34 a 18:15 ubehlo 341 minut, tj. 5 h 41 min **Nápověda** Použijte celá čísla. Převeďte oba údaje na počet minut od půlnoci, tyto hodnoty odečtěte. Pro zobrazení výsledku použijte operátor pro výpočet zbytku po dělení (%). Pokročilí budou počítat i sekundy. ==== II. ==== Realizujte program, který vypočte soustavu lineárních rovnic 2 * 2. Předpokládejte, že soustava má tvar: a1,1 x + a1,2 y = b1 a2,1 x + a2,2 y = b2 Příklad použití: Zadej a11: 1 Zadej a12: 4 Zadej b1: 32 Zadej a21: 3 Zadej a22: 3 Zadej b2: 42 x = 8.0 y = 6.0 **Nápověda** Použijte sčítací metodu. Pokročilí počítají soustavu 3x3 ==== III. ==== Realizujte program, který přečte ze vstupu 3 celá čísla, nalezne mezi nimi maximum, minimum a prostřední z nich (předpokládejte, že čísla jsou navzájem různá). Příklad použití: Zadej prvni cislo: 8 Zadej druhe cislo: 6 Zadej treti cislo: 17 nejvetsi 17 prostredni 8 nejmensi 6 **Nápověda** Použijte vztahu: max(a,b) = ( a + b + abs ( a - b ) ) / 2, min(a,b) = ( a + b - abs ( a - b ) ) / 2. Absolutní hodnotu vypočte metoda Math.abs() ===== Domácí úkol ===== **Úvodní zadání semestrální práce.** \\ Návrhy semestrálních prací naleznete v sekci [[courses:a0b36pr1:tutorials:semestralka:start|Témata semestrálních prací]]. */