If, then, else, switch zamiast else - jak traktuje je GM
Załóżmy, że dla wszystkich przykładów w create definiujemy zmienne:
kodtest=true;
test2=false;
predkosc=5;
1. if <cośtam>
Sprawdzanie cy jakaś wartość jest większa czy mniejsza, dokonujemy poprzez używanie znaków >, >=, =, <, <=, <>
Na przykład:
kodif predkosc>5
if predkosc>=5
if predkosc<5
if predkosc<=5
if predkosc<>5
if predkosc=5
if predkosc==5 //oznacza to samo co wyżej
Jest to dość oczywiste. Skupmy się jednak na ostatnich dwóch przykładach. Pomijam już to, że dla GM oba zapisy są prawidłowe, pomimo, że znakiem = nadajemy również wartość, a powinno być to jakoś rozróżniane. Ale dla wygody jest tak. O ile porównujemy liczby, to jeszcze wszystko jest jasne, ale jak się okazuje, porównując wartości boolean, czyli true i false, można zastosować jeszcze kilka innych sztuczek. Warto zwrócić uwagę, że każdy warunek jaki postawimy po if, tak na prawdę zwraca właśnie true, lub false i wykonuje się, gdy zwrócona wartość będzie równa true. Zatem poniższe warunki tak naprawdę oznaczają to samo
kodif test=true //zwracana jest wartosc true, bo skoro zdefiniowaliśmy, że test=true, to nasz warunek tak naprawdę to if true=true...
if test //też zwracana jest wartość true, bo test=true, co zostało zdefiniowane wcześniej
Jak widać, jeżeli coś przybiera wartość true, nie trzeba pisać znaku równości co natomiast, gdybym napisał if test2 ?? Warunek oczywiście nie będzie prawdziwy, a co za tym idzie dalszy kod nie wykona się, ponieważ zdefiniowana przez nas zmienna test2=false, a warunek if test2 to inaczej if test2=true. W takim razie czy da się jakoś skrócić też warunkiem dla zmiennych równych false? Oczywiście. Wystarczy użyć znaku ! który w programowaniu oznacza negację. Neguje zatem następujące po nim wyrażenie, np.:
kodif predkosc!=5 //to taki sam zapis jak if predkosc<>5
No tak, a jak ma się to do wartości false? A tak:
kodif test2=false if test2 //test 2 false, zatem otrzymujemy funkcję if false=true - nie jest ona prawdziwa
if !test2 //test 2 jest negowany, zatem z false zrobi się true i wyjdzie nam funkcja if true=true, lub jak kto woli if false=false, w każdym bądź razie sama prawda
Skoro wiemy już jak to działa, to można pobawić się dalej:
kodif !test!=true //if false<>true
if !test!=!true //if false<>false
Warto też wiedzieć, że w podobny sposób można zmieniać wartość z true na false, na przykład gdy na zmianę po naciśnięciu spacji obiekt znika i pojawia się.:
kodif keyboard_check(vk_space) visible=!visible;
Dzięki temu, gdy visible było true, zmieni się na false (bo ! neguje czyli zamienia na przeciwne true i false), a jak visible=false to zmienia się na true. Ot, taka ciekawostka. Kolejna ciekawostka to taka, ze true to inaczej 1, a false to inaczej 0 (czyli bity jak ktoś nie wie). Zatem zamiast if test=true można napisać też:
kodif test=1
I to też prawda. Warto jeszcze zaznaczyć, że postawienie; oznacza zakończenie danej linijki kodu, zatem napiasnie if test=true; to tak naprawdę nie napisanie niczego,bo wszystko co napiszemy za znakiem ; traktowane jest, jak coś nowego.
2. if <cośtam> then
Dobra, skoro mamy warunek, trzeba by coś wykonać. Konstrukcja if <cośtam> then po naszemu znaczy po prostu Jeżeli coś tam to wtedy. Ale czy tak naprawdę potrzeba pisać zawsze then ? Okazuje się, że i tutaj GM okazuje się dość tolerancyjny i można sobie odpuścić then. Zatem kod można zapisać np.:
kodif predkosc>5 then predkosc=5;
if predkosc>5 predkosc=5; //j.w.
No dobra, zapis nie wygląda pięknie, bo brak słowa then zanieczyszcza lekko kod. Ale gdy potrzebujemy zapisać trochę więcej kodu, wygląda to już inaczej:
kodif predkosc>5 then {
predkosc=5;
test=false;
}
//i to samo, ale bez then
if predkosc>5
{
predkosc=5;
test=false;
}
No i tym razem brak then tylko upiększa kod. Warto więc czasem zastanowić sie, czy warto użyć then.
3. if <cośtam> then <cośtam> else <cośtam>
Kontrukcja else dość często sprawia początkującym programistom problem. Po prostu zapominają jej użyć, co prowadzi często do błędów. Ale jak jej w ogóle używać? Instrukcja else wykonywana jest, gdy to co wpisaliśmy w if nie jest prawdą, np.:
kodif predkosc>5 then predkosc=5 else predkosc+=1;
albo bardziej rozbudowanie:
kodif predkosc>5 then {
predkosc=5;
test=true;
}
else predkosc+=1;
Jak widać, gdy zmienna prędkość jest większa niż 5, ustawiana jest na 5, w przeciwnym wypadku dodajemy do niej 1 (tak na marginesie, powyższy kod ogranicza narastanie zmiennej predkość do 5, i tak na prawdę to lepiej zapisać go jako if predkosc<5 then predkosc+=1 else predkosc=5; a skoro już podaję przykłady pisania warunków, to również predkosc<=4 then predkosc+=1 else predkosc=5; jest prawidłowym skryptem, ale nieco mniej czytelnym na pierwszy rzut oka.). Dobra, ale przejdźmy to tego najdzczęściej popełnianego błędu - w tym celu posłużę się przykładem. Załóżmy, że dwukrotne wciśnięcie spacji powoduje, że nasz obiekt niszczy się, a po pierwszym wciśnięciu jego prędkość spada o połowę. Wniosek prosty, trzeba zrobić coś, aby za pierwszym razem nie zginął. Ustalamy zatem, że na początku zmienna test2=false;. Gdy wciskamy spację, a test2=false, to test2 ustawiamy na true, a speed=speed/2; gdy natomiast naciskamy spację i test2=true, obiekt zostaje zniszczony. Tylko jak to zapisać? No cóż, większość początkujących w zdarzeniu Keyboard Press <space> wpisze taki kod (pomijam tutaj uproszczenia o których mowa była wcześniej, dla lepszego zobrazowania):
kodif test2=false {
test2=true;
speed=speed/2;
}
if test2=true {
instance_destroy();
}
Na pierwszy rzut oka, kod jest dobry, bo oba warunki zostały wpisane jako osobne warianty. Ale po mimo to, obiekt znika za pierwszym wciśnięciem. Dlaczego? A bo w 3 linijce tego kodu, zmieniamy test2 na true, kod analizuje się dalej, zmienia prędkośc, wpada na klamerkę kończoncą ten blok kodu i co ? Wpada na warunek if test2=true - który zgodnie z tym co chwilę temu ustawiliśmy jest prawdziwy i też się wykonuje. Każde nowe if - o ile nie zostało poprzedzone słowem else i innym if, traktowane jest jako osobny, nowy kod. Wystarczy dodać else i pozbędziemy się tego błędu:
kodif test2=false {
test2=true;
speed=speed/2;
}
else if test2=true {
instance_destroy();
}
Teraz drugi kod nie wykona się bo po pierwszym if pomija wszystkie else w tym bloku, aż napotka kolejne słowo if nie poprzedzone else - czyli nowy kod bloku. Dobra, ale czy musieliśmy pisać drugie else? Nie. Skoro w przypadku, gdy test2=false, pierwsze if jest pomijane, wystarczy samo else, aby wykonać kod - tak naprawdę nie interesuje nas ile teraz wynosi test2, czy true, czy 5 czy może 'tekst' - ważne, ze nie false, bo właśnie tak stanowi pierwszy warunek. Zatem prawidłowy zapis to także:
kodif test2=false {
test2=true;
speed=speed/2;
}
else {
instance_destroy();
}
Dlaczego zatem poprzednio napisałem po else if ? Teraz zakładamy, że na początku zmienna predkosc=1, a za każdym razem, gdy naciskamy spację, zwiększa się o 1. Gdy wyniesie 2, speed zwiększymy razy 2, a gdy wyniesie 3, zniszczymy obiekt. Ten kod zapiszemy tak:
kodif predkosc=1
{
predkosc=2; //mozna tez predkosc+=1;
}
else if predkosc=2
{
predkosc=3;
speed=speed*2;
}
else {
instance_destroy();
}
No i wszystko jasne. Jeżeli predkosc nie równa się 1, to sprawdzamy drugi warunek, ale skoro nie równa się 2, to wykonany zostanie następny, a jako że nie ma tam już żadnego innego warunku, tylko samo else, no to dla każdej innej wartości zostanie wykonany ten właśnie kod. No właśnie - to należy podkreślić - dla każdej innej, nie spełniającej dwóch pierwszych warunków. Zatem nie tylko dla predkosc=3, ale też predkosc=-1, predkosc=10, predkosc='test'; (chociaż doszukiwanie się w zmiennej tekstowej zmiennej liczbowej, może wywalić nam errora, ale to inna bajka :P), zatem aby ominąć ten błąd poprawiamy kolejny raz nasz kod:
kodif predkosc=1
{
predkosc=2; //mozna tez predkosc+=1;
}
else if predkosc=2
{
predkosc=3;
speed=speed*2;
}
else if predkosc=3
{
instance_destroy();
}
No. To mamy za sobą kawał dłuugiej lekcji, z której na pewno dało się sporo wynieść. Nie rozpisuje się już na temat and or i łączenia warunków, czy zagnieżdzania w jedym warunku kolejnych. Zwrócę jednak uwagę na jeszcze jeden zapis - a mianowocie, kiedy if i else warto zastąpić switchem.
4. Switch zamiast if .. else if .. else if .. else
Bierzemy znany nam już kod, który niszczy obiekt, zawsze poza przypadkiem gdy predkosc=1 lub =2.
kodif predkosc=1
{
predkosc=2; //mozna tez predkosc+=1;
}
else if predkosc=2
{
predkosc=3;
speed=speed*2;
}
else instance_destroy();
switch to taka jakby szafa z szufladami, które otwieramy w określonych przypadkach i jedną szufladą, otwieraną, dla pozostałych przypadków, na które nie było już w tej szafie miejsca. Powyższa konstrukcja wygląda jako switch tak:
kodswitch predkosc
{
case 2: predkosc=3; speed=speed*2; break;
case 1: predkosc=2; break;
default: instance_destroy(); break;
}
Trochę mniej miejsca, nie? Od razu mówię, po co tam funkcja break. Otóż break powoduje, przerwanie przetwarzania dalej danego bloku, zatem jeżeli prędkość=2 i wykonany zostaje case 2, to reszta kodu będzie pominięta - czyli inaczej zrobi się else if. Z kolei default to czyste else. Fakt braku break i wykonania nastepnych linijek kodu można wykorzystać - skoro zawsze dodajemy do prędkości 1:
kodswitch predkosc
{
case 2: speed=speed*2;
case 1: predkosc+=1; break;
default: instance_destroy(); break;
}
i teraz dla case 2 zostaną wykonane również instrukcje poniżej - pomimo, że to case 1. Po prostu, gdy otworzymy daną szufladę, automatycznie dostajemy dostęp do wszystkich następnych na tak długo, aż napotkamy break.
Warto zapamiętać to o czym była dzisiaj mowa, warto eksperymentować i mieszać ze sobą poznane techniki - naprawdę można w ten sposób zdziałać wiele, bo ja nie wyczerpałem jeszcze tematu.
Miłej zabawy!