Możemy spotkać się z sytuacją, że nasz program będzie miał wykonać jeden z kilku równorzędnych fragmentów kodu. Tak może działać np. prosty kalkulator, który wykonuje na podanych mu liczbach jedną z czterech operacji: kod ustalający jakie to liczby i wyświetlający wynik byłby ten sam w każdym przypadku, natomiast kod wykonujący działanie byłby inny dla dodawania, odejmowania, mnożenia i dzielenia.
Podobnie w sytuacji gdy mamy robota sterowanego za pomocą prostego joysticka. Mamy cztery kierunki, w których porusza się robot: przód, tył, lewo, prawo. Kierunki wybieramy przyciskami. Całe oprogramowanie robota pozostaje takie samo, np. procedura wykrywająca przeszkodę, natomiast inne będą procedury sterujące silniczkami będą inne dla każdego kierunku.
STEROWANIE ROBOTEM
Nasz robot posiada prosty, przewodowy joystick, składający się z czterech przycisków. Naciśnięcie przycisku powinno uruchomić odpowiadający mu silnik i robot powinien ruszyć w odpowiednim kierunku. Mamy też procedurę, sprawdzającą, czy nie natknęliśmy się na przeszkodę. Jej kod nie jest dla nas w tej chwili istotny, powiem tylko, że może działać na zasadzie odbierania sygnałów z tzw. mikrostyków (stosowanych m.in. w telefonach stacjonarnych w przycisku, na którym kładziemy słuchawkę lub w przyciskach myszki komputerowej): jeżeli robot dotknie jakiejś przeszkody, naciska tym samym jeden z mikrostyków i w ten sposób wysyła informację, że dalej w tym kierunku nie może jechać. Możemy nawet sprawić, że robot cofnie się nieco przy napotkaniu przeszkdy, ale to zostawiam czytelnikom jako ćwiczenie.
Joystick jest podłączony następująco:
P0.0 – przód
P0.1 – tył
P0.2 – lewo
P0.3 – prawo
Możemy dla ułatwienia i czytelności programu zastosować tzw. stałe, pisząc:
#define JOY_PRZOD P0.0
#define JOY_TYL P0.1
itd.
Od tej chwili zamiast P0.0 możemy pisać w naszym programie JOY_PRZOD itd.
Silniczki są podłączone następująco:
P0.4 – przód
P0.5 – tył
P0.6 – lewo
P0.7 – prawo
Tutaj też zastosujmy stałe, nadając nazwy odpowiednio: SILNIK_PRZOD, SILNIK_TYL itd.
Czujniki mikrostykowe (jest ich również 4) są podłączone do portu P1, ale ich konkretna realizacja nie jest dla nas w tej chwili ważna. Mamy procedurę czy_przeszkoda(), która zwraca wartość true jeśli jest przeszkoda albo false jeśli droga jest wolna i na podstawie tych danych będziemy sterowali robotem. Ma się on zatrzymać jeśli napotka przeszkodę i nie jechać w podanym kierunku.
NASZ PROGRAM I INSTRUKCJA SWITCH
Oprogramowanie robota oprzemy na pętli while(). Znajdzie się w niej procedura pobierająca stan joysticka get_joystick() i zwracająca odpowiednio wartości: „PRAWO”, „LEWO”, itd. Instrukcja switch będzie odpowiedzialna za sprawdzenie, czy natknęliśmy się na przeszkodę i jeśli nie, uruchomienie silniczka.
Instrukcja switch posiada następującą formę:
switch(wyrażenie) { case ‘wyrażenie’:
funkcja1();
funkcja2();
break;
case ‘wyrażenie2’:
funkcja3();
funkca4();
break;
default:
funkcja5();
break;
}
JAK TO DZIAŁA?
Instrukcja switch wybiera jedną z możliwości i wykonuje przypisane do niej działania. Jeżeli, tak jak w naszym przypadku, mamy do czynienia z funkcją zwracającą różne wartości – get_joystick(), będziemy mogli w łatwy sposób napisać czytelny algorytm. Podajemy więc do switch() naszą funkcję get_joystick():
switch(get_joystick())
Teraz, w zależności od tego, co zwróci funkcja get_joystick(), będziemy chcieli wybrać odpowiedni przypadek (ang. case) i wykonać przypisane do niego funkcje. Musimy więc przygotować kod dla wartości PRZOD, TYL itd. oraz dla sytuacji, gdy nie naciśnięto żadnego przycisku.
JEDZIEMY DO PRZODU
Zanim uruchomimy silnik, musimy sprawdzić, czy nie natknęliśmy się na stojącą przed naszym robotem przeszkodę. Jeżeli tak jest, to nie jedziemy nigdzie, szkoda bowiem czerpać niepotrzebnie baterie i zużywać silnik. Sprawdzamy więc za pomocą znanej już instrukcji if:
if(!przeszkoda()) { jedz_do_przodu();
}
Wykrzyknik przed funkcją przeszkoda() to negacja. Dzięki niemu wyrażenie to możemy tłumaczyć tak: jeżeli nie przeszkoda, to zrób jedz_do_przodu().
Switch może sprawdzić kilka warunków jednocześnie, np. gdy mamy jedną procedurę dla kolorów czerwonego, zielonego i niebieskiego:
case ‘czerwony’:
case ‘zielony’:
case ‘niebieski’:
rysuj();
Jeśli chcemy, by switch skończył na którymś z przypadków swoje działanie, wstawiamy na końcu instrukcję break (ang. przerwij):
if(!przeszkoda()) { jedz_do_przodu();
}
break;
Osobnym przypadkiem jest default – nie ma on żadnej wartości i jest wykonywany wtedy, gdy żaden inny nie został wykonany. U nas znajdzie on zastosowanie jeśli nie zostanie naciśnięty żaden przycisk – robot nie będzie wtedy nic robił, a default przyjmie postać:
default: break;
Cała nasza instrukcja switch będzie wyglądała tak:
switch(get_joystick()) { case ‘PRZOD’:
if(!przeszkoda()) { jedz_do_przodu();
}
break;
case ‘TYL’:
if(!przeszkoda()) { jedz_do_tylu();
}
break;
case ‘PRAWO’:
if(!przeszkoda()) { jedz_na_prawo();
}
break;
case ‘LEWO’:
if(!przeszkoda()) { jedz_na_lewo();
}
break;
default:
break;
}
Tak jak mówiłem, czytelnikom pozostawiam jako ćwiczenie takie zmodyfikowanie tego programu, by robot, w momencie natknięcia się na przeszkodę, cofał się od niej.



Programowanie w C