Programování robotů 1

Transkript

Programování robotů 1
OBCHODNÍ AKADEMIE ORLOVÁ, PŘÍSPĚVKOVÁ ORGANIZACE
ÚVOD DO PROGRAMOVÁNÍ ROBOTŮ 1
MGR. MIROSLAV SULÍR
ORLOVÁ 2012
Tento projekt je spolufinancován Evropským sociálním fondem a státním rozpočtem České republiky PROJEKT: ŠKOLA DNES A ZÍTRA INOVATIVNÍ PŘÍSTUP K VÝUCE TECHNICKÝCH A PŘÍRODOVĚDNÝCH OBORŮ Řešitel projektu: Obchodní akademie, Orlová, příspěvková organizace Učební pomůcka pro podporu výuky přírodních věd a technických oborů Název: Úvod do programování robotů 1 Autor: Mgr. Miroslav Sulír Vydání: Počet stran: 99 Náklad: Tisk: Ediční středisko první, 2012 20 © Mgr. Miroslav Sulír © Obchodní akademie, Orlová, příspěvková organizace Jazyková korektura nebyla provedena, za jazykovou správnost odpovídá autor. ISBN 978‐80‐87477‐04‐5Orlová
Tento projekt je spolufinancován Evropským sociálním fondem a státním rozpočtem České republiky 0bsah
Kapitola 0. Úvod ................................................................................................................................ 4 Pro koho je kniha určena ..................................................................................................................... 4 Programovací jazyk C# ......................................................................................................................... 4 Lego Mindstorms a Robotc ................................................................................................................. 4 Jak se učit ............................................................................................................................................ 5 Dodatky ke sbírce ................................................................................................................................ 5 Metodika ............................................................................................................................................. 6 Hodně štěstí při práci .......................................................................................................................... 6 Kapitola 1. Program Robotc a stavebnice Lego Mindstorms ............................................................ 7 Instalace vývojových prostředí ............................................................................................................ 7 Chyby při aktualizaci firmware ............................................................................................................ 8 Okno programu Robotc ....................................................................................................................... 9 Sestavení robota ................................................................................................................................ 10 Kapitola 2. Algoritmus a jeho vlastnosti .......................................................................................... 14 Pojem algoritmu ................................................................................................................................ 14 Vlastnosti algoritmu .......................................................................................................................... 14 Zápis algoritmů .................................................................................................................................. 15 Základní algoritmické struktury ......................................................................................................... 16 Kapitola 3. První příklad v prostředí Robotc .................................................................................... 18 Programování motorů ....................................................................................................................... 18 Struktura programu ........................................................................................................................... 18 Kompilace programu ......................................................................................................................... 19 Chyby programů ................................................................................................................................ 20 Nahrání programu do NXT terminálu a jeho testování ..................................................................... 22 Příkazy: motor, wait1Msec ................................................................................................................ 23 Komentáře programu ........................................................................................................................ 24 Kapitola 4. Příklady na jízdu ............................................................................................................. 26 Otáčíme robotem .............................................................................................................................. 26 Kapitola 5. Zvuky .............................................................................................................................. 30 Příkaz PlaySound ............................................................................................................................... 30 Problémy doprovázející příkazy přehráváním zvuku ......................................................................... 32 Přehrání zvuku ze souboru ................................................................................................................ 33 Kapitola 6. Proměnné a datové typy ............................................................................................... 37 Pojem proměnné a datového typu ................................................................................................... 37 Přiřazení hodnoty do proměnné ....................................................................................................... 40 Počáteční inicializace proměnné ....................................................................................................... 40 Konstanta .......................................................................................................................................... 41 Kapitola 7. Psaní na displej NXT terminálu ...................................................................................... 42 Psaní textů ......................................................................................................................................... 42 Velikost písma ................................................................................................................................... 44 Zobrazování hodnot číselných proměnných ..................................................................................... 46 Výpis více proměnných v jednom řetězci .......................................................................................... 48 Zobrazení obsahu textových proměnných v řetězci .......................................................................... 48 Další způsoby výpisu textových informací na displej ........................................................................ 49 Vymazání obsahu displeje ................................................................................................................. 49 Kapitola 8. Početní operace s proměnnými a konstantami číselných datových typů ..................... 51 Zjednodušené psaní operací.............................................................................................................. 53 Kapitola 9. Podmínka ....................................................................................................................... 55 Kapitola 10. Dotykový senzor ............................................................................................................ 58 Dotaz na stisk dotykového senzoru ................................................................................................... 59 Nekonečný cyklus .............................................................................................................................. 60 Časová prodleva pro opětovné testování ......................................................................................... 62 Vícenásobná podmínka ..................................................................................................................... 68 Disjunktní podmínky .......................................................................................................................... 69 Kapitola 11. Hrajeme si ...................................................................................................................... 74 Generátor náhodných čísel ............................................................................................................... 74 Hra pozornosti ................................................................................................................................... 75 Seznam cvičení a souhrnných cvičení v kapitolách
Kapitola 0. Úvod ................................................................................................................................ 4 Kapitola 1. Program Robotc a stavebnice Lego Mindstorms ............................................................ 7 Kapitola 2. Algoritmus a jeho vlastnosti .......................................................................................... 14 Kapitola 3. První příklad v prostředí Robotc .................................................................................... 18 Testování příkazů motor a wait1Msec .............................................................................................. 23 Kapitola 4. Příklady na jízdu ............................................................................................................. 26 Otočka o 360 stupňů ......................................................................................................................... 26 Tam a zpět ......................................................................................................................................... 27 Jízda městem ..................................................................................................................................... 28 Kapitola 5. Zvuky .............................................................................................................................. 30 Pojezd a zvuk ..................................................................................................................................... 32 Kolečko se zvuky ................................................................................................................................ 35 Kapitola 6. Proměnné a datové typy ............................................................................................... 37 Kapitola 7. Psaní na displej NXT terminálu ...................................................................................... 42 Popis jízdy .......................................................................................................................................... 44 Odpočet ............................................................................................................................................. 45 10 stupňů celsia ................................................................................................................................. 47 Pi ........................................................................................................................................................ 48 Výkon motorů .................................................................................................................................... 48 Fotbal ................................................................................................................................................. 49 Kapitola 8. Početní operace s proměnnými a konstantami číselných datových typů ..................... 51 Pořadí matematických operací .......................................................................................................... 53 Porovnání zápisu pro zvětšení proměnné ......................................................................................... 54 Odpočet s proměnnou ...................................................................................................................... 54 Kapitola 9. Podmínka ....................................................................................................................... 55 Kapitola 10. Dotykový senzor ............................................................................................................ 58 Zapnutí a vypnutí pojezdu dvěma ovladači ....................................................................................... 62 Zvyšování a snižování rychlosti .......................................................................................................... 65 Zahýbání ............................................................................................................................................ 66 Jízda s nastavením rychlosti předem ................................................................................................. 67 Zahýbání a jízda vpřed 1 .................................................................................................................... 68 Zahýbání a jízda vpřed 2 .................................................................................................................... 69 Zastavení po uplynutí určité doby nebo nárazem do zdi .................................................................. 72 Kapitola 11. Hrajeme si ...................................................................................................................... 74 Generování čísel ze zadaných intervalů ............................................................................................ 74 Hra pozornosti pro dva hráče ............................................................................................................ 78 Pojezdová hra .................................................................................................................................... 79 Kapitola 0. Úvod
Pro koho je kniha určena
Programování bývá pro začátečníky často učivem velmi obtížným. Každý začátek je
ale těžký, a proto je dobré nenechat se odradit. Abych Vám pomohl překonat první krůčky do
světa programů „za zdí“, kde slovo program znamená tisíce znaků sdružených do příkazů
programovacího jazyka, připravil jsem pro Vás sbírku příkladů Úvod do programování robotů
k mechanické programovatelné stavebnici Lego Mindstorms NXT 2.0. Právě držíte její první
díl.
Tato publikace je určena všem, kteří se chtějí seznámit s programováním, nejen
v moderním programovacím jazyce C#. Na své si ovšem přijdou i Ti, kteří už v programování
něco zvládají, a chtějí se v něm zdokonalovat zábavnou formou.
V obou případech je nutné vlastnit, anebo mít k dispozici (třeba ve škole)
programovatelnou stavebnici Lego Mindstorms a program Robotc.
Programovací jazyk C#
Hlavním cílem knihy je, průběžně Vás seznámit se základy programování
v programovacím jazyku C#. Jedná se o objektově orientovaný programovací jazyk, který
vyvinula firma Microsoft tak, aby splňoval požadavky platformy .NET. Jazyk C# je
pokračovatelem programovacích jazyků C a C++, a vychází tedy z jejich syntaxí (mají stejné
nebo podobné příkazy). V jazyce C# dnes můžete programovat prakticky cokoliv, co Vás
napadne. Od formulářových aplikací pro Windows, přes software do mobilních zařízení,
databáze, až po internetové stránky. Než se však dostanete k programování náročných
aplikací, budete muset ujít ještě dlouhou cestu.
Stojíte nyní na jejím začátku, což je bezesporu její nejnáročnější část. Na začátku se
musíte seznámit se základními algoritmizačními strukturami a příkazy. V tomto dílu učebnice
se bude jednat o sekvenci a podmínku. Dozvíte se také, jak pracovat s tzv. proměnnými a
konstantami. Pomocí příkladů si budete upevňovat základní programovací návyky.
Jazyk C# je dnes velmi moderním a rozšířeným jazykem. Jeho základy, nabyté v této
knize, můžete v budoucnu využít k programování formulářových, mobilních, internetových i
jiných aplikací.
Lego Mindstorms a Robotc
Lego Mindstorms je pro začínající programátory velmi zajímavý projekt. Snoubí
v sobě totiž jak hračku (přiznejte se, kdo z Vás si rád nehraje ), tak programovací nástroj.
Právě skutečnost, že se jedná o hračku, dělá programování zábavnějším. Společnost Lego
přibaluje ke stavebnici software nazvaný Lego Mindstorms, ve kterém jsou návody pro
sestavení čtyř základních strojů. Taktéž je dodáváno grafické prostředí pro vývoj programů.
Tím se ale budeme zabývat velmi okrajově a rovnou se vrhneme na programování pomocí
textového zápisu algoritmu. K tomu využijeme program Robotc společností Robomatter LLC
/ DRJ Software LLC.
Protože budete vytvářet programy pro lego robota, jsou nezbytnou součástí učebnice
postupy, jak přistupovat k jeho součástkám. Dozvíte se například, jak rozhýbat motor, aby
robot popojel, nebo jak detekovat stisk senzoru, aby robot uměl zareagovat na povel zvenčí.
Konkrétně se budeme zabývat motory a jejich pojezdem ve stanoveném čase, dotykovým
(touch) senzorem, programováním displeje a reproduktoru NXT terminálu. Tento terminál,
obsahující procesor, paměť, vstupní a výstupní porty, displej, reproduktor a napájecí systém je
hlavním jednotkou každého robota.
Jak se učit
Při psaní této knihy jsem dbal na to, aby byl každý nový poznatek vysvětlen nejen
teoretickým popisem, ale hlavně praktickým příkladem použití. Sbírka obsahuje jak příklady
přímo řešené, jejichž rozborem, úpravou a spuštěním se naučíte nové poznatky, tak cvičné, na
nichž si osvojené znalosti otestujete. Souhrnná cvičení nakonec otestují Vaše dovednosti na
složitějších příkladech. Vyřešené kódy veškerých cvičení s vysvětlením jsou uvedeny v zadní
části učebnice. Velmi však na Vás apeluji, abyste těchto klíčů využívali minimálním
způsobem. Osvojení programátorských zásad a metod nepatří k nejlehčím, ale vězte, že
opisováním kódů se ještě nikdo programovat nenaučil. Pokud tedy budete mít při
programování problém, zkuste se ještě jednou vrátit k dotyčné látce v učebnici, nebo se
poradit se svými kamarády, či učiteli o možnostech řešení. Nakouknutí do vyřešených kódů
berte vždy až jako poslední východisko.
Je ještě jeden důvod, proč se unáhleně neuchylovat k hotovým řešením. Programování
je tvůrčí činnost, jejímž cílem je vytvořit program splňující zadání (dané učitelem,
zaměstnavatelem, sebou samými, …). Pokud byste tento úkol, zadali několika lidem, všichni
by začali pracovat na prázdném listu. Výsledné programy by se nakonec více, či méně, lišily.
Mohou existovat desítky programových kódů, které nejsou stejné, ale dělají to samé. V zadní
části knihy je ale jen jeden z nich. Proto hrozí nebezpečí, že podíváte-li se na hotová řešení
této učebnice, můžete spatřit velké rozdíly oproti řešení Vašemu a ztratit tak motivaci, protože
budete své řešení automaticky pokládat za od základu špatné. To ale nemusí být pravda a
drobnou úpravou Vašeho odlišného přístupu můžete dojít ke zdárnému řešení. Proto si raději
programy sami vytvářejte a konzultujte, ne opisujte.
Dodatky ke sbírce
Knihu doplňuje doprovodné CD, které obsahuje jak veškeré ukázkové programy
sbírky, tak řešení cvičných úkolů. Dále je obsažena časově omezená verze programu Robotc
v.3.04 a ovladače robota Lego Mindstorms pro Windows, které jsou také volně stažitelné
z internetu. CD obsahuje i zvukové soubory použitelné v programech.
Na tuto sbírku navazuje její druhý díl Úvod do programování robotů 2, který
v příkladech rozvíjí učivo sbírky první a doplňuje ji o další navazující témata. V části
programovacích jazyků se jedná hlavně o algebraickou strukturu cyklus. Znalosti stavebnice
Lego Mindstorms si rozšíříte o další možnosti ovládání pojezdu motorů, práci s barevným
senzorem a ultra-sonic senzorem, což je prakticky sonar pro detekci předmětů v určité
vzdálenosti.
Metodika
Aby byl člověk schopen dobře programovat, určitě se neobejde bez základní teorie.
Krom obecné teorie programování se jedná především o znalost základních algebraických
struktur a příkazů. S algebraickými strukturami je potřeba se postupně sžívat, a to od
jednoduché sekvence, přes složitější podmínku, až k cyklům. Abych dal čtenáři možnost
vstřebávat tyto struktury pozvolna, beru je popořádku a ke každé uvádím značné množství
ukázkových příkladů i cvičení. Z cyklů se v této sbírce dostane jen na netradiční nekonečný
cyklus, který pomůže především při práci s dotykovými senzory.
Nad běžícím učivem algebraických struktur nechávám čtenáře objevovat základní
příkazy. Jejich naučení podporují ukázkové příklady, které slouží k analýze.
Poslední fází naučení je procvičování. Cvičných příkladů je zde dohromady 25. 19
z nich je průběžných a jsou různých typů. Jedná se např. o procvičování jednoduchých
příkazů pomocí experimentu, vytváření jednoduchých příkazů, či úpravu kódů vložených na
doprovodném CD tak, aby se upravila činnost robota dle zadání. Programování je ale
především tvůrčí proces, ve kterém je potřeba naučit se samostatnému tvůrčímu myšlení. To
jsem měl při psaní této sbírky na paměti, a proto zde nezanedbatelnou roli hrají příklady, které
si musí programátor vymyslet od začátku do konce. K některým příkladům jsem přiřadil
poznámky, a to buď dopředu sbírky, abych programátory upozornil na některé problémy a
cesty, kudy se vydat. Další poznámky jsou umístěny vzadu v klíči, aby podpořily naučení u
problémovějších úloh.
6 souhrnných cvičení ve sbírce má podobu pracovního listu, na kterém je krom zadání
její podrobnější rozbor a seznam znalostí a pomůcek, které bude programátor potřebovat.
Hodně štěstí při práci
Z vlastní zkušenosti vím, že v jakékoli práci je nejdůležitější najít motivaci. Pokud se
k ní připojí radost, ať už z objevování nového, či práce samotné, budete na nejlepší cestě být
dobří v tom, co děláte. Doufám, že Vám v tom tato sbírka bude aspoň trochu nápomocna.
Kapitola 1. Program Robotc a stavebnice Lego
Mindstorms
Co se naučíte:
Stojíte na samém počátku učebnice programování. Proto nebude na škodu seznámit
se s programem, ve kterém budete pracovat. Dále si podrobně povíme o stavebnici
Lego Mindstorms a jejích možnostech.
Klíčové pojmy kapitoly:
Robotc, Lego Mindstorms
Instalace vývojových prostředí
Než nainstalujeme software Robotc do počítače, je nejprve zapotřební nainstalovat do
Windows ovladače robota Lego Mindstorms. Ovladače si můžete stáhnout ze stránky
http://www.robotc.net/download/nxt/, anebo je naleznete na přiloženém CD. Je potřeba zvolit
32-bitovou nebo 64-bitovou verzi ovladačů, podle verze operačního systému.
Zapněte terminál robota oranžovým tlačítkem, připojte jej k počítači USB kabelem a
spusťte instalaci. Během ní potvrďte licenční podmínky tlačítkem Agree.
Obr. 1 ‐ Průběh instalace ovladače Lego Mindstorms Následně nainstalujte program RobotcForMindstorms. Instalační soubor lze stáhnout
ze stejného umístění, ze kterého jste stahovali ovladač robota. Program je dostupný i na
přiloženém CD, konkrétně se jedná o verzi 3.0. Při instalaci je opět potřeba potvrdit licenční
ujednání.
Obr. 2 ‐ Průběh instalace programu Robotc Na CD se nachází pouze 30-ti denní trial verze. Vlastníte-li licenci, můžete si produkt
aktivovat v okně ROBOTC License Management. Dostanete se k němu z menu Help,
kliknutím na položku Manage Licences.
Obr. 3 – Okno pro aktivaci produktu Robotc Při prvním spuštění programu Robotc a prvním připojení robota je potřeba
aktualizovat jeho firmware. Zapněte terminál robota oranžovým tlačítkem a připojte
k počítači USB kabelem. V nabídce Robot programu Robotc vyberte možnost Download
Firmware, a následně položku Standard File (za nápisem Standard File může být označení
aktuální verze firmware). Otevře se Vám okno NXT Brick Download, ve kterém stiskněte
tlačítko F/W Download. Tím se nainstaluje Firmare ze souboru uloženého ve složce Firmware
programu Robotc. Až se v části Message Log okna objeví nápis „Firmware download
completed“, je firmware v pořádku nainstalován a můžete se pustit do práce.
Chyby při aktualizaci firmware
Pokud by došlo k chybě, která by se projevila dlouhodobým zablokováním NXT
terminálu za současného „tikajícího“ zvukového signálu, stiskněte v okně NXT Brick
Download tlačítko Refresh Lists. Poté se opakujte nahrání tlačítkem F/W Download.
Na některých počítačích jsem se při pokusu o aktualizaci firmware setkal s chybovou
hláškou odkazující na nemožnost komunikace skrze USB port. V takovém případě stačí
program Robotc vypnou a nainstalovat software Lego Mindstorms dodávaný se stavebnicí. To
by mělo problém vyřešit.
Obr. 4 ‐ Aktualizace firmware robota Lego Mindstorms v okně NXT Brick Download Okno programu Robotc
Nyní si popíšeme okno programu Robotc, které můžete vidět na Obr. 5. V horní části
programu se nachází, jak jsme zvyklí od většiny programů, hlavní menu a panely nástrojů.
Hlavní nabídka obsahuje položky File pro práci se soubory, Edit pro práci se schránkou a
funkcemi pro vyhledávání v kódu a View pro úpravu prostřední programu (zobrazování
panelů, úpravy fontů, …). Nabídka Robot slouží pro nastavení platformy, správu senzorů a
jiných vstup/výstupních zařízení, kompilaci a nahrání programu do paměti NXT terminálu
robota. Zbývají nabídky Window pro nastavení samotného menu a Help pro zobrazení
přehledně provedené nápovědy, či aktualizace produktu. Pokud budete mít problém
s programem, anebo programovacím jazykem, vřele doporučuji nápovědu v menu Help
využívat. Nejednou mi dobře posloužila.
Panely nástrojů pod hlavní nabídkou umožňují rychlejší přístup k nejčastěji
používaným funkcím programu.
Největší část okna tvoří editor kódu. Zde budete psát své programy, o jejichž struktuře
se něco dozvíte později. Projektů, jak se říká rozpracovaným programům, si můžete otevřít
několik najednou a přepínat mezi nimi pomocí záložek nad editorem kódu.
Nalevo se nachází panel Function Library, ve které můžete vyhledávat téměř všechny
funkční a deklarační předpisy, které lze v programu využít. Výhodné je to především tehdy,
nepamatujete-li si příkaz, který potřebujete, nebo hledáte-li příkaz, který by Vám v práci
pomohl. Po nalezení jej stačí myší systémem „táhni a pusť“ přesunout na místo kódu, kde jej
chcete vložit a doplnit o konkrétní proměnné, či výrazy. Doporučuji však naučit se zápis
základních struktur a funkcí programu zpaměti. Ušetříte si tak spoustu času. Dvojitým klikem
na položku Function Library spustíte nápovědu.
Před každým spuštěním programu se provádí kontrola, zda je veškerý kód napsán
formálně správně. Na nesprávně napsaný kód Vás upozorní panel Errors, který se nachází ve
spodní části okna programu. A nejen že na něj upozorní, ale navíc označí řádek, kterého se
chyba týká a napoví, jak ji opravit. Více o chybách v programu se dočtete v další kapitole.
Obr. 5 ‐ Okno programu Robotc
Sestavení robota
Než začnete vytvářet programy, musíte si ze stavebnice postavit model, pro který je
budete vytvářet. Nejsnadnější cesta je spustit si nainstalovaný program Lego Mindstorms,
dodávaný se stavebnicí, a vybrat si jeden ze 4 typů robotů vyobrazených v panelu Robo
Center programu. Ke každému modelu je připraveno několik obrazových průvodců pro
sestavení.
Obr. 6 ‐ Panel Robo Center s návody pro sestavení robotů v pravé části okna
Pro práci s touto sbírkou příkladů postačí, když si sestavíte vozidlo (Vehicles)
v základní variantě (Driving Base). V některých příkladech si k tomuto sestavení (Obr. 7)
připojíme senzory. Až budete v programování zběhlejší, můžete si samozřejmě vyzkoušet psát
programy i pro roboty v jiných sestaveních. A pokud by Vás ty standardní omrzely, na
internetu si jistě najdete návody na další varianty.
Obr. 7 ‐ Robot Lego Mindstorms v základní verzi vozidla, se kterou budeme pracovat Krom jednoduchých plastových součástek se ve stavebnici nachází hlavní jednotka
nazvaná NXT (název vychází ze slova NEXT) s procesorem a pamětí. Paměť obsahuje
obslužný program jednotky, programy, které si do ní skrze USB kabel nahrajete a zdroje,
které programy využívají (např. zvuky).
Jednotka také obsahuje porty RJ11 pro kabelové připojení motorů a senzorů.
Stavebnice disponuje v základní verzi třemi motory (ve většině případů jsou dva hlavní pro
pojezd, či pochod, robota a jeden s doplňkovou funkcí), sonar (ultrasonic sensor), který
zjišťuje vzdálenost objektů před ním, barevný (color) senzor pro rozeznávání barev a dva
dotykové (touch) senzory pro reakci na stisk. Dotykové senzory mohou reagovat na stisk buď
jiné součástky robota, nebo na tlak okolního prostředí (např. vražení senzoru na zeď, stisknutí
senzoru palcem, …). Je možné dokoupit si další senzory.
Senzory jsou hlavní součástky pro komunikaci mezi programem a jeho okolím. Jako
vstupní zařízení poskytují programu data z okolí, na základě kterých se pak program
rozhoduje, co dál dělat. Jako výstupní zařízení, která demonstrují činnost programu navenek,
můžeme označit všechny tři motory a obrazovku NXT terminálu, na které lze vyobrazovat jak
textové, tak grafické informace. Mezi výstupní zařízení počítáme i reproduktor terminálu.
Při sestavování robota se prosím držte základních připojení motorů a senzorů k NXT
terminálu, která dodržuji i ve všech programech sbírky. Vyhnete se tak zbytečným hledání
chyb v programu, které by vycházejících pouze ze špatného zapojení:
Vstupní, výstupní zařízení
Obrázek senzoru
Název portu NXT terminálu
pojezdové motory
B, C
doplňkový motor
A
dotykové senzory
dle nastavení programátora
v okně Motors and Sensors
Setup
(touch sensor)
barevný senzor
(colour sensor)
sonar
(ultrasonic sensor)
dle nastavení programátora
v okně Motors and Sensors
Setup
dle nastavení programátora
v okně Motors and Sensors
Setup
Tab. 1 – Vstupní a výstupní zařízení základní sady stavebnice Lego Minstorms NXT 2.0
Obr. 8 ‐ Základní připojení vstupních a výstupních zařízení k portům NXT terminálu Shrnutí kapitoly:
Na úvod jsme si ukázali, co všechno si máme pro naši práci připravit.
Nyní se Vám začnou pootevírat dvířka do světa programování. Protože se ale
žádná pořádná práce neobejde bez základních teoretických znalostí, bude právě
následující kapitola teoretického rázu. Potom už ale rovnýma nohama do
programování.
Kapitola 2. Algoritmus a jeho vlastnosti
Co se naučíte:
V následující kapitole se dozvíte, co je to algoritmus, jaké musí splňovat vlastnosti,
aby se dal skutečně za algoritmus považovat. Dále si řekneme něco o tom, jaké
existují způsoby zápisu algoritmu a z jakých částí (struktur) se obvykle skládají.
Klíčové pojmy kapitoly:
Algoritmus, konečnost, hromadnost, determinovanost, rezultativnost, vývojový
diagram, sekvence, podmínka, cyklus
Pojem algoritmu
Pod pojmem algoritmu rozumíme posloupnost příkazů (jakýsi postup), která vede
k nějakému výsledku. Ač je dnes pojem algoritmu automaticky spojován s programováním,
nemusí se k němu nutně vázat. Příkladem může být recept, kdy procházíte od začátku do
konce sérií úkonů, na jejichž konci se nachází výsledek v podobě nějaké dobroty. I návod,
pomocí kterého skládáte nábytek, nebo třeba vašeho robota, se dá nazvat algoritmem.
Vlastnosti algoritmu
Nyní, když máte aspoň malou představu o tom, co to algoritmus je, upřesníme si jeho
definici výpisem charakteristických vlastností algoritmů:
Konečnost
Každý algoritmus končí po konečném počtu kroků.
Kdybych chtěl např. zjistit, pomocí kolika 2dl skleničkami naplním 1l nádobu vodou,
naplnil bych skleničku a vylil do velké nádoby, a to tolikrát, dokud by se nádoba nenaplnila.
Důležité přitom je, že by došlo k naplnění nádoby, a tudíž ukončení práce.
Pokud bych volil početní řešení, převedl bych nejprve 2dl na 0,2l, a následně vypočítal
1l / 0,2l. Tak bych zjistil, že výsledek je 5 a postup by byl také ukončen.
Existují i nekonečné výpočetní metody. Říká se jím reaktivní procesy. To proto, že
reagují na podněty z okolí, např. na stisk tlačítka. Nyní Vám prozradím, že i některé programy
psané pro našeho robota, budou reaktivní procesy obsahovat. Tím, že nesplňují vlastnost
konečnosti, se ale nemusíte trápit. Reaktivní procesy se dají za jistý specifický druh algoritmu
pokládat, navíc existují krajní způsoby, jak tento proces ukončit.
Hromadnost
Každý algoritmus se musí správně vykonat pro jakákoli data splňující vstupní
podmínku.
Napsat algoritmus pro dělení dvou čísel by asi neměl moc využití, kdyby uměl dělit
např. jen čísla 6 a 3. Musí fungovat pro jakákoli čísla, která mu uživatel zadá. Co když ale
uživatel zadá jako dělitel číslo 0, kterým dělit nelze? Právě proto je v definici použit onen
dodatek: „…data splňující vstupní podmínku.“. Nula zjevně nesplňuje vstupní podmínku pro
dělitele. I tak by se měl programátor postarat o to, aby se algoritmus po zadání podobné
hodnoty vhodně zachoval, např. upozornil uživatele na chybné zadání.
Determinovanost
Algoritmus musí být definovaný přesně a jednoznačně. V každém kroku musí
algoritmus jednoznačně vědět, kterou cestou se vydat.
Představte si, že byste si sedli k televizi a dálkový ovladač Vás najednou přestal
poslouchat. Např. by po zvolení kanálu č. 1 ne vždy naskočilo správné vysílání. Nebo byste
na kávovaru zvolili konkrétní přípravu kávy a on by ji začal přelévat studenou vodou. Takové
„nehody“ by byly asi pořádnou zkouškou pro vaše nervy. Zmíněná zařízení jsou naštěstí
naprogramována tak, že vždy přesně vědí, jaká je posloupnost jejich pracovních úkonů a při
stejném zadání vždy poskytnou stejný výsledek. A takový by měl být každý algoritmus.
Rezultativnost
Algoritmus vždy poskytne řešení (neboli výstup), tedy výsledek své činnosti.
Když vaříte a procházíte algoritmem – receptem, děláte to za účelem výstupu, tedy
oběda. A když se oběd spálí? Inu to také můžeme považovat za výstup. Znovu připomínám
příklad s dělením dvou čísel, kde může být řešením jak výsledek dělení, tak informace o
chybně zadaných vstupních údajích.
Zápis algoritmů
Algoritmus je postup sloužící k dosažení nějakého výsledku, a proto je potřeba umět
jej správně popsat. Mezi nejjednodušší způsoby zápisu algoritmů patří slovní a písemné. Jde
o situace, kdy nám druhá osoba řekne, nebo napíše, co máme udělat. Nejlepší jsou
samozřejmě formální popisy, o kterých se již nedají vést velké spory. Často však rozumíme i
prostému vysvětlení. Tento způsob prezentace algoritmů je však naprosto nevhodný pro účely
programování. Za prvé neexistuje přesný způsob zápisu (dva lidé nás mohou požádat o totéž
různým způsobem), ale hlavně, nejsme zvyklí v něm nemluvit tak „doslovně“, jak to přesné
algoritmy vyžadují. Pokud např. sedím za stolem a někdo mi dá příkaz: „Rozsviť světlo!“, už
mi neříká, že se musím odsunout od stolu, vstát, otočit o x stupňů, popojít o y kroků,
natáhnout ruku pod úhlem z stupňů zatlačit na vypínač. Automaticky vím, co musím vykonat
pro splnění úkolu a člověk, který mi to přikázal, s tím také počítá. Ale od programu jaksi nic
předpokládat nejde. Ten ví pouze to, co mu napíšeme.
Pro účely programování musely logicky vzniknout jiné způsoby zápisu –
programovací jazyky. Ty jsou přesně definované množinou příkazů a pravidel, jak příkazy
používat. My se budeme v této učebnici orientovat na programovací jazyk C#. Ten patří mezi
tzv. vyšší programovací jazyky (stejně jako např. další verze jazyku C, Pascal a další).
Hardware počítače ale příkazy těchto jazyků nezná. Ten potřebuje univerzálnější, a
hlavně strojově akceptovatelnější nižší programovací jazyk, což je jazyk, který dokáže
pracovat se strojovým kódem. Programy vyšších programovacích jazyků se proto musí do
nižších jazyků překládat, aby je byl hardware schopen zpracovat. K tomu slouží tzv.
kompilátory a interpretery.
Aby se mezi sebou programátoři pracující s různými programovacími jazyky
domluvili, byl vytvořen univerzální způsob zápisu algoritmů, kterému se říká vývojový
diagram. Zapisuje se pomocí grafických značek (kroužky, obdélníky, kosočtverce,
kosodélníky) na papír nebo do speciálních programů. Grafické značky reprezentují základní
příkazy, uvnitř nichž je napsán jejich přesný význam. Jsou propojeny šipkami, které naznačují
průchod diagramem. Příklad takového vývojového diagramu můžete vidět na Obr. 9.
Začátek
čti: číslo číslo < 0 číslo = ‐ číslo vypiš: číslo Konec
Obr. 9 ‐ Příklad vývojového diagramu pro výpočet absolutní hodnoty čísla
Základní algoritmické struktury
Algoritmická struktura je způsob zápisu algoritmu. V programování se setkáváme se
třemi základními algoritmickými strukturami: sekvencí, podmínkou a cyklem. Protože je
mým cílem, abyste se v rámci učebnice seznamovali s programováním skrze praktické
příklady, řekneme si zatím o daných strukturách jen velmi obecně. Nebojte, podrobnějšího
výkladu se dočkáte, až budete postupovat učebnicí.
Sekvence
Sekvence se vyskytují v každém algoritmu, avšak algoritmy, které jsou čistě sekvenční
(bez ostatních struktur) potkáváme pro svou jednoduchost velmi zřídka. Jedná se o zápis
několika po sobě jdoucích kroků. Ty se vykonávají v přesně daném pořadí a žádný z nich není
vynechán. Za sekvenci můžeme považovat už tolikrát zmiňovaný recept (znovu si přečtěte
předchozí větu a pochopíte).
Podmínka
Podmínka je místo v algoritmu, kde je na základě podmínky jednoznačně rozhodnuto,
kterou cestou se bude algoritmus dále ubírat. Příkladem ze života může být hod mincí. Pokud
si např. házíte, zda půjdete do kina, nebo do divadla, přisoudíte nejprve jednoznačně ke každé
možnosti stranu mince. Algoritmus začíná hodem, při kterém padne jedna ze dvou možností.
Nastává vyhodnocení na základě podmínky, která jednoznačně říká, co se má dělat v případě,
že padne orel, či panna. Dále už se algoritmus zabývá jen buď cestou do kina, nebo cestou do
divadla.
Cyklus
Cyklem nazýváme algebraickou strukturu, která má na starost opakování posloupnosti
příkaz. V některých případech je počet opakování přesně daný, jiné cykly opakují své příkazy,
dokud není splněna nějaká podmínka.
Velmi specifickým druhem cyklu je nekonečný cyklus, který slouží pro testování, zda
byla splněna podmínka. Příkladem budiž klávesnice, ve které se stále dokola (pomocí cyklu)
testuje, zda došlo ke stisku klávesy. V případě detekce je zjištěno, která klávesa byla stisknuta
a příslušný znak se vypíše na obrazovku. Pak se v testování pokračuje. O tomto speciálním
cyklu se rozepisuji, protože v této sbírce s ním budete pracovat. V našich programech bude
nekonečný cyklus detekovat stisknutí dotykových senzorů robota.
Shrnutí kapitoly:
Abychom mohli předpis nazvat algoritmem, musí splňovat vlastnost konečnosti,
hromadnosti, rezultativnosti a determinovanosti. Výjimečný případ nastává u tzv.
reaktivního procesu, který, ač nesplňuje podmínku konečnosti, můžeme za
algoritmus považovat.
Algoritmy můžeme zapsat různými způsoby. Z odborného hlediska by však měl
být tento zápis formalizován. Tyto zápisy mohou být buď obecného (vývojové
diagramy) nebo konkrétního charakteru (programovací jazyk).
Nejjednodušším algoritmům, které vykonávají jednoduché za sebou jdoucí příkazy,
říkáme sekvence. Pokud se musí program rozhodovat, kterak dál postupovat,
využije podmínky. Cyklus poslouží pro případ, že potřebujeme jistou část kódu
několikrát zopakovat.
Kapitola 3. První příklad v prostředí Robotc
Co se naučíte:
Ukážeme si první sekvenční algoritmus – pojezd robota.
Na příkladu si vysvětlíme zapojení a ovládání motorů robota, řekneme si, jaká jsou
pravidla při psaní programu, co je to kompilace a jak program nahrát do NXT
terminálu.
Dále se dozvíte, jak se program chová, má-li v sobě chybu a jak Vám může Robotc
pomoci ji napravit.
Klíčové pojmy kapitoly:
kompilace, syntax, sémantika
Nové příkazy:
task main( )
hlavička hlavního programu
motor( );
nastavení výkonu motoru
wait1Msec( );
časová prodleva programu
Programování motorů
Ke stavebnici jsou přiloženy celkem 3 motory. V sestavení vozidla byste měli mít dva
pojezdové motory připojeny k portům B a C NXT terminálu. V programu se na ně budete
odkazovat podle písmena portu, ke kterému jsou připojeny. Motor připojený k portu B se
bude v programu jmenovat motorB, obdobně to platí i pro ostatní motory.
Nyní budeme chtít naprogramovat jízdu robota v délce 3 vteřin. Otevřete si program
Robotc, vytvořte nový projekt a napište do editoru kódu následující příkazy:
task main() { motor(motorB)=50; motor(motorC)=50; wait1Msec(3000); } Struktura programu
Na základě našeho malého příkladu si nyní řekneme něco o struktuře programu.
Každý program, který napíšete, bude začínat stejným řádkem, a to:
task main() Jedná se o hlavičku hlavního programu.
Následovat vždy budou v páru zapsané složené závorky, které ohraničují tělo hlavního
programu. Mezi nimi bude napsána posloupnost příkazů. Všimněte si polohy závorek vůči
ostatním příkazům. Vím, že budete mít od začátku co dělat s příkazy a logikou programů,
avšak důrazně doporučuji naučit se správně program zapisovat. Bude-li nějaká ze závorek
trochu víc vlevo nebo vpravo, nebo nebudou-li příkazy pod sebou, ale za sebou, nebude to mít
vliv na funkčnost programu, rapidně to však sníží jeho přehlednost a čitelnost. To poznáte, až
budou Vaše programy složitější a složitější.
Složené závorky ohraničují skupinu příkazů a vyskytují se bezprostředně za určitými
typy příkazů. V tomto příkladu se jedná o příkaz task main(), později to bude např. příkaz if.
První složená závorka se vždy píše přesně pod první znak příkazu, ke kterému patří. Po stisku
Enter můžete sledovat, že se kurzor na novém řádku odsadí o dva znaky doprava oproti
závorce. Tam přesně jej chceme chtít. Tam pište své příkazy. Každý napsaný příkaz ukončete
středníkem. Až budete na posledním řádku psát ukončující složenou závorku daného bloku,
uvidíte, že sama přeskočí na své místo, tedy pod závorku, která daný blok začíná. Teď si
můžete říct, že stačí pouze mačkat Enter a Robotc si odsazení řádků projektu obhospodaří
sám. A měli byste pravdu. Praxe však vypadá tak, že se stále někde něco dopisuje, přeskupuje
a mění, takže na pochvíli si budete muset odsazení příkazů stejně hlídat sami.
Program uložte pod názvem „Program 1 – Pojezd“. Vytvoříte tak soubor s příponou
„.c“. Příkazy si podrobně vysvětlíme později.
Kompilace programu
V horní části menu Robot programu Robotc se nacházejí dvě položky: Compile and
Download Program a Compile Program.
Obr. 10 ‐ Kompilace programu Slovíčko Compile se do češtiny překládá jako kompilace. Kompilace je funkce, kterou
provádí překladač (neboli kompilátor). Jedná se o převod programu vytvořeného ve vyšším
programovacím jazyce do strojového kódu. Za vyšší programovací jazyky můžeme považovat
C, C++, C#, Java, Pascal (a další). Tyto jazyky procesory neznají. Proto je potřeba překladu
do strojového kódu, aby si program s hardwarem rozuměl.
Kompilátor vždy přeloží program celý od začátku do konce (na rozdíl od programů
s obdobnou funkcí – interpreterů).
Zatímco položka menu „Compile“ program pouze zkontroluje a přeloží, položka
Compile and Download Program jej navíc nahraje do NXT terminálu. Ten musí být během
nahrávání zapnutý a připojený k počítači.
Aby se program v pořádku přeložil, musí být napsán bez syntaktických chyb.
Chyby programů
Nikdo není neomylný a každý programátor děla chyby. Svých chyb jsou si vědomy i
velké softwarové společnosti, které vydávají zkušební beta verze, aby testováním skryté
nedostatky odhalily. A co se neodhalí v beta verzi, to vyspraví opravné balíčky.
Vy se budete s chybami potýkat také. I když to samozřejmě nebude v tak masivním
měřítku, bude to chtít hodně zkušeností, než se naučíte na chyby pružně reagovat. Nenechte se
tím ale odradit. To je úděl každého programátora.
Programové chyby dělíme na dva základní typy:
Syntaktické chyby jsou prohřešky proti gramatice jazyka. Pokud např. místo příkazu
„motor(motorB);“ napíšete příkaz „moter(motorB);“, jedná se o syntaktickou chybu. Pokud
byste zapomněli za příkaz napsat středník, nebo vložili do závorky výraz, se kterým příkaz
nebude umět pracovat, bude se také jednat o chybu v syntaxi. Stejně tak můžete za
syntaktickou chybu považovat neuzavřenou závorku.
Syntaktická chyba se nepozorností nebo překlepem vyrobí velmi snadno. Naštěstí pro
nás, je také velmi snadno opravitelná. Při kompilaci na něj program upozorní. V dolní části
okna Robotc se pod sebe vypíše, na jakých řádcích jsou chyby a jakého typu. Kritické chyby
bránící spuštění programu jsou označeny červeným křížkem. Jednodušší chyby, které si
kompilátor umí opravit sám, jsou označeny křížkem žlutým, i ty je však dobré opravit ručně.
Vyzkoušejte si výše napsaný program zkompilovat přes položku Compile program.
Kompilátor by neměl hlásit žádnou chybu (viz. Obr. 11).
Obr. 11 ‐ Kompilace syntakticky správně napsaného programu Nyní přepište první příkaz motor na příkaz moter. Opětovná kompilace upozorní na
neznámou proceduru na třetím řádku. Tuto chybu označí za kritickou, tedy červeným
křížkem. Na tuto chybu se mohou „nabalit“ i další, které však automaticky zmizí s opravou
chyby hlavní. Situaci ukazuje Obr. 12.
Obr. 12 ‐ Ukázkový příklad syntaktické chyby Opravte chybu, kterou jste schválně vyrobili před chvílí a vyrobte jinou. Smažte
středník za prvním příkazem motor a sledujte, jak kompilátor chybu ohlásí. Kritická chyba se
dá přeložit jako chybějící (očekávaný) středník. Kompilátor však ukazuje ne na řádek
s chybějícím středníkem, nýbrž na řádek pod ním (Obr. 13). To je specifické pro chybu tohoto
typu. Překladač totiž hledá středník tak daleko, kam až sahá následující příkaz. Proto chybu
najde až těsně před ním.
Obr. 13 ‐ Specifický ohlas syntaktické chyby ‐ chybějícího středníku Vyzkoušíme si vyrobit poslední chybu. Tentokrát ale středník vymažeme za
posledním příkazem. Na Obr. 14 vidíte, že kompilátor tuto chybu za kritickou nepovažuje. Jak
je to možné? Poslední příkaz před koncem bloku (před každou pravou složenou závorkou)
totiž nemusí být zakončen středníkem. Reakce kompilátoru je, jak je z obrázku patrné, taková,
že chybějící středník sám nahradí.
Obr. 14 ‐ Jednoduché syntaktické chyby, které si kompilátor sám opraví, jsou označeny žlutým křížkem Sémantické chyby jsou bohužel horší v tom, že nás na ně kompilátor neupozorní.
Jedná se o chyby ve významu. Tyto chyby se projeví až při testování programu, ať už
neočekávanou chybou a havárií programu, nebo nekorektními výsledky funkcí (např. 3 + 7 =
15). Nalézt je, a opravit, už je složitější, protože to vyžaduje ponořit se do logiky programu.
Nahrání programu do NXT terminálu a jeho testování
Zapněte NXT terminál oranžovým tlačítkem a připojte jej USB kabelem k počítači.
Program 1 – Pojezd zkompilujte a nahrajte do terminálu pomocí položky Compile and
Download Program, která se nachází v nabídce Robot (nebo klávesou F5).
Umístěte robota tak, aby měl kolem sebe volné místo na jízdu, stiskněte tlačítko Start
v okně ukazující Obr. 15 a sledujte jeho činnost.
Obr. 15 ‐ Okno Program Debug Předtím, než si kód rozebereme, vyzkoušejte si, jak bude robot reagovat na následující
změny. Po provedení každé změny musíte program uložit, klávesou F5 nahrát do NXT
terminálu a spustit jeho provádění tlačítkem Start. Sledujte, jak změny ovlivňují chování
robota. Správnost svého pozorování si můžete porovnat s klíčem v zadní části učebnice.
Testování příkazů motor a wait1Msec
Otevřete si „Program 1 – Pojezd“ a vyzkoušejte si, jak se změní chování robota po
těchto
programových úpravách:
Cvičení 1
1. V původním příkladu změňte čísla 50 na čísla 100.
2. Změňte pouze jednu hodnotu 50 na 100, u druhého příkazu ponechte
hodnotu 50.
3. V původním příkladu změňte hodnotu u posledního příkazu z 3000 na
6000.
4. Vymažte celý příkaz wait1Msec(3000);
Příkazy: motor, wait1Msec
První dva příkazy programu „Program 1 – Pojezd.c“ slouží k nastavení výkonu
motorů. Obecný zápis tohoto příkazu je:
Příkaz pro nastavení výkonu motoru
motor(motorX)=výkon; Rozbor příkazu
Písmeno X se nahrazuje písmenem A, B, nebo C (podle toho, k jakému portu
terminálu je motor připojen). Za výkon se dosazuje číslo, které označuje
procentuální výkon motoru. Nejvyšší číslo, které lze dosadit, je 100 - motor tehdy
pracuje na 100% výkon. Nejnižší možný výkon je naopak -100, což znamená
100% výkon v opačném směru otáčení. Vozidlo tedy jede pozpátku. Chcete-li
motory zastavit, dosadíte za výkon číslo 0.
Pokud má vozidlo 2 motory, je potřeba oba motory nastavit na stejnou hodnotu,
chceme-li, aby jelo rovně dopředu nebo dozadu. Při nastavení odlišných hodno se robot otáčí.
Nastavíte-li např. levému motoru vyšší výkon, otáčí se rychleji, než motor pravý a robot se
tím pádem otáčí na pravou stranu.
Poslední příkaz programu je určen pro časovou prodlevu programu a obecně vypadá
takto:
Časová prodleva
Wait1Msec(čas); Rozbor příkazu
Časová prodleva se udává do závorky v jednotkách milisekund. Pokud chcete např.
časovou prodlevu 1 sekundu, do závorky napíšete číslo 1000.
Časová prodleva se nejčastěji využívá proto, aby vymezila čas, po který se projevuje
skupina předchozích příkazů, v našem případě, jak dlouho jsou motory aktivní. Kdyby náš
program neobsahoval příkaz wait1Msec, po aktivaci motorů by okamžitě následoval konec
programu. Při rychlosti, jakou se příkazy provádějí, by totiž program skončil dřív, než by se
motory stačily roztočit. To jste si ostatně mohli vyzkoušet u cvičení k tomuto příkladu.
Nenabuďte ale mylného dojmu, že časová prodleva vyměřuje čas pro práci
motorů. Motory nepřestaly po 3 sekundách prodlevy pracovat, protože by je zastavil
příkaz wait1Msec. Tento příkaz slouží pouze jako přestávka programu před
vykonáváním dalších příkazů. Motory se v našem příkladu zastavily proto, že za
příkazem wait1Msec už nenásledovaly příkazy další a program došel na svůj konec.
Pokud by za časovou prodlevou následovaly další příkazy, vykonávaly by se
s třísekundovým zpožděním, ale motory by přitom pořád běžely. Nechcete-li, aby se při
vykonávání dalších příkazů motory stale točily, musíte je po uplynutí prodlevy zastavit:
task main() { motor(motorB)=50; //rozběhnutí motorů motor(motorC)=50; wait1Msec(3000); //3sekundová prodleva motor(motorB)=0; //zastavení motorů motor(motorC)=0; //zde by následovaly další příkazy } Komentáře programu
Jistě jste se zamýšleli nad tím, co znamenají ona dvě lomítka na několika částech výše
napsaného kódu. Jedná se o komentáře. Pomocí nich si můžete program jednoduše popsat
přímo v kódu, abyste věděli (buď okamžitě, nebo za nějaký čas), co jaká část program dělá.
Komentář se v programu píše vždy za dvě lomítka. Toto předznačení je informací pro
kompilátor, že následující text není příkazem. Bez předznačení by se kompilátor snažil Váš
komentář neúspěšně přeložit a ohlásil by chybu programu.
Dvě lomítka lze použít pouze bezprostředně před jednořádkovým komentářem. Pokud
byste potřebovali napsat komentář na více řádků, musíte jej na začátku i na konci uzavřít
pomocí znaku lomítka a hvězdičky:
/* Jsem komentář, který přesahuje přes dva nebo více řádky. Musíte mě označit na začátku i na konci, aby kompilátor věděl, kde končím a kde začínají další příkazy. */ Shrnutí kapitoly:
Každý program pro Robotc začíná hlavičkou hlavního programu „task main( )“. Za
tímto příkazem následuje blok dat ohraničený složenými závorkami.
Pro přehlednost programového kódu je vhodné dodržovat zavedenou formu zápisu,
u které každý nový programový blok způsobí odsazení jeho vnitřních příkazů
doprava oproti předchozímu textu. Je také vhodné si kód okomentovat komentáři.
Před nahráním programu do NXT terminálu dochází k jeho přeložení do strojového
kódu – tzv. kompilaci. Krom překladu nám kompilace vyhledá syntaktické
(gramatické) chyby. Sémantické (logické) chyby se však projeví až při testování
programu a programátor musí jejich zdroj hledat sám.
Kapitola 4. Příklady na jízdu
Co se naučíte:
Základní informace pro psaní programu a hledání chyb jste získali v předchozí
kapitole. V této kapitole si je osvojíte na několika cvičeních. Detailněji si
rozebereme příkaz pro nastavení výkonu motorů.
Otáčíme robotem
Na základě předchozího příkladu už víte, jak naprogramovat zabočení robota. Oběma
motorům dáte kladné otáčky, přičemž jednomu z nich nastavíte vyšší výkon, než druhému.
Motoru, který je na straně zabočení, nastavíte zpravidla výkon 0, druhému motoru jakýkoli
kladný výkon. Jak ale zajistit otočení na místě?
Otevřete si z CD soubor „Program 2 - Otočení na místě“ a vyzkoušejte si jej. Kód
programu vypadá následovně:
task main() { motor(motorB)=50; motor(motorC)=‐50; wait1Msec(1000); } Možná byste na to přišli sami. Stačí nastavit jednomu motoru kladné otáčky o určitém
výkonu, druhému pak záporné otáčky o stejném výkonu. Takovéto protichůdné otáčení
způsobuje otáčení robota na místě.
O kolik stupňů se ale robot otočí? Na to bohužel neexistuje snadná odpověď. Úhel
otočení závisí na výkonu motorů, na době, po kterou se má robot otáčet a na tření působící na
pojezdové pásy, tudíž na povrchu podložky, na které je robot umístěn.
Testováním jsem zjistil, že při 50% výkonu motorů trvá robotovi s pojezdovými pásy,
který je umístěn na papírové podložce, 1 sekundu (1000 ms), než se pootočí o 90 stupňů.
Z toho byste mohli mylně usuzovat, že při 100% výkonu bude doba otočení 500 ms. Bohužel,
mezi výkonem motorů a časem potřebným k pootočení neexistuje nepřímá úměra. Ostatně si
to můžete sami ověřit úpravou výchozího programu. Proto není od věci zapsat si výsledky
podobných cvičení, jako je následující. Když později budete vytvářet programy s pojezdy o
konkrétní vzdálenosti, či otočkami o konkrétní úhel, z poznámek si budete moci čas pojezdu
pro danou činnost a výkon motorů odvodit.
Otočka o 360 stupňů
Pomocí pokusů určete, jak dlouho trvá robotovi s pojezdovými pásy pootočení o
360
stupňů, stojí-li na dřevěné podložce, pro tyto výkony motorů:
Cvičení 2
1. Jeden motor 30% a druhý motor -30%.
2. Jeden motor 50% a druhý motor -50%.
3. Jeden motor 100% a druhý motor -100%.
Tam a zpět
Vytvořte a otestujte příklad, ve kterém jede robot 4 vteřiny směrem dopředu, otočí
se
o 180 stupňů a vrátí se na místo, odkud vyjel. To vše při 100% výkonu motorů.
Cvičení 3
Pozn. Pokuste se nejprve napsat příklad sami. Pokud si nebudete vědět rady, využijte
nápovědy níže. Pokud se Vám ani přesto nepodaří cvičení po delší době vyřešit, využijte klíče
v zadní části učebnice.
Do klíče se podívejte i přesto, že se Vám příklad vyřešit podaří. Možná zjistíte, že
k jeho napsání potřebujete méně příkazů, než jste si mysleli.
Nápověda: Program se bude skládat ze tří částí. První a poslední část se shodují
(jízda směrem dopředu pomocí nastavení výkonu motorů a nastavení časové prodlevy).
Prostřední (otáčecí) sekvence je analogická předchozímu příkladu.
Jízda městem
Souhrnné
cvičení 1
Teoretická
východiska
Pomůcky
Zadání
Nakreslete si na papír jednoduché město a vytvořte program, který provede robovozidlo skrz něj ze startovního do koncového bodu – garáže. Do garáže ať vozidlo
zacouvá.

znalost základní struktury programu

příkaz pro spuštění motorů stavebnice s požadovaným výkonem

příkaz pro časovou prodlevu

robot Lego Mindstorms v sestavení vozidlo (stačí základní, ale může být
jakékoli jiné)

papír o rozměru cca 0,5 x 1m

fixy

různě velké krabice (nepovinné)
1. Fixy si namalujte na papír schéma „bludiště“, podobné, jako na obrázku.
Krom startovacího a cílového bloku (garáž) jsou na nákresu obdélníky
s překříženými čarami. Ty představují domy, které bude muset robot objet.
Tip 1: Pokud chcete, můžete nakreslit na prázdná místa ulici a domy
vyrobit z krabic. Vše bude vypadat zajímavěji a „město“ určitě najde
uplatnění i v jiných příkladech.
Tip 2: Pojezdovou plochu si můžete vytvořit i jinou, dbejte však na to, aby
robot během své cesty aspoň 3x zatáčel.
2. Vytvořte nový program
s názvem „Souhrnné cvičení 1
– Průjezd městem“ a
naprogramujte průjezd ulicí
města od startu až do garáže.
Těsně před garáží, ať se
vozidlo na místě otočí o 180° a
do garáže zacouvá. Rychlost
jízdy nastavte na 30% výkonu.
GARÁŽ START Shrnutí kapitoly:
Tato kapitola byla spíše praktického rázu. Především jsme si podrobně rozebrali
příkaz pro nastavení výkonu motorů robota.
Pokud jste předchozí příklady zvládli, můžete si pogratulovat. Pro začínajícího
programátora totiž není nic důležitějšího, než pevný a jistý programátorský základ,
na kterém se dá dále stavět.
Kapitola 5. Zvuky
Co se naučíte:
Tato kapitola pojednává o přehrávání zvuků přes reproduktor NXT terminálu.
Naučíte se pár základních příkazů, a také způsoby, jak nové zvuky do terminálu
nahrát.
Nové příkazy:
PlaySound( název_zvuku)
přehrání předdefinovaného zvuku
PlaySoundFile(„název_zvuku“);
přehrání nahraného zvukového souboru
Příkaz PlaySound
Zvuk se přehrává dvěma různými způsoby. První z příkazů vypadá následovně:
Přehrání předdefinovaného zvuku
PlaySound(název_zvuku); Rozbor příkazu
Používá se tehdy, chcete-li přehrát jeden z předdefinovaných zvuků. Bohužel, NXT
terminál jich obsahuje jen devět.
Vytvořte si program Play_sound a vložte příkaz PlaySound( ). Obecně máte při
vkládání jakéhokoli příkazu dvě možnosti, jak to udělat. Buď jej přímo napíšete, anebo si jej
najdete v panelu Function Library (viz. Obr. 16).
Obr. 16 – Příkaz můžete najít v panelu Function Library a přetáhnout do editoru kódu Obr. 16 ‐ Vložení příkazu PlaySound() z Function Library Pokud jste příkaz vložili druhým způsobem, vymažte slovo sound a vepište název
vybraného předdefinovaného zvuku. Pokud neznáte jejich názvy, můžete si zvuk vybrat ze
seznamu. Stiskněte levým tlačítkem mimo příkaz, a potom umístěte kurzor zpět, mezi prázdné
závorky příkazu PlaySound( ). Měl by se Vám ukázat seznam zvuků, ze kterého si stačí
vybrat dvojklikem myši, jak to ukazuje Obr. 17.
Obr. 17 ‐ Výběr zvuků do příkazu PlaySound() Vyberte zvuk „soundBeepBeep“ a program uložte pod názvem „Program 3 Přehrávání PlaySound“. Program zkompilujte a nahrajte do terminálu. Spuštěním si ověřte,
že… nefunguje 
Z reproduktoru se nic neozývá, protože program zase pádí dopředu rychleji, než
bychom potřebovali. Příkaz PlaySound(soundBeepBeep) se sice provede, ale dřív, než se stačí
zvuk přehrát, program se vypne. Je to, jako byste si v CD přehrávači našli skladbu, kterou
chcete poslouchat, zmáčkli jste Play, ale vzápětí vypnuli přehrávač hlavním tlačítkem. Co ale
udělat proto, aby se skladba přehrála? Správně, dáme jí čas. První možností je umístit za
příklad dostatečně dlouhou časovou prodlevu. To od nás vyžaduje vědět, jak je zvuk dlouhý.
Mnohem lepší je ale vložit za příkaz PlaySound následující cyklus:
while(bSoundActive) {} Ačkoli se budete s cykly podrobně seznamovat až ve druhé části sbírky, bude pro Vás
užitečné, když se tento specifický naučíte nazpaměť. Aby se Vám lépe pamatoval, zkusíme si
jej přeložit do češtiny:
While (zatímco) bSoundActive (je aktivní přehrávání zvuku)… a následuje prázdný
programový blok, který tedy říká: „Nedělej nic“. Tedy vytvoř časovou prodlevu na nezbytně
dlouhou dobu, dokud nedohraje právě přehrávaný zvuk.
Zvykněte si tento příkaz dávat za každý příkaz pro přehrání zvuku, který nemá být
rušen žádnou následující akcí (např. pojezdem). Pokud program přehráním zvuku končí, je
nutné příkaz while(bSoundActive) použít také. Nyní už by se měl program chovat korektně a
vypnout se až po dohrání zvuku.
Kdybyste chtěli, aby se robot po zaznění zvuku rozjel na 4 sekundy o výkonu 50%,
doplnili byste jej takovým způsobem. Doplňte program, uložte jej a ověřte, zda se chová
správně.
task main() { //přehrání zvuku PlaySound(soundBeepBeep); while(bSoundActive); {} //jízda motor(motorB)=50; motor(motorC)=50; wait1Msec(4000); } Pojezd a zvuk
Vytvořte program, ve kterém nejprve robo-vozidlo pojede 5 sekund dopředu 20%
Cvičení 4 výkonem motorů a po zastavení přehraje zvuk „soundDownwardTones“.
Problémy doprovázející příkazy přehráváním zvuku
Pokud se Vám podařilo předchozí cvičení správně naprogramovat, tak Vás chválím.
Rád bych Vás ale upozornil na jednu záludnost, kterou provází přehrávání zvuků. Zkuste
v programu „Cvičení 4 – Pojezd a zvuk“, který jste buď naprogramovali, nebo jej máte
k dispozici na přiloženém CD, změnit výkon pojezdu z 20% na 100%.
Po spuštění zjistíte, že zvuk, který se má po dojezdu přehrát, neslyšíte, nebo jej slyšíte
v pozadí, když vozidlo stále jede. Tato chyba se projeví pokaždé, použijete-li příkaz
přehrávající zvuk za příkazy, které zastavují motory po pojezdu s vysokým výkonem. Jedná
se pravděpodobně o synchronizační chybu NXT terminálu. Pro Vás je především důležitá
informace, že tuto chybu nemáte jako programátoři možnost ovlivnit. Můžete ji však obejít, a
to tím, že za příkazy zastavení motoru vložíte cca 1,5-sekundovou časovou prodlevu, během
níž budou ještě motory dokončovat svůj pojezd.
Program (na CD uložen pod názvem Program 4 - Pojezd s velkým výkonem a
zvukem) tedy bude vypadat následovně.
task main() { motor(motorB)=100; //jízda motor(motorC)=100; wait1Msec(5000); motor(motorB)=0; //pokud nevypnete motory, zvuk nepůjde slyšet motor(motorC)=0; wait1Msec(1500); /*NUTNÁ ČASOVÁ PRODLEVA MEZI PŘÍKAZY ZASTAVUJÍCÍ MOTORY PO POJEZDU S VYSOKÝM VÝKONEM A PŘÍKAZEM PŘEHRÁVAJÍCÍ ZVUK*/ PlaySound(soundDownwardTones); //prehrani zvuku while(bSoundActive); {} } Tuto chybu jsem uvedl záměrně, protože pro toho, kdo o ní neví, je velmi těžko
odhalitelná. Proto, pokud by se Vám někdy nechtěl přehrát zvukový soubor, zkuste si
vzpomenout na tuto část kapitoly. Možná Vám ušetří spoustu času.
Přehrání zvuku ze souboru
Robot dokáže přehrát zvuk i ze souboru: Tento soubor musí mít příponu .rso. Příkaz
má následující syntaxi:
Přehrání zvuku ze souboru
PlaySoundFile(„název_zvuku“); Rozbor příkazu
Zvukový soubor musí mít příponu „rso“.
Název zvuku musí být vypsán včetně přípony a v uvozovkách.
Zvukový soubor musí být nahrán do NXT terminálu. Způsob tohoto nahrání je
obsažen dále v této kapitole.
Máte několik možností, jak se dostat ke zvukům v .rso formátu:
1. Můžete je nalézt ve složce Sounds nainstalovaného software Lego Mindstorms
dodávaného se stavebnicí. Standardní cesta ke zvukovým souborům je:
C:\Program Files\LEGO Software\LEGO MINDSTORMS NXT\engine\Sounds
2. Několik zvukových soborů si můžete stáhnout ze stránek http://mindstorms.lego.com
Je potřeba kliknout na odkaz Funzone, na další stránce na Downloads, a nakonec na
Sounds.
Přímý odkaz na stránku se stahováním je (přístupnost ověřena 1.8.2010)
http://mindstorms.lego.com/en-us/funzone/downloads/default.aspx#Sounds
3. Pomocí konvertovacích nástrojů převést zvukový soubor v jiném formátu (např. mp3)
na formát .rso. Bohužel, převod se vždy musí provést přes formát .vaw (pokud chcete
např. přehrát mp3 soubor, je třeba jej nejprve převézt do .vaw formátu, a následně do
.rso formátu).
Další omezení vyplývá z velmi malé paměti NXT terminálu, která nepojme velké
zvukové soubory, nebo jen v omezeném množství.
Zvukové soubory z bodu 1 a 2 máte k dispozici na CD k této sbírce.
Aby bylo možné přidané soubory v programech využívat, musí být zvuk nahrán
v NXT terminálu. To se děje dvěma způsoby:
1. Nahrát do soubor do složky NXT Systém Files programu RobotC. Zde je standardní
cesta k adresáři:
C:\Program Files\Robotics Academy\ROBOTC for MINDSTORMS\NXT System
Files
Mějme vytvořený, uložený a zkompilovaný program s využitím externího zvukového
souboru. Při nahrání si software zkontroluje, zda se daný soubor nachází v NXT
terminálu. Není-li tomu tak, stáhne si jej sám z výše uvedené složky. Pokud se
nenachází ani v této složce, nahlásí chybu.
2. Přes program Robotc. V menu Robot, NXT Brick, File Management (Obr. 18)
Obr. 18 ‐ Cesta k File Managementu pro nahrání souborů do NXT terminálu V okně File Managementu (Obr. 19) stiskněte tlačítko Download. Najděte soubor,
který chcete nahrát, ve složkách počítače a otevřete. Nakonec stiskněte tlačítko Refresh Files.
Tímto způsobem jste nahráli soubor rovnou do NXT terminálu a je připraven k použití
v programu.
Ve správci souborů si můžete zvuky i přehrávat, mazat je, anebo uvést paměť NXT
terminálu do původního stavu, v jakém byl zakoupen.
Obr. 19 ‐ Okno File Management pro správu souborů NXT terminálu
Pro přehrání zvuku ze souboru je potřeba dodržet stejná opatření, jako tomu je u
příkazu PlaySound. Tedy použít příkaz while(bSoundActive) za příkazem, nemá-li být zvuk
přerušen. Taktéž před příkaz nezapomeňte umístit 1,5-sekundovou časovou prodlevu,
následuje-li za příkazy zastavující motory po pojezdu s vysokým výkonem. Tím předejdete
tomu, že byste zvuk neslyšeli z důvodu dojezdu motorů.
Další příkazy spojené s přehráváním zvuku si můžete prostudovat v nápovědě
programu Robotc.
Kolečko se zvuky
Ať robot řekne na začátku programu „Start“, objede jedno kolečko o poloměru cca
Cvičení 5 10 cm. Po dojezdu ať zavolá „Good Job“ (to abychom se pochválili, jak nám to
programování dobře jde) a program se ukončí.
Pozn. Pro začátek bude potřeba připravit soubory Start.rso a Good Job.rso pro
nahrání do NXT terminálu. Jedná s o zvuky nainstalované se softwarem Lego Mindstorms
dodávaného se stavebnicí. Jak je dohledat a jak připravit pro nahrání do terminálu bylo
popsáno v této kapitole.
Shrnutí kapitoly:
V této kapitole jste se naučili, jakým způsobem naučit robota pípat, hrát, nebo třeba
i mluvit. Buď se jednoduše využije jeden z mála předdefinovaných zvuků, nebo
nahrajete zvuk z externího souboru. Druhá varianta je sice malinko zdlouhavější,
může však učinit Vaše programy mnohem originálnější.
Vedle pohybových a zvukových projevů robota můžeme postavit i další jeho
možnou činnost - zobrazování textu na displeji NXT terminálu. Před jeho
vysvětlením si ale musíme připravit půdu v podobě ´teoretičtější kapitoly a
proměnných.
Kapitola 6. Proměnné a datové typy
Co se naučíte:
Tato kapitola je čistě teoretického rázu a pojednává o proměnných. Proměnné si
můžete představit jako pojmenovaná místa v paměti, do kterých můžete ukládat a
uchovávat různé hodnoty.
Naučíte se, jak vytvořit proměnné takového typu, aby se jim daly přiřadit
informace, jaké potřebujete. A o přiřazení samotném si také povíme.
Klíčové pojmy kapitoly:
proměnná, case-sensitive, datový typ, inicializace, konstanta
Nové příkazy:
datový_typ název_proměnné ;
deklarace proměnné
název_proměnné = hodnota;
přiřazení hodnoty
datový_typ název_proměnné = hodnota_proměnné;
deklarace s inicializací
const datový_typ název_konstanty = hodnota_konstanty; deklarace konstanty
Pojem proměnné a datového typu
Proměnnou v programování nazýváme symbolické označení libovolného prvku
z určité množiny prvků. Prvky patří do dané množiny tehdy, splňují-li nějaké přesně dané
vlastnosti, jsou-li, jinak řečeno, nějakého typu. Proto se těmto množinám říká datové typy.
Abych opět uvedl příklad z reálného života. Představte si, že máte několik kuliček
různých velikostí. Určili jste si datový typ „Malé kuličky“, což je množina takových kuliček,
jejichž průměr je do 1 cm. Krabici ve tvaru krychle o straně 1 cm si nazveme K a řekneme, že
je to proměnná datového typu Malé kuličky. Do krabice K (proměnné) je přípustné vložit
pouze jednu kuličku z dané množiny (datového typu). Pokud bychom chtěli vložit jinou
kuličku z množiny, předchozí umístěná kulička se automaticky z krabice vysype. Kdybychom
potřebovali manipulovat s dvěma kuličkami najednou, potřebovali bychom dvě krabice
(proměnné) označené např. K a L.
Mezi základní datové typy programovacího jazyka C# patří několik typů číselných,
znak, řetězce znaků a logická hodnota.
Chcete li v programu využívat nějakou proměnnou, musíte ji v programu nejprve
vytvořit. A to buď na místě, kde proměnnou potřebujete poprvé, nebo kdekoli v kódu před
jejím prvním použitím. Vytvoření nové proměnné v programu se říká deklarace. Kód
deklarace má následující syntaxi.
Deklarace proměnné
datový_typ název_proměnné; Rozbor příkazu
Název proměnné by se měl odvíjet od jejího účelu.
Datový typ by se měl odvíjet od množiny prvků, které do ní chcete uložit a operací,
které s nimi chcete provádět.
Název proměnné by se měl odvíjet od jejího účelu. Pokud byste např. vytvářeli
program pro základní početní operace mezi dvěma čísly, bylo by vhodné vytvořit tři
proměnné s názvy, jako cislo1, cislo2 a vysledek.
Možná byste mi mohli oponovat, že i kdybyste proměnné nazvali x, y a z, byli byste se
v programu vyznali. Představte si ale, že budete v programu potřebovat proměnných třeba
deset. Pojmenovat je každé jedním písmenem, to byste se orientovali o mnoho hůře, a co
teprve někdo, kdo by se na Váš kód přišel podívat? Vyznat se v něm by trvalo mnohem delší
čas. Za měsíc už byste se v něm nevyznali ani Vy.
Krom udělování správného jména si také zvykněte na jeho specifický zápis.
Pojmenujete-li proměnnou jedním slovem, začněte malým písmenem. Jestliže bude název
víceslovný, skládejte slova za sebe a každé krom prvního začněte velkým písmenem (např.
cenaZaKus, konecnyVysledek, apod.). Dodržovat tento styl zápisu není bezpodmínečně nutné
pro chod programu, ale ulehčí Vám spoustu chybových hlášek kompilátoru. Jazyk C# je totiž
tzv. case-sensitive, to znamená, že od sebe odlišuje velká a malá písmena. Pokud byste např.
deklarovali proměnnou s názvem „vysledek“ a pak byste při práci s ní psali její název jako
„Vysledek“, považoval by ji kompilátor za novou, doposud nedeklarovanou proměnnou a
nahlásil chybu. A ještě jedna připomínka. Budete-li chtít zahrnout do názvu proměnné číslice,
nesmí jimi název proměnné začínat.
Zde je přehled základních datových typů. V deklaraci se využívá informace z prvního
sloupce tabulky.
Datový typ
sbyte
byte
short
ushort
int
uint
long
ulong
float
double
bool
char
string
Název
8-bitová celá čísla se
znaménkem
8-bitová celá čísla bez
znaménka
16-bitová celá čísla se
znaménkem
16-bitová celá čísla
bez znaménka
32-bitová celá čísla se
znaménkem
32-bitová celá čísla
bez znaménka
64-bitová celá čísla se
znaménkem
64-bitová celá čísla
bez znaménka
reálná čísla
Velikost
1B = 8b
Rozsah
-128 .. 127
1B = 8b
0 .. 255
2B = 16b
-32 768 .. 32 767
2B = 16b
0 .. 65 535
4B = 32b
-2 147 438 648 .. 2 147 438 647
4B = 32b
0 .. 4 294 967 295
8B = 64b
-9 223 372 036 854 775 808 ..
.. 9 223 372 036 854 775 807
8B = 64b
0 .. 18 446 744 073 709 551 615
4B = 32b
reálná čísla s větší
přesností
logická proměnná
znak
řetězec (znaků)
8B = 64b
1.5*10 -45 .. 3.4*10 38
(7-8 platných cifer)
5.0*10 -324 .. 1.7*10 308
(15-16 platných cifer)
1B = 8b
2B = 16b
2B * počet
znaků
true nebo false
1 znak z ASCII tabulky
n znaků
Tab. 2 ‐ Tabulka základních datových typů C#
Výběr správného datového typu je velmi důležitý. A nejedná se jen o to, zda se bude
jednat o proměnnou číselného, či alfanumerického charakteru. Musíme dbát i na rozsah dané
proměnné a operace, které s nimi budete chtít provádět.
Představte si, že potřebujete proměnnou, do které se bude ukládat číslo kalendářního
měsíce. Povolené položky jsou tedy celá čísla v rozsahu 1 až 12. Podíváte-li se na rozsah
všech číselných datových typů uvedených v tabulce, zjistíte, že můžete použít prakticky
jakýkoli. My však vyloučíme použití reálných čísel (měsíc 1,4 neexistuje) a čísla o zbytečně
velkých rozsazích. Nakonec vybíráme mezi datovými sbyte a byte. Zvolíme raději byte,
protože záporná čísla využívat nechceme.
Proč jsme ale takovouto vylučovací metodou vybírali vhodný datový typ, když jsme si
řekli, že čísla v požadovaném rozsahu můžeme uložit do jakékoli číselné proměnné?
Podívejte se do třetího sloupce tabulky. Ta udává, kolik paměti bude daná proměnná zabírat.
Někdo by mohl namítat, že máme dnes v počítačích operační paměti o takových kapacitách,
že rozdíl mezi 1B a 4B nic neznamená. Tento přístup ale není hoden dobrého programátora,
který by měl krom správného fungování programu zajistit i jeho co možná nejmenší
paměťovou náročnost.
Přiřazení hodnoty do proměnné
Máme-li někde v programu vytvořenou proměnnou, třeba následovně:
int cislo; můžeme kdekoli dále v programu přiřadit této proměnné konkrétní hodnotu z rozsahu
daného datovým typem. Syntaxe je následující:
Přiřazení hodnoty do proměnné
název_proměnné = hodnota; Rozbor příkazu
V případě, že bych chtěl do naší proměnné cislo vložit hodnotu 50, udělal bych to
příkazem:
cislo = 50; Pokud bych kdekoli dále v programu přiřadil proměnné cislo jinou hodnotu,
automaticky nahradila starou hodnotu 50.
Počáteční inicializace proměnné
Někdy je potřeba vložit hodnotu do proměnné okamžitě po jejím vytvoření.
Takovémuto druhu přiřazení se říká inicializace. Pokud byste měli v úmyslu vytvořit např.
proměnnou mesic datového typu byte a okamžitě mu přiřadit hodnotu 1, máte dvě možnosti,
jak to udělat. První již napsat umíte:
byte mesic; mesic = 1; Druhým způsobem zápisu, který doporučuji používat, má obecný tvar:
Deklarace proměnné a její inicializace
datový_typ název_proměnné = hodnota_proměnné; Rozbor příkazu
Příklad:
byte mesic = 1; Inicializace je důležitá z toho hlediska, že při vytvoření proměnné prakticky
nevíme, co je v ní uloženo. Někdo by si mohl myslet, že tam je nula a s tímto
chybným předpokladem počítat při programování.
Inicializace proměnné má ovšem větší význam, než jen ušetření jednoho řádku kódu.
Předpokládám, že jste si ještě kvůli čerstvosti informací o datových typech nepoložili otázku:
„Co se nachází v proměnné bezprostředně po její deklaraci?“ Je odpověď 0? Či nějaké jiné
číslo? Nebo dokonce písmeno?
Proměnné se vytvářejí v buňkách operační paměti. Tyto buňky, předtím, než jsme si je
zablokovali naším programem, využíval jiný proces a zanechal v nich hodnoty. Pokud
vytvoříme proměnnou s odkazem na danou datovou buňku, přebírá si proměnná hodnotu oné
paměťové buňky. Proto je v některých případech přímo nezbytné, ihned po deklaraci vložit do
proměnné počáteční hodnotu, a nenechat ji „náhodě“.
Typickým příkladem budiž funkce čítače. Pokud byste chtěli počítat, kolikrát bylo za
určitou dobu stisknuto tlačítko, vytvořili byste si nejprve proměnnou, pojmenovanou řekněme
citac. V programu byste vytvořili příkaz, který na každý stisk tlačítka zvedne hodnotu
proměnné citac o jedničku. Zde je naprosto jasné, že pokud bychom proměnnou citac na
začátku neinicializovali na hodnotu 0, mohly by se stisky připočítávat k úplně jiné hodnotě a
výsledkem by bylo špatné číslo. Navíc, při testování se tato chyba vůbec nemusí projevit,
protože v mnoha případech může být hodnota paměťové buňky, na které vytvářím novou
proměnnou, nulová.
Konstanta
Speciálním případem proměnné, která se inicializuje hned při její deklaraci, a poté se
již její hodnota nemění, je konstanta. Deklarace konstanty vypadá následovně:
Deklarace konstanty
const datový_typ název_konstanty = hodnota_konstanty; Rozbor příkazu
Příklad:
const int vyhra = 1000000; S konstantou se v příkladu pracuje stejným způsobem, jako s proměnnou, akorát jí
nelze přiřadit žádná nová hodnota.
Shrnutí kapitoly:
Naučili jste se vytvářet proměnné a naplňovat je hodnotami. Řekli jsme si, co je
inicializace proměnné, a že je často nezbytné nastavení na počáteční hodnotu
provést. Nakonec jste se mohli dočíst o konstantách a jejich deklaraci.
Tato kapitola byla sice více teoretická, ale o to víc si zaprogramujeme v kapitolách
příštích. Než začneme vytvářet komplexnější programy, ve kterých se budou
vyskytovat proměnné, anebo konstanty, budeme se ještě muset naučit, jak je
zobrazit na displeji NXT terminálu.
Kapitola 7. Psaní na displej NXT terminálu
Co se naučíte:
Práci s proměnnými lze nejlépe ukázat s pomocí displeje NXT terminálu. Na tomto
displeji lze psát texty (bohužel jen bez diakritiky, už program Robotc diakritiku při
psaní kódu nepovoluje) nebo nebo vypisovat hodnoty proměnných.
Na displeji lze mimo jiné vykreslovat základní geometrické objekty. V rámci
základní sbírky se však tomuto tématu vyhneme.
Nové příkazy:
nxtDisplayTextLine(číslo_řádku, "text");
vypsání textu
nxtDisplayTextLine(číslo_řádku, název_proměnné);
výpis textové proměnné
nxtDisplayBigTextLine(číslo_řádku, „text“);
výpis větším písmem
nxtDisplayCenteredTextLine(číslo_řádku, „text“);
nxtDisplayCenteredBigTextLine(číslo_řádku, „text“);
výpisy na střed řádku
nxtDisplayTextLine(číslo_řádku,“řetězec_s_formátem_čísla“,název_proměnné);
výpis proměnné v řetězci
eraseDisplay();
vymazání obsahu displeje
Psaní textů
Text se na displej terminálu vypisuje po řádcích. Řádků má terminál celkem 8, avšak
jsou číslovány od nuly. První řádek má tedy číslo 0, druhý řádek číslo 1, atd. Poslední řádek je
osmý a má označení 7. Na to si možná budete chvíli zvykat, ale věřím, že to zvládnete.
Na každý řádek se vejde jen omezený počet znaků. Jestliže dáte vložit text delší, než
se na daný řádek vejde, nedojde k jeho zalomení (podobně jako když píšete v textovém
editoru), ale nevypíše se celý. Proto se displej nepoužívá k zobrazení nějakých souvislých
textů, ale jednoduchých informací, jako výsledek matematické operace, aktuální stav
programu, výkon motorů, apod.
Vypsání textové informace
nxtDisplayTextLine(číslo_řádku, "text"); Rozbor příkazu
V příkazu píšete na první pozici závorky číslo řádku, na který se má psát, a za
čárku pak vepisovaný text V UVOZOVKÁCH.
Pokud budete chtít např. na první řádek displeje vypsat „Ahoj!“, příkaz bude vypadat
následovně:
nxtDisplayTextLine(0,“Ahoj!“); Příkaz si zkuste napsat jako program. Uložte jej pod názvem „Program 5 – Ahoj“ a
otestujte, zda funguje.
Že nefunguje? Ale funguje. Akorát dřív, než stačíte zaznamenat změnu na displeji, tak
se program ukončí a vrátí do menu terminálu. Proto musíme v tomto jednoduchém programu
umístit za příkaz nxtDisplayTextLine příkaz wait1Msec a nastavit časovou prodlevu
v milisekundách před skončením programu. Vyzkoušejte, zda to pomohlo:
task main() { nxtDisplayTextLine(0,“Ahoj!“); wait1Msec(10000); //nápis „Ahoj!“ bude na displeji 10 sekund } Protože už známe pojem proměnné a její deklarace, zkusíme si program přepsat tak,
aby se nevypisoval přímo text „Ahoj!“, ale informace uložená v námi deklarované proměnné
napis. Program si uložte pod názvem „Program 6 - Ahoj jako hodnota proměnné“ a otestujte,
zda funguje dle očekávání:
task main() { string napis; napis = „Ahoj!“; nxtDisplayTextLine(0,napis); wait1Msec(10000); } //deklarace textové proměnné /*nápisy přiřazené proměnným typu string nebo char musí být ohraničeny uvozovkami*/ //zobrazení hodnoty proměnné napis //na displeji uvidíme Ahoj! //„Ahoj!“ bude na displeji 10 sekund Všimněte si, že u předposledního příkazu není slovo napis v uvozovkách. To proto, že
nezobrazujeme přímo text, ale hodnotu textové proměnné. Uvozovky jsme u řetězce použili
už tehdy, když jsme jej vkládali do proměnné napis. Pokud bychom slovo napis vložili uvnitř
zobrazovacího příkazu do uvozovek, zobrazilo by se na displeji slovo „napis“. Jen si to
zkuste.
Vypsání obsahu textové proměnné
nxtDisplayTextLine(číslo_řádku, název_proměnné); Rozbor příkazu
V příkazu píšete na první pozici závorky číslo řádku, na který se má psát, a za
čárku pak název textové proměnné BEZ UVOZOVEK.
Deklarace a vložení textu by se dalo nahradit jediným řádkem (inicializace na
počáteční hodnotu):
string napis = „Ahoj!“; Velikost písma
Standardní velikost písma při použití příkazu nxtDisplayTextLine je 8 pixelů. Příkaz
pro vložení písma dvounásobné velikosti vypadá podobně:
Vypsání textu dvojnásobné velikosti
nxtDisplayBigTextLine(číslo_řádku, „text“); Rozbor příkazu
Příkaz je analogický předchozímu, jen v názvu příkazu je zakomponováno slovo
„Big“. Uvědomte si, že zvětšením písma snížíte počet znaků, které se vejdou na
daný řádek displeje.
Obdobné příkazy můžete využít, chcete-li text vypsat na střed zvoleného řádku:
Vypisování textu na střed řádku
nxtDisplayCenteredTextLine(číslo_řádku, „text“); nxtDisplayCenteredBigTextLine(číslo_řádku, „text“); Rozbor příkazů
Příkazy jsou analogické předchozím, jen v názvech příkazů je zakomponováno
slovo „Centered“.
Do všech příkazů pro výpis textu na displej se zadává číslo řádku. Pokud v kódu dojde
podruhé k vložení textu na stejný řádek, dosavadní text na řádku se kompletně přepíše novým.
Popis jízdy
Otevřete si program „Cvičení 3 – Tam a zpět“ a přeuložte jej pod názvem „Cvičení
Cvičení 6 6 – Popis jízdy“. Doplňte kód tak, aby se sekundu před samotnou jízdou zobrazil
vlevo na prvním řádku displeje (řádku označeném 0!) malý text „Prubeh jizdy:“.
Nápis ponechte vypsaný až do konce programu.
Při pojezdu ať je na středu čtvrtého řádku displeje velkým písmem popsán průběh
jízdy, a to následovně:

při odjezdu nápisem „Odjezd“

při otočce ať nápis „Odjezd“ zmizí (displej tedy zůstane bez popisu
průběhu jízdy)

při návratu nápisem „Prijezd“
Odpočet
Souhrnné
Vytvořte program pro startovací odpočet se zobrazením na displeji, po jehož
uplynutí robo-vozidlo vystartuje vpřed.
cvičení 2

příkaz pro spuštění motorů stavebnice s požadovaným výkonem

znalost příkazů pro vypsání textových řetězců

znalost práce se zvuky
Pomůcky

zvukový soubor Start.rso, který naleznete na CD ke sbírce
Zadání
1. Připravte zvukový soubor Start.rso pro použití v programu.
Teoretická
východiska
2. Zobrazte na středu čtvrtého řádku displeje malým písmem odpočet 3, 2, 1.
Každé z čísel ať je na displeji 1 sekundu.
3. Za odpočtem zobrazte na středu čtvrtého řádku displeje velkým písmem
slovo START a přehrajte zvukový soubor Start.rso.
4. Po doznění zvukového souboru ať robot vyrazí dopředu o 100% výkonu a
zastaví se po 5 sekundách jízdy.
Zobrazování hodnot číselných proměnných
Prozatím jsme se zabývali pouze zobrazováním textových informací na displeji
terminálu. Co když ale budeme chtít zobrazit hodnotu číselné proměnné?
Příkaz pro výpis čísla se liší od výpisu textu počtem parametrů (informací v závorce).
Vypsání proměnné v řetězci
nxtDisplayTextLine(číslo_řádku,“řetězec_s_formátem_čísla“,název_proměnné); Rozbor příkazu
Příkaz pro výpis čísla se liší od výpisu textu počtem parametrů (informací
v závorce).
Za formát čísla můžete vkládat následující znaky:
Označení
formátu čísla
Popis formátu čísla
%d
zobrazujete-li proměnnou typu celé číslo (decimal)
%f
zobrazujete-li proměnnou typů reálné číslo (float)
%e
zobrazujete-li proměnnou typu reálné číslo v tzv. E formě
(např. 423.78 se zobrazí jako 4.2378e+2)
%x.yf
Tato syntaxe se používá pro zobrazení proměnné typu reálné
číslo, přičemž se vypisuje pouze určitý počet celých a
desetinných míst.
Za x se dosazuje počet celých míst, za y počet desetinných
míst, f se ponechává.
(např. při zápisu „%2.4f“ se číslo 12.4551923 zobrazí jako
12.4551)
Tab. 3 ‐ Označení formátu čísla v příkazech vypisujících hodnoty číselných proměnných Takto by vypadal příklad zobrazení čísla 10 vlevo nahoře displeje. Zkuste si jej napsat
a uložit pod názvem „Program 7 - Zobrazení číselné proměnné“.
task main() { byte cislo = 10; //deklarace celočíselné proměnné s počáteční inicializací číslem 10 nxtDisplayTextLine(0,“%d“,cislo); //zobrazení hodnoty proměnné cislo ‐ na displeji uvidíme číslo 10 wait1Msec(5000); //číslo bude na displeji 5 sekund } Ve výše uvedeném příkladu jsme vypisovali pouze hodnotu dané proměnné. Protože
ale každé číslo v reálném světě chápeme v určitém kontextu, často je potřeba vypsat
kombinaci čísla a textu, který by jej okomentoval.
Zde je pár jednoduchých příkladů, abyste věděli, o čem mluvím. V zápisu příkazu se
napíše celý požadovaný výraz v uvozovkách, přičemž na místo, kde je potřeba dosadit
hodnotu proměnné, se napíše označení formátu čísla příslušného datového typu (viz. Tab. 3).
Samotný název proměnné je posledním argumentem v závorce:
Hodnota
proměnné
reálného
datového typu
Kontext
Možnost použití základního příkazu
10 stupňů Celsia stupňů úhlu alfa procent výkonu motoru nxtDisplayTextLine(0,“Venku je %f°C.“, proměnná); 90 100 nxtDisplayTextLine(0,“úhel alfa: %f°“, proměnná); nxtDisplayTextLine(0,“ %fprocentní výkon“, proměnná); Tab. 4 ‐ Zobrazování hodnot číselných proměnných v příslušném kontextu 10 stupňů celsia
Vytvořte proměnnou teplota 8-bitového celočíselného typu byte a inicializujte ji
Cvičení 7 číslem 10. Na prvním řádku NXT terminálu pak na 10 sekund zobrazte nápis „10
stupnu Celsia“, kde 10 je hodnota proměnné teplota.
Při práci s reálnými čísly se v C# používá desetinná TEČKA místo desetinné čárky, na
kterou jsme zvyklí. Tzn. že např. místo 3,14 se musíte naučit psát 3.14. V opačném případě
kompilátor nahlásí chybu. Pro úplnost uvádím příklad, ve kterém se na displej vypisuje
výsledek testu. Vytvořte si jej pod názvem „Program 8 - Skóre testu“ a otestujte funkčnost.
task main() { float skore = 6.8; //deklarace reálné proměnné s počáteční inicializací nxtDisplayTextLine(0,"Prumerne skore"); nxtDisplayTextLine(1,"je %1.1f bodu",skore); nxtDisplayTextLine(2,"z 10."); //na obrazovku se vypíše „Prumerne skore je 6.8 bodu z 10.“ wait1Msec(10000); } A abyste si nějaký program zase zkusili vymyslet sami, naprogramujte následující
cvičení.
Pi
Nadeklarujte reálnou proměnnou cisloPi a inicializujte hodnotou
Cvičení 8 3,14159265358979323846. Vypište na první řádek displeje výraz „pi = 3,14“.
Věřím, že si s tím, jak dlouhé číslo proměnné cisloPi vypsat ve zkrácené formě,
rychle poradíte. A kdybyste přece jen měli nějaké problémy, snad pomůže Tab. 3.
Výkon motorů
Vytvořte program, ve kterém jede robo-vozidlo 5 sekund dozadu výkonem 20%, na
3
sekundy se zastaví, a stejným výkonem dojede dopředu na místo, odkud vyrazilo.
Cvičení 9
Po celou dobu běhu programu musí být v horní části displeje nápis „VYKON
MOTORU“ a zhruba uprostřed displeje informace o aktuálním výkonu motorů.
Výpis více proměnných v jednom řetězci
Pokud byste někdy potřebovali vložit text obsahující více vložených proměnných,
bude příkaz o něco složitější. Ale nebojte se. Stále budeme vycházet z toho, co už znáte.
Celý problém si vysvětlíme na příkladu. Můžete si jej napsat a uložit pod názvem
Program 9 – Fotbal. Úkolem programu je výpis fotbalového skóre. Počet vstřelených gólů je
uchován ve dvou proměnných (pro každý tým jedna).
task main() { byte skoreTymu1 = 2; byte skoreTymu2 = 0; //deklarace dvou celočíselných proměnných s počáteční inicializací nxtDisplayTextLine(0,“%d : %d“,skoreTymu1,skoreTymu2); //na obrazovku se vypíše „2 : 0“ wait1Msec(10000); } Z příkladu je patrné, že v příkazu nxtDisplayTextLine přibylo parametrů. Vypisujemeli pouze jedinou proměnnou, má příkaz právě 3 parametry. S každou další proměnnou jeden
parametr přibývá. Prvním parametrem je, jako vždy, číslo řádku, na který se řetězec vypisuje.
Druhým parametrem je text řetězce, který obsahuje tolik označení formátů (%d, %f, apod.),
kolik je proměnných. Následují čárkami oddělené názvy proměnných, a to v tom pořadí, ve
kterém mají být vkládány do řetězce.
Zobrazení obsahu textových proměnných v řetězci
Pokud má být v řetězci umístěna proměnná typu string, vkládá se do řetězce na její místo zástupné symboly „%s“ (string). Pokud byste např. chtěli ve větě „Úhel gama pravý.“ slovo „gama“ přečíst z proměnné pravyUhel, vypadal by kód následovně: string pravyUhel = „gama“; nxtDisplayTextLine(0,“Uhel %s je pravy.“,pravyUhel); Fotbal
Otevřete si Program 9 – Fotbal, přeuložte pod názvem Cvičení 10 – Fotbal a
upravte
jej dle instrukcí:
Cvičení 10
 Na druhé řádku vycentrujte velký nápis „SKORE UTKANI“.

Informaci o stavu utkání vycentrujte na pátém řádku displeje.

Vytvořte dvě vhodně pojmenované proměnné pro zadání názvů fotbalových
klubů a vložte do nich názvy: „Real“ a „Barcelona“. Zobrazte je nad skóre
tak, jak to ukazuje náhled:
SKORE
Real:Barcelona
Podobně, pokud bychom do řetězce vkládali hodnotu proměnné typu char (znak),
použili bychom zástupné symboly „%c“.
Další způsoby výpisu textových informací na displej
Pro „konzolový“ výpis na displej terminálu existuje ještě jedna sada příkazů. Syntaxe
se krom jiného názvu příkazu liší počtem a významem parametrů. První parametr, který jsme
používali pro číslo řádku, na který se má vepisovat, je nahrazen dvěma parametry, které
zastupují x-ovou a y-ovou souřadnici (v jednotkách pixelů), kde má text začínat:
nxtDisplayStringAt(x‐ová_souřadnice,y‐ová_souřadnice, „textový_řetězec“); Tento příkaz existuje i v dalších modifikacích, jako např. pro psaní velkým písmem, či
s vypisováním řetězců obsahujících proměnné. Tento způsob vypisování uvádím pouze pro
úplnost a nebudu se jím v dalších příkladech dále zabývat.
Vymazání obsahu displeje
Na závěr kapitoly si jen řekneme o příkazu, který se Vám může někdy hodit, když
potřebujete vyčistit displej pro zobrazení dalších informací:
Vymazání obsahu displeje
eraseDisplay(); Rozbor příkazů
Příkaz jednoduše vyčistí obrazovku NXT terminálu ode všech informací, které jsou
na ní aktuálně zobrazeny.
Shrnutí kapitoly:
Jednou z charakteristických vlastností algoritmů je to, že podávají informaci o
výsledku své práce. To se většinou děje vypsáním těchto informací na obrazovku.
Právě proto je konzolový způsob výpisu informací na displej, popsaný v této
kapitole, nepostradatelnou dovedností pro psaní jakýchkoli dalších programů pro
Lego Mindstorms.
Při vypisování hodnot je také nezbytné uvést, čeho se týkají. Např. samotné číslo o
ničem nevypovídá a získává na významu až v uvedeném kontextu. Proto se musí
programátor vcítit do pozice uživatele programu, který potřebuje danou informaci
nejen přečíst, ale i pochopit.
V této kapitole jsme často vypisovali hodnoty číselných proměnných. Proto by
bylo dobré se naučit, jak s těmito proměnnými matematicky pracovat. Pokud Vás
zajímá, jak se to dělá, nezavírejte sbírku a čtěte dál 
Kapitola 8. Početní operace s proměnnými a
konstantami číselných datových typů
Co se naučíte:
Protože se programování váže k výpočetní technice, není vůbec nic divného na
tom, že výpočty jsou jednou z nejčastějších funkcí programování. Uvidíte ale sami,
že to není nic těžkého. Stačí se naučit příkazy pro základní operátory a umět
matematiku 
Klíčové pojmy kapitoly:
inkrementace, dekrementace
Nové příkazy:
výsledek_operace = číslo1 znaménko_operace číslo2;
algebraické operace
číslo1 početní_operace = číslo2;
mat. změna proměnné
cislo ++;
inkrementace
cislo --;
dekrementace
S čísly, potažmo číselnými proměnnými, v jazyce C# můžeme provádět různé
aritmetické operace. Příkaz je jednoduchým přepisem matematického vztahu mezi čísly:
Příkazy základních aritmetických operací
výsledek_operace = číslo1 znaménko_operace číslo2; Rozbor příkazu
Na levé straně se vždy musí nacházet proměnná vhodného datového typu,
kterého nabude výsledek operace. Následuje přiřazovací znaménko rovnosti a dvě
čísla oddělená znaménkem. Znaménka základních aritmetických operací jsou
následující:
Znaménko operace
Název operace
Příklad
+
sčítání
11 + 5 = 16
-
odčítání
11 – 5 = 6
*
násobení
11 * 5 = 60
/
dělení (jsou-li veškeré
proměnné vystupující
ve výrazu datového
typu reálné číslo)
11 / 5 = 2.2
/
celočíselné dělení (jeli aspoň jedna
proměnná ve výrazu
celočíselného
datového typu)
11 / 5 = 2
%
zbytek po
celočíselném dělení
(modulo)
11 % 5 = 1
(11 : 5 se dá napsat jako 2 celé,
zbytek 1)
Tab. 5 ‐ Tabulka základních aritmetických operací Čísla mohou být vyjádřena přímo zapsanými čísly, jako např. v tomto příkladě sčítání:
soucet = 5 + 3; Mnohem častější je však matematická operace mezi dvěma proměnnými:
soucet = scitanec1 + scitanec2; Kombinace konkrétního čísla a číselné proměnné je také možná:
soucet = scitanec + 1; Na pravé straně výrazu se může vyskytovat i více operací najednou. Pořadí operací při
výpočtu je stejné, jako v matematice. Můžete si to vyzkoušet na následujícím cvičení.
Pořadí matematických operací
Napište program, který vypočítá, jaké výsledky dávají následující příkazy.
Cvičení 11 Výsledek vypište na displej.
vysledek1 = 3 + 6 * 2; vysledek2 = (3 + 6) * 2; Zjednodušené psaní operací
Velmi často se v programování stává, že je potřeba upravit hodnotu číselné proměnné.
Např. k ní něco přičíst, odečíst, něčím ji vynásobit, apod. Pokud byste vycházeli ze znalostí,
které máte, dospěli byste nejspíš k tomuto zápisu:
číslo1 = číslo1 početní_operace číslo2; Pokud byste chtěli např. zvednout proměnnou hodnota o 5, vypadal by příkaz:
hodnota = hodnota + 5; Tedy do proměnné hodnota vlož číslo, kterého již nabývá, zvětšené o 5.
Podobný případ by nastal při zvedání proměnné hodnota o proměnnou x:
hodnota = hodnota + x; V jazyku C# existuje analogický zkrácený zápis těchto příkazů. Jsou shrnuty
v následující tabulce. Protože jsou velmi oblíbené, často se v programech vyskytují. I vy byste
se je měli naučit:
Zkrácené formy příkazů přepočítávajících hodnotu proměnné
číslo1 početní_operace = číslo2; Rozbor příkazu
Konkrétní příkazy pro různé operace vypadají následovně:
Název operace
Klasický zápis
Zkrácený zápis
přičtení čísla x
k proměnné cislo
cislo = cislo + x;
cislo +=x; odečtení čísla x od
proměnné cislo
cislo = cislo – x; cislo ‐=x; vynásobení proměnné
cislo číslem x
cislo = cislo * x; cislo *=x; vydělení proměnné
cislo číslem x
cislo = cislo / x; cislo /=x; Tab. 6 ‐ Zkrácený zápis některých aritmetických operací Porovnání zápisu pro zvětšení proměnné
Vytvořte program, ve kterém porovnáte, zda dávají klasický a zkrácený zápis
Cvičení 12 navýšení čísla stejné výsledky. Do proměnné cislo vložte číslo 10, v proměnné x
vložte číslo 2. Proměnnou cislo navyšte o proměnnou x dvě různými příkazy.
Výsledky obou příkazů zobrazte pod sebou na displeji.
Zdržme se ještě chvíli u problematiky navyšování či snižování hodnoty proměnné.
V programování se velmi často vyskytují případy, kdy se hodnota zvyšuje, anebo snižuje o
jedničku. Zvyšování hodnoty se říká inkrementace, jejímu snižování pak dekrementace.
Pokud bychom chtěli dejme tomu zvýšit hodnotu proměnné cislo o 1 (inkrementovat
proměnnou cislo), mohli bychom místo příkazu:
cislo = cislo + 1; či
cislo += 1; napsat jednoduše:
cislo ++; Obdobný příkaz existuje i pro snížení hodnoty proměnné o 1 (dekrementace proměnné
cislo):
cislo ‐‐; Inkrementace a dekrementace
cislo ++; cislo ‐‐; Rozbor příkazů
Inkrementací rozumíme zvýšení čísla o jedničku, dekrementace znamená snížení o
jedničku.
Odpočet s proměnnou
Otevřete si program „Chyba! Nenalezen zdroj odkazů.“ (buď jste si jej vytvořili
ami,
anebo je dostupný na přiloženém CD) a přeuložte jej pod názvem „Cvičení 13
Cvičení 13
– Odpočet s proměnnou“. Chyba! Chybný odkaz na záložku.Přepište jej tak, aby
se čísla 3, 2 a 1, vypisovaná na displej, vkládala z celočíselné proměnné. Tu během
programu zmenšujte o jedničku.
Shrnutí kapitoly:
Znalostí programování matematických operací jsme si značně zvětšili okruh
problémů, které můžeme jako programátoři řešit. Je dobré naučit se nejen základní
příkazy, ale i zkrácené. Nejenže nám ušetří nějaký ten čas, ale budeme vědět, co
znamenají, až je uvidíme v cizím kódu.
Kapitola 9. Podmínka
Co se naučíte:
Sekvence je sice krásná věc, ale žádnému, ani tomu nejvíce podprůměrnému,
programátorovi nestačí k tomu, aby tvořil zajímavé programy. Na to je sekvence
příliš prostá. V této krátké kapitole si řekneme základní informace k algebraické
struktuře podmínka, které naše dosavadní znalosti povznesou na novou úroveň.
Nové příkazy:
if (podmínka)
{
sekvence příkazů 1;
}
else
{
sekvence příkazů 2;
}
Podmínka
Podmínka se využívá v programech všude tam, kde je potřeba, aby program zvolil
jednu ze dvou cest vykonávání programu. Rozhoduje se na základě podmínky, což je
proměnná, výraz nebo vlastnost, která musí být logického datového typu, tedy typu bool. Na
podmínku vždy existuje odpověď ANO nebo NE (PRAVDA nebo NEPRAVDA, TRUE nebo
FALSE).
Podmínky se v C# zapisují následujícím způsobem:
Podmínka
if (podmínka) { sekvence příkazů 1; } else { sekvence příkazů 2; } Rozbor příkazu
Pro úplné pochopení uvádím několik příkladů podmínek:
Symbolický zápis
podmínky
Slovní zápis podmínky
if (rychlost < 50) Je rychlost (číselná proměnná) menší než 50?
if (stopStav == true) Je stopStav (logická proměnná) nastaven na true?
if (pocet != 10) Je pocet (čiselná proměnná) jiný než 10?
Tab. 7 ‐ Příklady podmínek Z příkladů je patrné, že jakýkoli symbolický zápis podmínky se dá slovně
interpretovat jako otázka, na niž existuje jednoznačná odpověď: ANO nebo NE.
Pokud je odpověď na otázku ANO, provede se sekvence příkazů 1. Pokud je
odpověď NE, provede se sekvence příkazů 2.
Jestliže místo sekvence příkazů 1 nebo sekvence příkazů 2 chcete vložit pouze jediný
příkaz, nemusíte jej ohraničovat nahoře a dole závorkami. Vnitřní příkazy podmínky
je však vhodné vždy odsadit od ostatních příkazů kvůli přehlednosti programu.
Ve středu podmínky se nachází operátor (znaménko), na jehož obou stranách se
mohou nacházet proměnné, nebo konkrétní hodnoty. Úplný výčet a význam operátorů je
v tabulce níže. Je potřeba se jej naučit:
Operátor == != < <= > >= Význam je rovno není rovno (je různé od) je menší je menší nebo rovno je větší je větší nebo rovno Tab. 8 ‐ Operátory podmínek Pokud chcete vykonat určité příkazy jen v případě, že podmínka platí a v případě její
neplatnosti pouze pokračovat ve vykonávání programu, můžete vypustit „else“ část.
Podmínka by v tomto případě vypadala:
if (podmínka) { sekvence příkazů 1; } Pojďme se podívat alespoň na malý příklad zápisu konkrétní podmínky. Bude se
jednat o příklad, který vypíše, zda je v celočíselné proměnné cislo sudé, nebo liché číslo:
if (cislo % 2 == 0) nxtDisplayTextLine(0,“Cislo %d je sude.“,cislo) else nxtDisplayTextLine(0,“Cislo %d je liche.“,cislo) Pozn. Je-li číslo dělitelné dvojkou (tedy je-li zbytek po dělení dvěma roven 0), jedná se
o číslo sudé. V opačném případě je číslo liché.
Shrnutí kapitoly:
Podmínka je velmi důležitou algebraickou strukturou. Její uplatnění však najdeme
pouze tam, kde se rozhodujeme na základě vlastnosti, či hodnoty, kterou předem
jako programátoři neznáme. Protože ale zatím veškeré hodnoty zadáváme zevnitř
programu, neuvedl jsem v této kapitole žádný příklad. Použití podmínky by bylo
neprůkazné.
V dalších kapitolách se proto budete seznamovat s jinými možnostmi zadání
hodnot (ať už pomocí dotykových senzorů, či generátoru náhodných čísel), kde již
bude použití podmínky nezbytné. Naučíte se také, jak zapsat vícenásobnou
podmínku.
Kapitola 10.Dotykový senzor
Co se naučíte:
Abyste úplně docenili možnost psaní podmínek, je potřeba se naučit možnosti, jak
do robota dostat informace zvenčí (od uživatele). K tomu si vezmeme na pomoc
dotykové senzory. Ty se standardně zapojují do konektorů 1 a 2 NXT terminálu a
mohou plnit nejrůznější funkce. Dají se připevnit do čela robota, aby se tak stiskem
detekoval náraz do čelní stěny, anebo si je můžete vzít do ruky a používat je pro
ruční zadávání signálů.
V příkladech pro detekci, zda došlo ke stisku dotykového senzoru, budete
potřebovat nekonečný cyklus, který bude stále dokola testovat, zda nedošlo ke
stisku.
V poslední části této na nové informace i cvičení bohaté kapitoly se naučíte,
k čemu a jak používat vícenásobné a disjunktní podmínky.
Klíčové pojmy kapitoly:
Touch sensor, nekonečný cyklus, vícenásobná podmínka, disjunktní podmínky
Nové příkazy:
SensorValue(jménoSenzoru)
zjištění stavu dotykového senzoru
for(;;)
nekonečný cyklus
break;
vyskočení z právě probíhajícího cyklu
Ať už budete používat jakýkoli senzor, musíte tuto skutečnost zanést do programu
pomocí jednoho specifického příkazu. V něm zároveň určíte, pod jakým jménem bude senzor
v programu vystupovat. Obrovskou výhodou je, že si tento příkaz nemusíte pamatovat, ale že
jej za Vás napíše program Robotc. Stačí jen vědět, jak na to:
V menu Robot vyberte položku Motors and Sensors Setup (Obr. 20). V nově
otevřeném okně (Obr. 21) přejděte na záložku Sensors. Nacházejí se na ní 4 řádky začínající
zkratkami S1 až S4. Ty symbolizují vstupy 1 až 4 NXT terminálu. Pokud budete chtít
využívat jeden dotykový sensor zapojený do vstupu 1, napíšete do editačního pole vedle S1
název zařízení, např. ovladac a v seznamu vedle jména vyberete „touch“.
Pozn. Pokud byste chtěl používat ultra-sonic senzor, najdete jej v seznamu pod jako
SONAR. Barevný senzor pak reprezentuje položka LEGO Color.
Podobným způsobem můžete přidat do řádku S2 druhý dotykový senzor, případně
další senzory do řádků S3 a S4. Zadávání ukončíte tlačítkem OK. Pokud jste přidali pouze
jeden dotykový senzor výše popsaným způsobem, doplní se automaticky do Vašeho programu
následující řádek kódu:
#pragma config(Sensor, S1, ovladac, sensorTouch) Počet řádků závisí na počtu Vámi přidaných senzorů. Tento automaticky vložený kód
neslouží pouze programu, aby věděl, pod jakými označeními a v jakých portech hledat
příslušné senzory. Je to také informace pro člověka s daným programem pracujícího, aby
jasně věděl, jak správně zapojit senzory do terminálu, aby robot správně vykonával
naprogramovanou činnost.
Obr. 20 ‐ Cesta k nastavení senzorů Obr. 21 ‐ Okno Motors and Sensors Setup Dotaz na stisk dotykového senzoru
Zásadní vlastností dotykového senzoru je, zda je stisknut nebo ne. Tato hodnota je
logického datového typu a lze ji přečíst pomocí funkce SensorValue. Protože se dá na otázku
o stisku odpovědět jen ano nebo ne, prakticky vždy se programuje pomocí podmínky.
Dotaz na stisk dotykového senzoru
if(SensorValue(jménoSenzoru) == 1) { sekvence příkazů 1; } else { sekvence příkazů 2; } Rozbor příkazu
Ve výše uvedené podmínce se ptáme, zda je senzor o daném jménu stisknut. V
případě, že ano, provede se sekvence příkazů 1. V opačném případě je provedena
druhá sekvence příkazů.
Nekonečný cyklus
Ač se o cyklech podrobně dozvíte až ve druhé sbírce, naučíme se jeden velmi
jednoduchý cyklus už nyní. Je to z toho důvodu, že při práci s dotykovým senzorem je nutné
stále dokola testovat, zda nedošlo k jeho stisknutí. A dělat něco stále dokola znamená
pracovat v cyklu. Jednoduchý cyklus, o kterém si teď řekneme, je pro algoritmizaci velmi
specifický. Nekonečné cykly bývají většinou známkou špatného naprogramování, v našem
specifickém použití budou ale nezbytné.
Nekonečný cyklus
for(;;) { příkazy cyklu; } Rozbor příkazu
Největším nebezpečím nekonečných cyklů je to, že zacyklený program neskončí.
Problém je částečně vyřešen tím, že se NXT terminál po určité delší době, během
níž s ní uživatel nepracuje, sám vypne, a program se tak přeruší. Samozřejmě nám
také nic nebrání v případě potřeby běžící program vypnout ručně (pomocí šedého
tlačítka terminálu).
Ukončení cyklu není problém ani jednoduše naprogramovat. Cyklus se většinou
opouští po splnění nějaké podmínky. Stačí tuto podmínku dovnitř cyklu napsat, a v případě
jejího splnění použít příkaz vyskočení z cyklu:
Vyskočení z cyklu
break; Rozbor příkazu
Po vyskočení z cyklu bude program pokračovat příkazy za cyklem. Jestliže za ním
již žádné příkazy nejsou, program se ukončí.
V praxi použití nekonečného cyklu vypadá tak, že část programu, anebo celý program
(který má v reálném čase reagovat na změny vstupních senzorů), je umístěn uvnitř něj. Před
ním se většinou nachází základní deklarace, či inicializace proměnných, nebo např. nápisy na
displej, které na něm mají zůstat po celou délku běhu programu. Za složenou závorku
nekonečného cyklu má smysl vkládat další příkazy jen tehdy, je-li jeden z příkazů cyklu
vyskočení z cyklu. Nekonečný cyklus totiž znamená, že až se dostane program ve zpracování
na jeho konec, vždy se přesune na jeho začátek, a to stále dokola. Pokud by tedy uvnitř něj
nebyl příkaz break, jakýkoli příkaz za tímto cyklem by se nikdy neprovedl.
Vytvořte „Program 10 – Pojezd se stisknutým ovladačem“, který bude využívat
jednoho dotykového senzoru připojeného do portu S1 terminálu. Dotykový senzor bude
uživatel držet ve své ruce. Při stisknutém senzoru bude vozidlo v pohybu směrem vpřed o
výkonu 50%. Při nestisknutém senzoru bude vozidlo stát.
#pragma config(Sensor, S1, pojezd, sensorTouch) /*Kód vygenerovaný programem Robotc pomocí konfiguračního průvodce přidání senzorů. V tomto případě jsme přidali dotykový senzor do portu S1. V programu je na něj odkazováno slovem „pojezd“.*/ task main() //začátek programu { for(;;) //začátek nekonečného cyklu { if(SensorValue(pojezd)==1) //Je dotykový senzor pojezd aktivní? { motor(motorB)=50; //pokud ano, nastav výkon motorů na 50 motor(motorC)=50; } else { motor(motorB)=0; //pokud ne, nastav výkon motorů na 0 motor(motorC)=0; } } //konec cyklu vrací program na jeho začátek. } //K tomuto řádku (ukončení programu) program nikdy nedospěje. Nekonečným cyklem for(;;) se stále dokola testuje, zda je dotykový senzor stisknutý.
Pokud je, nastaví se výkon motorů na 50% a robot se rozjede. Při zjištění nestisknutého
senzoru jsou motory vynulovány a zastaví se.
Délka času, po který motory jedou, tedy už není dána příkazem wait1Msec, ale je
vytvářena reálným časem, po který se zpracovávají příkazy nekonečného cyklu během držení
stisknutého senzoru.
Zapnutí a vypnutí pojezdu dvěma ovladači
Vytvořte program pro ovládání pojezdu robota pomocí dotykových senzorů.
Stiskem
prvního senzoru se robot rozjede dopředu výkonem uvedeným v konstantě
Cvičení 14
rychlost. Stiskem tlačítka druhého senzoru se vozidlo zastaví.
Pozn. Pro případ, že byste si s programem nevěděli rady, je v zadní části sbírky
podrobně okomentovaný kód. Bylo by ale škoda to nejprve nezkusit sami. Má velmi malé
množství řádků. Tak směle do toho 
Časová prodleva pro opětovné testování
V některých programech bude užitečné, ba přímo žádoucí, abychom po nějaké sérii
příkazů nastavili časovou prodlevu pomocí příkazu wait1Msec, byť jsou příkazy součástí
nekonečného cyklu. Budeme to muset udělat v případech, kdy program nebude reagovat na
to, zda je dotykový senzor držený, ale zda došlo ke stisku (tedy stisknutí a okamžitému
puštění). Na tento úkon je totiž člověk mnohem více navyklý. Když se chcete dívat na
televizi, taky jen jednou zmáčknete tlačítko a nedržíte ho po celou dobu, co se díváte.
Problém si zkusíme ukázat na příkladu. Naším cílem je zvedat hodnotu proměnné
stiskem senzoru o jedničku. Až se dostaneme k číslu 10, začne se počítat znovu od nuly.
Jak zajistit, aby se při dosažení čísla 10 začínalo znova od nuly? Stačí se při každé
změně proměnné podmínkou zeptat, zda již nepřekročila hodnotu 10. V případě kladné
odpovědi proměnnou nebudeme neinkrementovat, ale přímo jí přiřadíme hodnotu 0, která už
se bude opět zvyšovat o jedničku. Vše je vidět v následujícím kódu. Ten si opište a uložte pod
názvem „Program 12 - Inkrementace čísla“.
#pragma config(Sensor, S1, inkrementace, sensorTouch) task main(); { sbyte cislo = ‐1; nxtDisplayCenteredBigTextLine(3,"%d",cislo); for(;;) { if(SensorValue(inkrementace)==1) { if(cislo = 10) cislo = 0; else cislo++; nxtDisplayCenteredBigTextLine(3,"%d",cislo); } } } Než si otestujeme funkci programu, chtěl bych Vás upozornit na vnořenou funkci if.
Splnění první podmínky (detekce stisknutého senzoru) je podmínkou pro to, aby se program
zabýval podmínkou druhou (dotazem, zda je hodnota proměnné cislo rovna 10). Else část, jak
jistě vidíte z ohraničení příkazů složenými závorkami, patří vnitřní (neboli vnořené)
podmínce.
Pokud není splněná podmínka první, logicky se program nedostane k podmínce druhé.
A takovýchto vnořených podmínek může být, kolik potřebujete.
Tento způsob programování je v některých příkladech prakticky nezbytný (i když
v našem případě by existovala i jiná možnost). Podmínka if má totiž pouze dvě cesty, kudy se
vydat (možnost ANO, možnost NE). Tím, že do jedné z cest vložíme další podmínku, ze které
vedou opět dvě cesty, rozšíříme počet možných řešení vstupní podmínky o jednu. Takto
můžeme vkládat vnitřní podmínky dál a dál. Některé situace, které mohou nastat různým
skládáním vnějších a vnitřních podmínek, ukazuje ve formě tzv. vývojových diagramů
Chyba! Nenalezen zdroj odkazů., Obr. 23 a Obr. 24.
Předchozí příkazy programu + + podm.2 podm.1 ‐ ‐ Příkazy při splněné 1. a 2. podmínce Příkazy při splněné 1. podmínce a nesplněné 2. podmínce Příkazy při nesplněné 1. podmínce Následující příkazy programu Obr. 22 ‐ Vnořená podmínka v kladné větvi vnější podmínky
Až 3 různé varianty Předchozí příkazy programu + + + podm.1 ‐ podm.2 ‐ podm.3 ‐ Příkazy při splněné 1., 2. a 3. podmínce Příkazy při splněné 1. a 2. podmínce, ale nesplněné 3. podmínce Příkazy při splněné 1. podmínce, ale nesplněné 2. podmínce Příkazy při nesplněné 1. podmínce Až 4 různé varianty Následující příkazy programu Obr. 23 ‐ Vnější podmínka má po jedné vnitřní podmínce v kladné i záporné větvi Předchozí příkazy programu + + podm.2 Příkazy při splněné 1. a 2. podmínce podm.1 ‐ + ‐ Příkazy při splněné 1. podmínce a nesplněné 2. podmínce Příkazy při nesplněné 1. a splněné 3. podmínce podm.3 ‐ Příkazy při nesplněné 1. a 3. podmínce Až 4 různé varianty Následující příkazy programu Obr. 24 ‐ Dvakrát vnořená podmínka
A jdeme testovat. Při testování jste určitě zjistili problém, který spočívá v tom, že ač
zvedáme proměnnou jen o jedničku, ve skutečnosti se mění velmi záhadným způsobem. Je to
proto, že příkazy programu se provádějí velmi rychle. Dokonce tak rychle, že jen při letmém
stisku dotykového senzoru se stačí cyklus mnohokrát zopakovat. Důsledkem je to, že pokud
se cyklus stačí během mého krátkého stisku zopakovat třeba 80x, dojde celkem 80x k detekci
stisku, a program se tak chová, jako bych senzor stisknul 80krát. Je to něco podobného, jako
když píšete na klávesnici a necháte prst na klávese příliš dlouho. Taky se pak program chová,
jako by byla klávesa stisknuta vícekrát, ačkoli byla stisknuta pouze jednou. Zde je vše akorát
mnohem rychlejší.
Východisko z tohoto problému je jednoduché. Stačí za každou detekcí stisku (resp.
změnou proměnné) vložit krátkou časovou prodlevu, abyste měli čas na uvolnění tlačítka a
nedošlo tak k další nechtěné detekci. Jak dlouhá by ale měla časová prodleva být? Při
testování programu jsem došel k závěru, že vhodný časový interval pro testování aktivity
senzoru je cca 0,2 sekundy. Pokud bychom nastavili interval kratší, pravděpodobně bychom
během něj při klasickém stisku nestačili palec sundat dřív, než by došlo k další (nechtěné)
detekci stisku. Pokud byste naopak nastavili prodlevu příliš velkou, např. 1 sekundu, mohlo
by se stát, že uživatel provede stisk, zatímco běží příkaz wait1Msec(1000). Tím pádem se
stisk nedetekuje (detekci má na starost podmínka if(SensorValue(inkrementace)==1)).
Doplňte příklad tak, že za příkaz vypsání na displej vložte časovou prodlevu 0,2s:
wait1Msec(200); Nastavení časové prodlevy před detekcí dalšího stisku záleží z velké části na
individuálním rozhodnutí. Prodlevu si můžete testováním programu upravit dle svých
požadavků. Složitější situace nastávají, má-li se během časové prodlevy prováděla nějaká
činnost, např. běh motorů. Můžete si to ověřit v následujícím cvičení a nastavit délku časové
prodlevy podle potřeby.
Zvyšování a snižování rychlosti
Vytvořte program pro ovládání pohybu vozidla. Při každém stisku senzoru
Cvičení 15 „zvyseni_vykonu“ se zvýší výkon pojezdu o 10%. Při stisku senzoru
„snizeni_vykonu“ se výkon o 10% sníží. Při snižování výkonu se může vozidlo
dostat do záporných hodnot výkonu, a jet tak pozpátku.
Aktuální výkon motoru ať je vyobrazen na displeji terminálu.
Pozn.1 Pokud budete stiskem zrychlování tolikrát zvyšovat proměnnou rychlost, až se
dostanete k číslu 150, budete moci pozorovat, že od čísla 100 se již rychlost nezvyšuje. Motory
mohou jet max. na 100% a tak ač jim přidělujeme sebevětší hodnoty, stroj již na ně nereaguje.
V tom by ještě takový problém nebyl. Horší je to, že při stisku ovladače pro zpomalování také
nedojde ke změně. Proměnná rychlost se snižuje ze 150 poprvé na 140, podruhé na 130,
potřetí na 120, ale to jsou hodnoty, při kterých motory jedou stále na 100% výkonu. Můžeme
tedy snižovat rychlost, jak chceme, ale pokud se nedostaneme k hodnotě 100, pojede robot
stále nejvyšší možnou rychlostí. Podobná situace nastává kolem rychlosti -100. Je třeba proto
zabránit tomu, aby se do proměnné vykon zapsala hodnota větší než 100 a menší než -100. K
tomu nám pomohou vnořené podmínky.
Pozn.2 V tomto příkladě opět musíme přidat časovou prodlevu. I kdybyste dotykový
senzor stiskli seberychleji, stihne se nekonečný cyklus, jež má na starost detekci stisku,
zopakovat více, než jednou. To by znamenalo zvýšení výkonu o mnoho více, než 10%.
Vyzkoušejte více různých časových rezerv, abyste našli tu ideální.
Zahýbání
Souhrnné
cvičení 3
Teoretická
východiska
Pomůcky
Zadání
Vytvořte program, ve kterém jede robo-vozidlo stále dopředu. Držením levého
nebo pravého dotykového senzoru zahýbá doleva, resp. doprava a vyhýbá se tak
překážkám.

znalost práce s dotykovým senzorem

znalost práce s podmínkou

znalost práce s nekonečným cyklem

znalost práce s přehráváním zvukových souborů

robot Lego Mindstorms v sestavení vozidlo s dotykovými senzory
připojenými k terminálovým portům 1 a 2

různé překážky (krabice, plechovky, …), může posloužit i mapa města
z prvního souhrnného cvičení
1. Vytvořte program, který reaguje na držení dotykových senzorů:
a. Není-li stisknut žádný dotykový senzor, ať jede robot dopředu
konstantním výkonem 50%.
b. Při držení senzoru v portu 1, ať zahýbá doprava.
c. Při držení senzoru v portu 2, ať zahýbá doleva.
2. Ať se po celou dobu zahýbání přehrává zvuk "MS_sfx_burp.rso", který
najdete na přiloženém CD ve složce NXT zvuky Internet.
Jízda s nastavením rychlosti předem
Souhrnné
cvičení 4
Vytvořte program pro robota ve složení vozidlo tak, aby byl ovladatelný dvěma
dotykovými senzory. První senzor ať slouží k nastavení rychlosti, druhý ať
aktivuje jízdu vpřed.

znalost práce s dotykovým senzorem

znalost práce s podmínkou

znalost práce s nekonečným cyklem

znalost práce se zobrazováním textu na displeji
Pomůcky

robot Lego Mindstorms v sestavení vozidlo (stačí základní, ale může být
jakékoli jiné)
Zadání
1. Vytvořte program pro ovládání pojezdu robo-vozidla vpřed pomocí dvou
dotykových senzorů.
Teoretická
východiska
2. Prvním senzor – nastaveniRychlosti - slouží k nastavení rychlosti, jakou
robot pojede. Každým stiskem senzoru se výkon motorů zvýší o 10. Až
dosáhne rychlost čísla 100 (a nebude ji tudíž možné dále zvyšovat), změní
se stiskem senzoru na nulu.
První senzor však slouží pouze k nastavení rychlosti, ne jízdě samotné.
3. Senzorem nastaveniRychlosti ať je aktuálně nastavená rychlost přehledně
zobrazena na displeji.
4. Stisk druhého senzoru - Start - způsobí rozjezd robota výkonem
nastaveným pomocí senzoru nastaveniRychlosti.
5. Robota ať zastaví nové zadávání rychlosti, tedy stisk senzoru
nastaveniRychlosti.
Vícenásobná podmínka
Pokud je v programu podmíněno vykonání nějakého příkazu, nebo série příkazů,
splněním více dílčích podmínek, máme 2 možnosti, jak k této situaci přistoupit.
První možnost, kterou již známe, je vnořená podmínka. Pokud budeme např.
vyžadovat splnění dvou dílčích podmínek, jednu dáme do vnější podmínky a druhou do
vnitřní. Samotný příkaz pak vložíme do vnitřní podmínky. V případě, že má být dílčích
podmínek víc, vnoříme o to víc příkazů if do sebe.
if(podmínka1) if(podmínka2) { sekvence příkazů; } Zahýbání a jízda vpřed 1
Vytvořte program na ovládání robo‐vozidla dvěma dotykovými senzory. Při stisku jednoho senzoru ať se robot otáčí na místě doleva, resp. doprava, podle toho, zda byl stisknut levý Cvičení 16
nebo pravý senzor. Při stisku obou senzorů ať robot jede vpřed. V programu použijte několika vnořených příkazů if s jednou podmínkou. Druhým, a příjemnějším, řešením je spojení dílčích podmínek v jednom příkazu if:
Vícenásobná podmínka
if(podmínka1 && podmínka2 && … && podmínkaN) { sekvence příkazů; } Rozbor příkazu
Propojení dílčích podmínek, které mají platit zároveň, se provádí pomocí spojky
&&, která se vkládá mezi každé dvě dílčí podmínky. Dílčích podmínek v jednom
příkazu if může být samozřejmě více.
Vícenásobnou podmínku si teď zkusíme naprogramovat. Vytvoříme program, ve
kterém se bude zapínat a vypínat pojezd robota jediným dotykovým senzorem. Můžete si jej
zkusit napsat a uložit pod názvem „Program 13 - Zapnutí a vypnutí pojezdu jedním
ovladačem.c“. Pod kódem naleznete rozbor příkladu, který si určitě si jej prostudujte.
#pragma config(Sensor, S1, stopStart, sensorTouch) //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*// task main() { bool jizda = false; for(;;) { if(SensorValue(stopStart)==1 && jizda==false) { motor(motorB)=50; motor(motorC)=50; jizda=true; } else if(SensorValue(stopStart)==1 && jizda==true) { motor(motorB)=0; motor(motorC)=0; jizda=false; } wait1Msec(200); } } Abych umožnil 2 možné reakce programu (rozjetí a zastavení) na jedinou reakci
zvenčí (stisk dotykového senzoru), vytvořil jsem si logickou proměnnou jizda, podle které
budu při stisku tlačítka rozhodovat o dalším osudu robota. Této proměnné přiřazuji hodnoty
true (robot je v pohybu) nebo false (robot stojí). Pokud je stisknut senzor a zároveň robot
stojí, jeho reakcí je rozjetí a nastavení proměnné jizda na true. Pokud je proměnná jizda
nastavena na true (příznak toho, že robot je v pohybu), je se stiskem senzoru robot zastaven a
proměnná jizda nastavena na false.
Zahýbání a jízda vpřed 2
Naprogramujte stejný problém, jako u cvičení 16, jen s tím rozdílem, že použijete vícenásobné podmínky v jednom příkazu if. Cvičení 17
Disjunktní podmínky
Nyní si představte situaci, kdy příkaz if obsahuje více dílčích podmínek, ale k tomu,
aby byla podmínka vyhodnocena jako true postačuje, aby byla splněna aspoň jedna z nich. Na
to v programování také jistě mnohokrát narazíte. Programuje se podobným způsobem, jako
vícenásobná podmínka, jen se změní znaménko mezi dílčími podmínkami na ||:
Disjunktní podmínky
if(podmínka1 || podmínka2 || … || podmínkaN) { sekvence příkazů; } Rozbor příkazu
Propojení dílčích disjunktních podmínek se provádí pomocí spojky ||, která se
vkládá mezi každé dvě dílčí podmínky. Dílčích podmínek v jednom příkazu if
může být samozřejmě více.
Programátor někdy musí šáhnout po proměnné, která bude obsahovat aktuální stav
programu. Pokuste se výhody takových proměnných pochopit na následujícím příkladu:
Dotykový senzor, který je připojený k portu 1, připevněte na přední část robo-vozidla
tak, aby se stisknul případným nárazem do překážky. Budeme mu říkat stop senzor. Druhý
dotykový senzor, připojený k portu 2, budete držet v ruce. Tento senzor pojmenujeme
stopStart. Vytvořte program, který rozjede vozidlo vpřed stiskem ručního senzoru, a zastaví
jej stiskem jednoho ze dvou senzorů. Tzn., že se robot zastaví stiskem stejného ovladače,
jakým se rozjíždí, anebo nárazem do zdi.
Před samotným programováním je potřeba uvážit, za jakých okolností se robot začne
pohybovat, a kdy se naopak zastaví.
Rozjezd je možný na stisk stopStart senzoru za předpokladu, že auto stojí na místě a
má uvolněný stop senzor.
Je-li robot v pohybu, zastaví se při stisku jak stopStart, tak stop senzoru.
Jak ale zjistím, zda je robot v pohybu, či nikoliv? Odpověď najdete v následujícím
kódu. Obsahuje, mimo jiné, logickou proměnnou jizda, která je buď false, pokud robot stojí,
nebo true, pokud jede. Tato proměnná je využívána při dotazech podmínky if. Nesmíme ji
ovšem zapomenout přenastavit při změně stavu robota.
Kód si uložte pod názvem „Program 14 – Start a stop“.
#pragma config(Sensor, S1, stopStart, sensorTouch) #pragma config(Sensor, S2, stop, sensorTouch) //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*// task main() { bool jizda = false; //na zacatku robot stoji, promennou jizda //tedy nastavim na false for(;;) { if(SensorValue(stopStart)==1 && SensorValue(stop)==0 && jizda==false) { motor(motorB)=50; motor(motorC)=50; jizda=true; wait1Msec(500); } if(SensorValue(stopStart)==1 || SensorValue(stop)==1) if(jizda==true) { motor(motorB)=0; motor(motorC)=0; jizda=false; wait1Msec(500); } } } Zastavení po uplynutí určité doby nebo nárazem do zdi
Souhrnné
cvičení 5
Teoretická
východiska
Pomůcky
Zadání
Vytvořte program pro robota ve složení vozidlo s dotykovým senzorem
připevněným vepředu. Ať se robot rozjede na stisk senzoru a zastaví se buď po 5
sekundách, nebo dříve nárazem do zdi.

znalost práce s dotykovým senzorem

znalost práce s disjunktní podmínkou

znalost práce s nekonečným cyklem

robot Lego Mindstorms v sestavení vozidlo s dotykovým senzorem
připevněným ve přední části tak, aby došlo k jeho stisku při kolmém najetí
na zeď
1. Robot bude v klidovém stavu čekat, až dojde ke stisku dotykového
senzoru rukou uživatele. Po stisku se robot rozjede dopředu výkonem
50%.
2. Doba jízdy ať je 5 vteřin. Po uplynutí tohoto časového intervalu se robot
zastaví a přehraje zvuk „soundUpwardTones“.
3. Pokud dojde před ukončením časového limitu 5 vteřin ke stisknutí senzoru
nárazem do zdi, předčasně se vypnou motory a přehraje se stejný zvuk,
jako v bodu 2.
Shrnutí kapitoly:
Chceme-li v našich programech využívat reakci na stisk dotykového senzoru,
musíme vědět, jak tento stisk detekovat. Testování stisku musí probíhat přiměřeně
často, aby se detekoval i při kratičkém stisku, ale aby se při delším podržení
nedetekoval vícekrát, než jednou. Detekce stisku probíhá formou nekonečného
cyklu, který obsahuje časovou prodlevu odpovídající intervalu testování
následovanou samotným testování pomocí podmínky.
Mezi jinými příkazy může být v cyklech přítomen i příkaz break, který způsobí
vyskočení z právě probíhajícího cyklu, což způsobí pokračování příkazy za ním.
Programátoři se často dostanou do situace, kdy potřebují provést část kódu za
předpokladu splnění 2 a více podmínek najednou. Máte na výběr za dvou
základních možností, jak tento problém řešit. Buď za pomoci vnořené podmínky
(do kladné větve podmínky if vložíte další podmínku), anebo vložením více
podmínek do jedné funkce if, přičemž mezi tyto podmínky vložíte zdvojenou
spojku &&. Podobně lze naprogramovat i disjunktní podmínku, která se považuje
za splněnou za předpokladu, že je splněna aspoň jedna z podmínek. V příkazu if se
mezi takovéto podmínky vkládá zdvojená spojka ||.
Kapitola 11.Hrajeme si
Co se naučíte:
Jednou z nejpřitažlivějších programátorských činností je jistě, alespoň pro
začínající vývojáře, programování her. Přitažlivé však ještě neznamená
jednoduché. Já ale věřím, že se s touto kapitolou poperete a přijdete jí na kloub.
Před samotným vytvářením her se seznámíme příkazem, který slouží ke generování
náhodných čísel. Ten bude využit v první hře, kterou budete mít za úkol pochopit a
upravit. Druhá hra už bude čistě na Vás.
Nové příkazy:
název_proměnné = random(max);
generování náhodného čísla
Generátor náhodných čísel
Čas od času potřebujeme, aby se nám v programu vygenerovalo náhodné číslo a
uložilo do proměnné pro její další využití. Náhodná čísla někdy potřebujeme vytvořit pro
funkčnost programu, jindy pro její testování. Existuje několik způsobů, jak se taková čísla
generují. Nám bude stačit tento jednoduchý:
Generátor náhodných čísel
název_proměnné = random(max); Rozbor příkazu
Příkaz vygeneruje číslo v intervalu 0 až max a uloží jej do proměnné.
Pokud např. chcete vygenerovat náhodné číslo od 0 do 10 a uložit jej do proměnné
nahoda, bude kód vypadat takto:
nahoda = random(10); Pokud chcete generovat čísla v jiném rozsahu, např. od 1 do 20, musíte
zaimprovizovat:
nahoda = random(19)+1; Příkazem random(19) se generují čísla od 0 do 19. Přidáním +1 za příkaz random se
každé vygenerované číslo zvedne o 1. Tedy z 0 se stane 1, z 1 se stane 2, …, z 19 se stane 20.
Do proměnné nahoda se tedy nakonec uloží čísla v intervalu 1 až 20.
Generování čísel ze zadaných intervalů
Jakými příkazy se vygenerují do proměnné x typu integer čísla z následujících
Cvičení 18 intervalů?
a) čísla od 0 do 100
b) čísla od 10 do 100
c) čísla od -100 do 100
Hra pozornosti
Vytvořte hru pozornosti, která se bude hrát na NXT terminálu s připojeným jedním
dotykovým senzorem.
Na začátku hry se objeví na displeji nápis „START“. Po třech sekundách začne hra. Ta
spočívá v tom, že se na displeji každé 0,8 sekundy objeví trojice náhodně vygenerovaných
čísel od 1 do 5. Hráč musí stisknout dotykový senzor ve chvíli, kdy jsou na displeji 2 nebo 3
stejná čísla:
1. Pokud jsou při stisku senzoru na displeji 2 stejná čísla, dostává hráč 3 body.
2. Trefí-li se hráč stiskem do tří stejných čísel, dostane bodů 10.
3. Pokud se hráč splete a stiskne senzor při třech různých číslech, 3 body se mu odečtou.
Hra končí ve chvíli, kdy hráč dosáhne 50 nebo více bodů. Na displeji se objeví na 5
vteřin nápis „VÍTĚZ“. Během hry musí být hráč stále informován o výši jeho bodového konta
a o tom, kolik bodů se mu daném kole přičítá, či odečítá.
Zásadním problémem, na který byste při programování této hry mohli narazit, je
kontinuální běh dvou časových smyček. Jedna časová smyčka je 0,8 sekundy a je potřeba pro
generování trojice čísel. Druhá časová smyčka slouží k detekci stisku dotykového senzoru.
Zde by se nám možná hodily znalosti paralelního programování dvou současně
probíhajících procesů. Protože již na to není v této sbírce prostor, zkusím Vám jednoduchým
schématem ozřejmit, jak můžete postupovat s tím, co znáte:
Nekonečný cyklus
Vygeneruj trojici náhodných čísel.
Vykonej 80krát 10ms časovou prodlevu pro získání celkové prodlevy 0,8s. Za každou 10ms prodlevou testuj, zda nedošlo ke stisku dotykového senzoru. Průběžně také hlídej, zda hráč nedosáhl požadovaného počtu bodů. V takovém případě hru ukonči. Obr. 25 ‐ Grafické znázornění algoritmu
Analyzujte si a prakticky otestujte kód programu „Program 15 – Hra pozornosti“.
K jeho pochopení by vám měly posloužit komentáře.
Pozn. Následující program funguje pouze v programu Robotc verze 3 a vyšší. Nižší
verze nedokáže na displej zobrazit tři proměnné v rámci jednoho příkazu. Máte-li nižší verzi,
vytvořte alternativní řešení, kdy jsou tři proměnné zobrazeny ne vedle sebe, ale pod sebou.
#pragma config(Sensor, S1, hrac1, sensorTouch) //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*// task main() { byte cislo1; byte cislo2; byte cislo3; byte citac = 80; /*promenna citac slouzi k odmereni osmdesáti 10 miliseknudovych časových prodlev, mezi kterymi se testuje stisk dotykoveho senzoru na jednu sadu znaku. Na zacatku se inicializuje cislem 80 proto, ze pred prvnim generovanim nahodnych cisel nechceme odmerovat zadny cas.*/ int skoreHrace1 = 0; bool blokaceHrace1 = false; /*promenna blokaceHrace1 slouzi k zablokovani vicenasobne reakce na stisk dotykoveho senzoru na jedu sadu znaku.*/ nxtDisplayCenteredBigTextLine(3,"START"); wait1Msec(2000); for(;;) { /*Pokud uplynulo 0,8 sekund od zobazeni posledni sady znaku, vygeneruje se nova sada, vypise se a citac se vynuluje pro odmereni dalsich 0,8s. Pokud hrac reagoval na stisk behem predchozi sady znaku, a byl tedy po svem pokusu zablokovat, je nyni odblokovan pro pokracovani ve hre. Pred kazdou sadou znaku je take vypsano skore hrace.*/ if(citac == 80) { cislo1 = random(4)+1; cislo2 = random(4)+1; cislo3 = random(4)+1; nxtDisplayCenteredBigTextLine(3,"%d %d %d",cislo1,cislo2,cislo3); citac = 0; blokaceHrace1 = false; nxtDisplayTextLine(6,"Hrac 1: %d",skoreHrace1); } else /*Pokud jeste neuplynulo 0,8 sekund od zobazeni posledni sady znaku, zda byl poprve (blokace je nastavena na false) behem aktualni sady stisknut senzor.*/ { if(SensorValue(hrac1) == 1 && blokaceHrace1 == false) { /*Byl‐li stisknut seznor, nastavi se blokace na true, aby nemohl byt stisknut vicekrat behem jedne sady znaku. Testuje se, zda jsou vygenerovana cisla stejna.*/ blokaceHrace1 = true; if(cislo1 == cislo2 && cislo2 == cislo3 && cislo1 == cislo3) { /*V pripade shodnosti vsech znaku se pricte 10 bodu a informace se zobrazi na displeji.*/ skoreHrace1 = skoreHrace1 + 10; nxtDisplayTextLine(6,"Hrac 1: %d +10",skoreHrace1); } else /*Pokud by nebyla vsechna 3 cisla stejna, testuje se, zda byla stejna aspon nektera dvojice cisel.*/ if(cislo1 == cislo2 || cislo2 == cislo3 || cislo1 == cislo3) { /*Pokud byla nalezena dvojice shodnych cisel, prictou se ke skore hrace 3 body a informace se zobrazi na displeji.*/ skoreHrace1 = skoreHrace1 + 3; nxtDisplayTextLine(6,"Hrac 1: %d +3",skoreHrace1); } else { /*Pokud se pri stisku nebojevila ani dvojice stejnych cisel, jsou ze skore odecteny 3 body a informace se zobrazi na displeji.*/ skoreHrace1 = skoreHrace1 ‐ 3; nxtDisplayTextLine(6,"Hrac 1: %d ‐3",skoreHrace1); } } } /*Casova prodleva je vyuzita k tomu, aby se kazdych 10 milisekund zvednul obsah citace. To slouzi k mezitestovani senzoru pri odmerovani 0,8 sekundy pro vygenerovani nove sady znaku.*/ citac++; wait1Msec(10); /*Testovani, zda hrac nedosahl nebo nepreskocil skore 50 a nezvitezil. Pokud zvitezil, objevi se infomace na obrazove a prikazem break se vyskoci z nekonecneho cyklu na konec programu.*/ if(skoreHrace1 >= 50) { nxtDisplayCenteredBigTextLine(3,"VITEZ"); wait1Msec(5000); break; } } } Hra pozornosti pro dva hráče
Hrát hru sám se sebou je nuda, a proto upravte „Program 15 – Hra pozornosti“ tak,
Cvičení 19 aby hru hráli dva hráči proti sobě.
K NXT terminálu připojte další dotykový senzor, aby měl každý hráč svůj. Oba
hráči si během hry zvedají své bodové konto najednou, takže na její plynulosti se
nic nemění. Pro větší zábavnost však můžete doprogramovat, že při „trefě“ jednoho
hráče (která povede k připsání 3 nebo 10 bodů) se zablokuje pokus druhého hráče
v daném kole. Body za postřeh při mačkání senzoru tedy může v každém kole
získat jen jeden z hráčů.
Bodová konta obou hráčů budou na obrazovce zobrazena najednou, aby o sobě
měli navzájem přehled. Hráč, který dosáhne 50 bodů dříve, než druhý, vyhrává.
Pojezdová hra
Souhrnné
cvičení 6
Vytvořte pojezdovou hru, která se hraje tak, že si dva hráči předávají dotykový
senzor, na jehož stisk se vozidlo rozjede. To je na začátku hry postavené
v libovolné vzdálenosti kolmo od zdi.
Před každým stiskem se na displeji rozpohybuje ukazatel tak, že se neustále
zvětšuje a zmenšuje. Čím je ukazatel při stisku dotykového senzoru větší, tím ať
je jízda delší.
Vítězí ten hráč, jehož pojezdem dojde k dotyku vozidla se zdí.
Hra tedy spočívá v tom, že si aktivní hráč musí promyslet, kolik času potřebuje do
kontaktu senzoru se zdí a zda dokáže sepnout ruční senzor v tom správném
momentě aktuální polohy časového ukazatele. Jestliže si např. hráč řekne, že ani
by ani při nejvyšším čase nedošlo ke kontaktu robota se zdí, měl by s délkou
pojezdu taktizovat tak, aby kontakt neumožnil soupeři, který hraje po něm.
Teoretická
východiska
Pomůcky
Zadání

znalost práce s dotykovým senzorem

znalost importování zvuků do NXT terminálu a jejich přehrávání

znalost práce s nekonečným cyklem a podmínkou

znalost příkazů pro programování displeje

znalost příkazu pro generování náhodného čísla

robot Lego Mindstorms v sestavení vozidlo s dotykovým senzorem
připevněným ve přední části tak, aby došlo k jeho stisku při kolmém najetí
na zeď

druhý připojený dotykový senzor bude držet hráč v ruce
1. Ať se na displeji objeví nápis „Hráč 1“ a zůstane tam 1,5 s.
2. Poté ať se na displeji objeví postupně na prvním až posledním řádku
libovolný znak (nebo série znaků):
Nejprve se znak vypíše na prvním řádku, potom přibude na druhém řádku,
atd. až bude znak na každém řádku. Poté ať znaky zase postupně mizí (od
posledního nakresleného). Po zmizení všech znaků ať se celý cyklus stále
dokola opakuje, a to dokud hráč nestiskne dotykový senzor, který má
v ruce.
Časový rozdíl mezi přidáváním a odebíráním znaků je 70 ms.
3. Po stisku senzoru ať vozidlo jede výkonem 30% po uvedenou dobu:
Doba jízdy = počet znaků na displeji * 200 ms
4. Po dojezdu se na displeji objeví nápis „Hráč 2“ po dobu 1,5 s, pro kterého
se bude celá procedura výběru času jízdy pomocí ukazatele na displeji
opakovat.
5. Program ať stále střídá Hráče 1 a 2, dokud nedojde ke kontaktu předního
dotykového senzoru se zdí. Vyhrává ten hráč, kterému se podařilo tohoto
kontaktu dosáhnout. Na konci hry oznamte na displeji informaci, který
hráč vyhrál a přehrajte importovaný zvuk „Hooray.rso“.
Shrnutí kapitoly:
V této kapitole jste si vyzkoušeli prakticky veškeré dovednosti, které jste nabyli
v předchozím textu sbírky. Navíc jste se naučili příkaz pro generování náhodného
čísla.
Poslední souhrnné cvičení bylo docela náročné, protože popis již neobsahuje
veškeré detaily, na které si musíte při programování dávat pozor. Pokud jste jej
zvládli, gratuluji Vám.
Závěrem
A tímto jste se dostali na konec této sbírky, což je ten nejlepší předpoklad k tomu,
abyste se nejprve pochválili, a pak co nejdříve pokračovali v neutuchajícím boji o vzdělávání
druhým dílem.
Z programátorského hlediska je nejdůležitější prakticky zvládnout základní
algebraické struktury. Nyní již znáte sekvenci a podmínku. Ve druhé části učebnice se dočtete
o cyklech, které Vám obrovským způsobem rozšíří Vaše možnosti v programování. Z této
učebnice již znáte nekonečný cyklus, přerušený podmínkou obsahující příkaz vyskočení z
cyklu. Čistě teoreticky by Vám tato znalost mohla stačit, protože veškeré klasické cykly lze
nahradit právě nekonečným cyklem s podmínkou. Skutečnost je ale jiná a jistě byste záhy
zjistili, že znalost typičtějších druhů cyklů, jejich zápisů a použití patří mezi znalosti základní,
bez kterých se neobejdete jak při analýze kódů, tak jejich přehlednějšímu psaní.
Ve druhé části sbírky se dále naučíte, jak v prostředí Robotc programovat sonar a
barevný senzor stavebnice Lego Mindstorms. Navíc využijete i funkci doplňkového motoru,
především pomocí tzv. krokování.
Doufám, že se Vám programování dařilo. Také doufám, že Vás bavilo, snad i díky
práci s netypickým prostředkem programovatelného robota. Protože pro další vzdělávání a
zdokonalování v jakékoli oblasti lidského vědění a konání není příznivější podmínky, než že
Vás práce baví.
Klíče ke cvičením
Cvičení 1:
1.
2.
3.
4.
Robot jede dopředu poloviční rychlostí.
Robot při jízdě zahýbá.
Délka jízdy robota se zdvojnásobí
Program skončí, aniž by se robot pohnul.
Cvičení 2:
1.
2.
3.
Testování příkazů motor a wait1Msec
Otočka o 360 stupňů
cca 6500 ms
cca 3800 ms
cca 2700 ms
Cvičení 3:
Tam a zpět
task main() { //jízda dopředu se 100% výkonem a délkou 4 vteřiny motor(motorB)=100; motor(motorC)=100; wait1Msec(4000); //otočení o 180 stupňů na místě motor(motorB)=‐100; motor(motorC)=100; wait1Msec(1400); //* Délka otáčení 1,4 vteřiny se může lišit podle povrchu, na kterém robot jede. *// //jízda dopředu se 100% výkonem a délkou 4 vteřiny motor(motorB)=100; motor(motorC)=100; wait1Msec(4000); } Když se podíváte pozorně, uvidíte, že v kódu je příkaz „motor(motorC)=100;“ napsán třikrát. Tolikrát
tam ovšem není potřeba. Nastavíme-li jednou motoru C nějakou hodnotu, zůstává mu stále přiřazena, dokud mu
nenastavím jinou, či neskončí program. Proto můžeme kód tzv. optimalizovat tak, že příkaz pro nastavení
motoru C ponecháme jen v prvním výskytu:
task main() { motor(motorB)=100; motor(motorC)=100; wait1Msec(4000); motor(motorB)=‐100; wait1Msec(1400); motor(motorB)=100; wait1Msec(4000); } Cvičení 4:
Pojezd a zvuk
task main() { motor(motorB)=20; //jizda motor(motorC)=20; wait1Msec(5000); motor(motorB)=0; //pokud nevypnete motory, zvuk nepujde slyset motor(motorC)=0; PlaySound(soundDownwardTones); //prehrani zvuku while(bSoundActive); {} } Cvičení 5:
Kolečko se zvuky
task main() { //program přímo začíná zvukem, není proto potřeba časové prodlevy předem PlaySoundFile(„Start.rso“); /*přehrání zvuku Start.rso, který musí být nahrán v terminálu, nebo musí být přítomen ve složce NXT System Files programu Robotc*/ while(bSoundActive) {} //čekání na dohrání zvuku motor(motorB)=30; //výkon jednoho motoru je vyšší, než druhého motor(motorC)=100; wait1Msec(15000); //pojezd motor(motorB)=0; //vypnutí motoru B po dojezdu motor(motorC)=0; //vypnutí motoru C po dojezdu wait1Msec(1500); //časová prodleva pro přípravu zařízení PlaySoundFile(„Good Job.rso“); /*přehrání zvuku Good Job.rso, který musí být nahrán v terminálu, nebo musí být přítomen ve složce NXT System Files programu Robotc*/ while(bSoundActive) {} //čekání na dohrání zvuku } K programu lze dodat, že poloměr, který má vozidlo opsat, závisí na rozdílu výkonů motorů B a C. Čím
větší bude mezi nimi výkonový rozdíl (čím rychlejší bude jeden motor oproti druhému), tím menší je průměr
kružnice, kterou vozidlo svým pohybem vykreslí. V závislosti na výkonu a podložce, po které se robot pohybuje,
je potřeba správně zvolit dobu pojezdu.
Cvičení 6:
Popis jízdy
task main() { nxtDisplayTextLine(0,"Prubeh jizdy:"); wait1Msec(1000); nxtDisplayCenteredBigTextLine(3,"Odjezd"); motor(motorB)=100; motor(motorC)=100; wait1Msec(4000); nxtDisplayCenteredBigTextLine(3,""); /*Uvozovkami napsanými u sebe vkládáme prázdný řetězec. Tím prakticky jen smažeme předchozí text.*/ motor(motorB)=‐100; wait1Msec(1400); nxtDisplayCenteredBigTextLine(3,"Prijezd"); motor(motorB)=100; wait1Msec(4000); } Cvičení 7:
10 stupňů Celsia
task main() { byte stupne = 10; //deklarace celočíselné proměnné s počáteční inicializací číslem 10 nxtDisplayTextLine(0,“%d stupnu Celsia“,stupne); //na obrazovku se vypíše „10 stupnu celsia“ wait1Msec(10000); } Cvičení 8:
Pi
task main() { float cisloPi= 3.14159265358979323846; //deklarace reálné proměnné s počáteční inicializací. //nezapomněli jste napsat místo desetinné čárky tečku? nxtDisplayTextLine(0,“pi = %1.2f“,cisloPi); //na obrazovku se vypíše „pi = 3.14“ wait1Msec(10000); } Cvičení 9:
Výkon motorů
task main() { nxtDisplayCenteredTextLine(1,“VYKON MOTORU“); //protože se nikde v následujícím kódu nepracuje s řádkem č. 1, //zůstane text „VYKON MOTORU“ na displeji po celou dobu běhu programu int vykon = ‐20; //vytvoříme proměnnou vykon, která bude uchovávat aktuální výkon motorů //proměnnou vykon budeme také vypisovat na displej motor(motorB)=vykon; motor(motorC)=vykon; //oběma motorům je přiřazen výkon z proměnné vykon nxtDisplayCenteredBigTextLine(4,“%d“,vykon); //vypsání hodnoty proměnné vykon na displeji wait1Msec(5000); //a jedeme  vykon = 0; //proměnnou vykon již nyní nevytváříme, jen jí přiřazujeme novou hodnotu motor(motorB)=vykon; motor(motorC)=vykon; nxtDisplayCenteredBigTextLine(4,“%d“,vykon); //přepsání hodnoty proměnné vykon na displeji wait1Msec(3000); vykon = 20; motor(motorB)=vykon; motor(motorC)=vykon; nxtDisplayCenteredBigTextLine(4,“%d“,vykon); //přepsání hodnoty proměnné vykon na displeji wait1Msec(5000); } Cvičení 10:
Fotbal
task main() { string nazevTymu1 = „Real Madrid“; string nazevTymu2 = „Barcelona“; byte skoreTymu1 = 2; byte skoreTymu2 = 0; nxtDisplayCenteredBigTextLine(1, „SKORE“); nxtDisplayCenteredTextLine(3,“%s : %s“,nazevTymu1,nazevTymu2); nxtDisplayCenteredTextLine(4,“%d : %d“,skoreTymu1,skoreTymu2); wait1Msec(10000); } Cvičení 11:
Pořadí matematických operací
task main() { int vysledek1; int vysledek2; vysledek1 = 3 + 6 * 2; nxtDisplayTextLine(0,"3 + 6 * 2 = %d",vysledek1); vysledek2 = (3 + 6) * 2; nxtDisplayTextLine(1,"(3 + 6) * 2 = %d",vysledek2); wait1Msec(15000); } Cvičení 12:
Porovnání zápisů pro zvětšení proměnné
task main() { int cislo = 10; int x = 2; cislo = cislo + x; nxtDisplayTextLine(0,"Zapis1: cislo=%d",cislo); /*Abychom otestovali, zda jsou zapisy analogicke, musime znovu nastavit promenne, se kterymi se pocita, na pocatecni hodnoty.*/ cislo = 10; x = 2; cislo += x; nxtDisplayTextLine(1,"Zapis2: cislo=%d",cislo); wait1Msec(10000); } Cvičení 13:
Odpočet s proměnnou
task main() { byte odpocet = 3; nxtDisplayCenteredTextLine(3,“%d“,odpocet); wait1Msec(1000); odpocet‐‐; nxtDisplayCenteredTextLine(3,“%d“,odpocet); wait1Msec(1000); odpocet‐‐; nxtDisplayCenteredTextLine(3,“%d“,odpocet); wait1Msec(1000); nxtDisplayCenteredBigTextLine(3,“START“); PlaySoundFile(„Start.rso“); while(bSoundActive) {} motor(motorB)=100; //výkon jednoho motoru je vyšší, než druhého motor(motorC)=100; wait1Msec(5000); } Cvičení 14:
Zapnutí a vypnutí pojezdu dvěma ovladači
Nejprve si necháme vygenerovat kód nastavením potřebných dotykových senzorů:
#pragma config(Sensor, S1, start, sensorTouch) #pragma config(Sensor, S2, stop, sensorTouch) Poté by mohl následovat tento kód. Na začátku je nastavená konstanta rychlost. Zbylé příkazy jsou
uzavřeny nekonečným cyklem for(;;), aby se na detekci stisknutých dotykových senzorů stále opakovaly.
task main() { const int rychlost = 50; for(;;) { if(sensorValue(start)==1) { motor(motorB)=rychlost; motor(motorC)=rychlost; } if(sensorValue(stop)==1) { motor(motorB)=0; motor(motorC)=0; } } } Rozbor příkladu:
Pokud není stisknut žádný senzor, program prochází vnitřní příkazy cyklu stále dokola, ale nic se
neděje. Uvnitř se totiž nacházejí pouze dvě podmínky, které nejsou splněny. Pokud by byl stisknut „stop-senzor“
a robot přitom stál na místě, opět by se nic nedělo. Výkon motorů by se nastavil na nulu, ale tuto hodnotu stejně
aktuálně mají.
Při x-tém průchodu cyklu uživatel stiskne „start-senzor“. Výkon obou motorů se nastaví na hodnotu
uvedenou v konstantě rychlost a robot se rozjede. Opět připomínám, proč za nastavením motorů nemusí být
časová prodleva. Po jejím uplynutí by se totiž nic nezměnilo. V dalším cyklu by následoval dotaz na aktivitu
„stop-senzoru“, který by byl negativní a program by opět přešel na začátek nekonečného cyklu. Motory přitom
pořád jedou, protože je žádný příkaz nedeaktivoval. To nastane, až se někdy v y-tém opakování nekonečného
cyklu detekuje zmáčknutý „stop-senzor“.
Časovou prodlevu tedy tak zastupuje nekonečná smyčka cyklu, ohraničená stiskem startovního a stop
senzoru.
Cvičení 15:
Zvyšování a snižování rychlosti
#pragma config(Sensor, S1, zvyseni_vykonu, sensorTouch) #pragma config(Sensor, S2, snizeni_vykonu, sensorTouch) //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*// task main() { int vykon = 0; //deklarace proměnné výkon //inicializace počáteční hodnoty na 0 je zde nutná for(;;) { if(SensorValue(zvyseni_vykonu)==1) if(vykon < 100) //horní hodnota výkonu nesmí přesáhnout 100 vykon = vykon + 10; else vykon = 100; if(SensorValue(snizeni_vykonu)==1) if(vykon > ‐100) //dolní hodnota výkonu nesmí přesáhnout ‐100 vykon = vykon – 10; else vykon = ‐100; motor(motorB) = vykon; motor(motorC) = vykon; nxtDisplayTextLine(0,"Vykon: %d",vykon); //zobrazení rychlosti wait1Msec(100); } } Cvičení 16:
Zahýbání a jízda vpřed
#pragma config(Sensor, S1, otoceniVpravo, sensorTouch) #pragma config(Sensor, S2, otoceniVlevo, sensorTouch) //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*// task main() { for(;;) { if(SensorValue(otoceniVpravo)==1) if(SensorValue(otoceniVlevo)==1) { motor(motorB)=50; motor(motorC)=50; } else { motor(motorB)=‐50; motor(motorC)=50; } else if(SensorValue(otoceniVlevo)==1) { motor(motorB)=50; motor(motorC)=‐50; } else { motor(motorB)=0; motor(motorC)=0; } } } Cvičení 17:
Zahýbání a jízda vpřed 2
#pragma config(Sensor, S1, otoceniVpravo, sensorTouch) #pragma config(Sensor, S2, otoceniVlevo, sensorTouch) //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*// task main() { for(;;) { if(SensorValue(otoceniVpravo)==1 && SensorValue(otoceniVlevo)==1) { motor(motorB)=50; motor(motorC)=50; } if(SensorValue(otoceniVpravo)==0 && SensorValue(otoceniVlevo)==1) { motor(motorB)=50; motor(motorC)=‐50; } if(SensorValue(otoceniVpravo)==1 && SensorValue(otoceniVlevo)==0) { motor(motorB)=‐50; motor(motorC)=50; } if(SensorValue(otoceniVpravo)==0 && SensorValue(otoceniVlevo)==0) { motor(motorB)=0; motor(motorC)=0; } } } Cvičení 18:
a)
b)
c)
Generování čísel ze zadaných intervalů
x=random(100); x=random(90)+10; x=random(200)‐100; Cvičení 19:
Hra pozornosti pro dva hráče
#pragma config(Sensor, S1, hrac1, sensorTouch) #pragma config(Sensor, S2, hrac2, sensorTouch) //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*// task main() { byte cislo1; byte cislo2; byte cislo3; byte citac = 80; int skoreHrace1 = 0; int skoreHrace2 = 0; bool blokaceHrace1 = false; bool blokaceHrace2 = false; nxtDisplayCenteredBigTextLine(3,"START"); wait1Msec(2000); for(;;) { if(citac == 80) { cislo1 = random(4)+1; cislo2 = random(4)+1; cislo3 = random(4)+1; nxtDisplayCenteredBigTextLine(3,"%d %d %d",cislo1,cislo2,cislo3); citac = 0; blokaceHrace1 = false; blokaceHrace2 = false; nxtDisplayTextLine(6,"Hrac 1: %d",skoreHrace1); nxtDisplayTextLine(7,"Hrac 2: %d",skoreHrace2); } else { if(SensorValue(hrac1) == 1 && blokaceHrace1 == false) { blokaceHrace1 = true; if(cislo1 == cislo2 && cislo2 == cislo3 && cislo1 == cislo3) { skoreHrace1 = skoreHrace1 + 10; nxtDisplayTextLine(6,"Hrac 1: %d +10",skoreHrace1); blokaceHrace2 = true; } else if(cislo1 == cislo2 || cislo2 == cislo3 || cislo1 == cislo3) { skoreHrace1 = skoreHrace1 + 3; nxtDisplayTextLine(6,"Hrac 1: %d +3",skoreHrace1); blokaceHrace2 = true; } else { skoreHrace1 = skoreHrace1 ‐ 3; nxtDisplayTextLine(6,"Hrac 1: %d ‐3",skoreHrace1); } }; if(SensorValue(hrac2) == 1 && blokaceHrace2 == false) { blokaceHrace2 = true; if(cislo1 == cislo2 && cislo2 == cislo3 && cislo1 == cislo3) { skoreHrace2 = skoreHrace2 + 10; nxtDisplayTextLine(7,"Hrac 2: %d +10",skoreHrace2); blokaceHrace1 = true; } else if(cislo1 == cislo2 || cislo2 == cislo3 || cislo1 == cislo3) { skoreHrace2 = skoreHrace2 + 3; nxtDisplayTextLine(7,"Hrac 2: %d +3",skoreHrace2); blokaceHrace1 = true; } else { skoreHrace2 = skoreHrace2 ‐ 3; nxtDisplayTextLine(7,"Hrac 2: %d ‐3",skoreHrace2); } } } citac++; wait1Msec(10); if(skoreHrace1 >= 50 || skoreHrace2 >= 50) { nxtDisplayTextLine(6,"Hrac 1: %d",skoreHrace1); nxtDisplayTextLine(7,"Hrac 2: %d",skoreHrace2); if(skoreHrace1 > skoreHrace2) { nxtDisplayCenteredBigTextLine(1,"HRAC 1"); nxtDisplayCenteredBigTextLine(3,"WINS!!!"); } else if(skoreHrace1 < skoreHrace2) { nxtDisplayCenteredBigTextLine(1,"HRAC 2"); nxtDisplayCenteredBigTextLine(3,"WINS!!!"); } else nxtDisplayCenteredBigTextLine(3,"REMIZA"); wait1Msec(5000); break; } } } Klíče k souhrnným cvičením
Souhrnné cvičení 1: Jízda městem
Program vychází ze zapojení pravého motoru (při pohledu zezadu) do portu B a levého motoru do portu
C. Dále se předpokládá, že jste dodrželi obdobný tvar města, jako je v zadání souhrnného cvičení. Váš program
se v tom případě může lišit jen délkami časových prodlev, které závisí na povrchu, po kterém robot jezdí, a na
proporcích „budov“, které objíždí.
task main() { //jizda dopredu motor(motorB)=30; motor(motorC)=30; wait1Msec(4000); //otoceni o 90 stupnu doprava motor(motorB)=0; wait1Msec(3200); //jizda dopredu motor(motorB)=30; wait1Msec(4600); //otoceni o 90 stupnu doleva motor(motorB)=30; motor(motorC)=0; wait1Msec(3200); //jizda dopredu motor(motorC)=30; wait1Msec(4000); //otoceni o 90 stupnu doleva motor(motorB)=30; motor(motorC)=0; wait1Msec(3200); //jizda dopredu motor(motorC)=30; wait1Msec(2300); //otoceni o 180 stupnu na miste motor(motorB)=30; motor(motorC)=‐30; wait1Msec(3300); //zacouvani do garaze motor(motorB)=‐30; wait1Msec(2300); } Souhrnné cvičení 2: Odpočet
task main() { nxtDisplayCenteredTextLine(3,“3“); //řádky displeje jsou označeny od nuly, proto čtvrtý řádek má označení 3 wait1Msec(1000); //nápis „3“ bude na displeji 1 sekundu nxtDisplayCenteredTextLine(3,“2“); wait1Msec(1000); nxtDisplayCenteredTextLine(3,“1“); wait1Msec(1000); nxtDisplayCenteredBigTextLine(3,“START“); //nápis „START“ vypíšeme 2x větším písmem, než je odpočet PlaySoundFile(„Start.rso“); /*přehrání zvuku Start.rso, který musí být nahrán v terminálu, nebo musí být přítomen ve složce NXT System Files programu Robotc*/ while(bSoundActive) {} //čekání na dohrání zvuku //nastavení pojezdu motor(motorB)=100; motor(motorC)=100; wait1Msec(5000); } Souhrnné cvičení 3: Zahýbání
#pragma config(Sensor, S1, doprava, sensorTouch) #pragma config(Sensor, S2, doleva, sensorTouch) task main() { motor(motorB)=40; motor(motorC)=40; for(;;) { if(SensorValue(doleva)==1) { motor(motorB)=40; motor(motorC)=0; PlaySoundFile("MS_sfx_burp.rso"); while(bSoundActive); {} } else if(SensorValue(doprava)==1) { motor(motorB)=0; motor(motorC)=40; PlaySoundFile("MS_sfx_burp.rso"); while(bSoundActive); {} } else { motor(motorB)=40; motor(motorC)=40; } } } Souhrnné cvičení 4: Jízda s nastavením rychlosti předem
#pragma config(Sensor, S1, nastaveniRychlosti, sensorTouch) #pragma config(Sensor, S2, start, sensorTouch) //*!!Code automatically generated by 'ROBOTC' configuration wizard!!*// task main() { int rychlost = 0; nxtDisplayCenteredTextLine(1,"Nastaveni"); nxtDisplayCenteredTextLine(3,"Rychlost: %d",rychlost); for(;;) { if(SensorValue(nastaveniRychlosti)==1) { motor(motorB)=0; motor(motorC)=0; wait1Msec(200); rychlost = rychlost + 10; if(rychlost > 100) rychlost = 0; nxtDisplayCenteredTextLine(3,"Rychlost: %d",rychlost); } if(SensorValue(start)==1) { motor(motorB)=rychlost; motor(motorC)=rychlost; wait1Msec(100); } } } Souhrnné cvičení 5: Zastavení po uplynutí určité doby nebo nárazem do zdi
#pragma config(Sensor, S1, startStop, sensorTouch) #pragma config(Sensor, S2, start, sensorTouch) //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*// task main() { for(;;) //cyklus ceka na stisk senzoru //stiskem senzoru se rozjedou motory a jde se odpocitavat //za for nasleduje jen jeden prikaz if, proto netreba {} if (SensorValue(startStop)==1) { motor(motorB)=50; motor(motorC)=50; break; } byte cyklus = 0; for(;;) { cyklus++; wait1Msec(200); //stisk senzoru se testuje co 200ms if(cyklus==25 || SensorValue(startStop)==1) //vozidlo se zastavi po 25 x 200ms = 5s //nebo setekovanym stiskem senzoru { motor(motorB)=0; motor(motorC)=0; wait1Msec(500); PlaySound(soundUpwardTones); while(bSoundActive) {} break; } } } Souhrnné cvičení 6: Pojezdová hra
#pragma config(Sensor, S1, ovladac, sensorTouch) #pragma config(Sensor, S2, konec, sensorTouch) //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*// task main() { byte intenzitaJizdy = 0; int casJizdy; bool zvysovaniCasu = true; byte cisloHrace = 1; nxtDisplayCenteredBigTextLine(3,"HRAC %d",cisloHrace); wait1Msec(1500); nxtDisplayCenteredBigTextLine(3,""); for(;;) { if(zvysovaniCasu == true) { nxtDisplayTextLine(intenzitaJizdy,"___________________"); intenzitaJizdy++; if(intenzitaJizdy==8) zvysovaniCasu=false; } else { intenzitaJizdy‐‐; nxtDisplayTextLine(intenzitaJizdy,""); if(intenzitaJizdy==0) zvysovaniCasu=true; } wait1Msec(70); if(SensorValue(ovladac)==1) { motor(motorB)=30; motor(motorC)=30; casJizdy = intenzitaJizdy*200; wait1Msec(casJizdy); motor(motorB)=0; motor(motorC)=0; if(SensorValue(konec)==0) { if(cisloHrace==1) cisloHrace = 2; else cisloHrace = 1; eraseDisplay(); nxtDisplayCenteredBigTextLine(3,"HRAC %d",cisloHrace); wait1Msec(1500); nxtDisplayCenteredBigTextLine(3,""); } else { eraseDisplay(); nxtDisplayCenteredBigTextLine(2,"HRAC %d",cisloHrace); nxtDisplayCenteredBigTextLine(5,"WINS!!!"); PlaySoundFile("Hooray.rso"); wait1Msec(5000); } } } } Tento algoritmus má jeden malý nedostatek, jehož přítomnost Vám musím, jakožto autor sbírky,
vysvětlit. Jedná se o to, že k vyhodnocení, zda došlo ke střetu vozidla s protější stěnou, dochází až po uplynutí
celého pojezdu za daný časový úsek zvolený dotykovým senzorem. V praxi to vypadá tak, že zbývá-li do střetu
se stěnou půl sekundy, ale hráč zvolí pojezd jednosekundový, bude se střet robota se zdí ověřovat právě až po
jedné sekundě. Jestliže se ale robot během druhé půl sekundy po střetu stočí tak, že se uvolní dotykový senzor
pro testování konce hry, program hru nevyhodnotí jako ukončenou.
Daný problém by se dal vyřešit tak, že by se netestovalo až po uplynutí časového intervalu, ale
několikrát během něj. To by však kód velmi znepřehlednilo. I když si myslím, že i přesto můžete k tomuto
správnému řešení dojít, odložil bych „lepší“ řešení až na dobu, kdy budete umět zapisovat klasické cykly. Až
jejich zápis by dokázal přinést kódu kýženou přehlednost.

Podobné dokumenty

Monitorování provozu operačních systémů a jejich diagnostika

Monitorování provozu operačních systémů a jejich diagnostika neustále zvyšuje, počet potenciálních chyb v počítači může růst násobky. A to nehovořím o chybách hardwaru. Nelze se tedy divit, že neexistuje žádný expertní program, jenž by po analýze operačního ...

Více

Řízení robota MINDSTORMS NXT pomocí PC PC Controlling of

Řízení robota MINDSTORMS NXT pomocí PC PC Controlling of sestavení prvního robota a originální software pro programování. Roboti jsou schopni plnit jednoduché i více složitější úlohy, vždy záleží na konstrukci a schopnosti naprogramovat odpovídající algo...

Více

Ovládání laboratorního modelu robota Mindstorms

Ovládání laboratorního modelu robota Mindstorms středního věku, kteří jsou většinou rádi, kdyţ si umí pouţívat alespoň základní funkce jako je volaní a psaní SMS. V roce 1949 vznikly první kostičky, které umoţňovaly pevné, ale rozebíratelné stav...

Více

Programování Lego robotů pomocí NQC

Programování Lego robotů pomocí NQC využívá. Samotný jazyk NQC však může být využíván i na jiných systémech (Sun, Apple, UNIX a další). Můžete jej stáhnout z www adresy http://www.enteract.com/~dbaum/lego/nqc/ Většina z tohoto tutori...

Více

LEGO Roboti a jejich programování (teoretická a praktická část)

LEGO Roboti a jejich programování (teoretická a praktická část) jednoduchost vývojového prostředí včetně procesu programování tak, aby s robotem mohli pracovat už i žáci základních škol, kteří mají s programováním minimální zkušenosti.

Více

Ovládání laboratorního modelu Mindstorms NXT (spike) pomocí PC

Ovládání laboratorního modelu Mindstorms NXT (spike) pomocí PC rychlostí 12,1 Mb/s), přes niž lze z nadřazeného počítače do paměti mikropočítače zaznamenat řídící program nebo další systémové soubory. Na spodní straně se nalézají čtyři výstupní porty (označené...

Více

Sborník - Olympiáda techniky Plzeň

Sborník - Olympiáda techniky Plzeň PhDr. Milan Klement, Ph.D., Univerzita Palackého v Olomouci, ČR Ing. Jaroslav Novák, Ph.D., Univerzita Karlova v Praze, ČR Doc. PaedDr. Viera Tomková. Ph.D., Univerzita Konštantína Filozofa Nitra, ...

Více