Jak uczyć pokonywania trudności, a jednocześnie pisać cykle

Pomimo tego, że będziemy rozmawiać o jednym z podstawowych tematów, ten artykuł jest napisany dla doświadczonych profesjonalistów. Celem jest pokazanie, jakie błędne przekonania mają początkujący w programowaniu. Dla praktykujących programistów problemy te zostały już dawno rozwiązane, zapomniane lub w ogóle niezauważone. Artykuł może się przydać, jeśli nagle będziesz musiał komuś pomóc w tym temacie. W artykule nawiązano do materiałów z różnych książek o programowaniu autorstwa Schildta, Stroustripa i Okulova.

Temat o cyklach został wybrany dlatego, że sporo osób jest z niego wykluczonych przy opanowywaniu programowania.

Technika ta jest przeznaczona dla słabych uczniów. Z reguły silni ludzie nie utkną w tym temacie i nie ma potrzeby wymyślania dla nich specjalnych technik. Drugorzędnym celem artykułu jest przeniesienie tej techniki z klasy „prace dla wszystkich uczniów, ale tylko jednego nauczyciela” do klasy „prace dla wszystkich uczniów, wszystkich nauczycieli”. Nie twierdzę, że jest to absolutna oryginalność. Jeśli używasz już podobnej metodologii do nauczania tego tematu, napisz, czym różni się Twoja wersja. Jeśli zdecydujesz się skorzystać, napisz nam jak poszło. Jeśli podobna technika jest opisana w książce, proszę wpisać jej nazwę.


Pracowałam nad tą techniką przez 4 lata, ucząc się indywidualnie z uczniami na różnym poziomie wyszkolenia. W sumie jest około pięćdziesięciu studentów i dwa tysiące godzin zajęć. Na początku studenci zawsze utknęli w tym temacie i odeszli. Po każdym uczniu dostosowywano metodologię i materiały. Przez ostatni rok studenci nie utknęli już w tym temacie, dlatego postanowiłam podzielić się swoimi wnioskami.

Dlaczego tak dużo listów? Cykle są takie elementarne!

Jak pisałem powyżej, dla praktykujących programistów i dla silnych studentów złożoność koncepcji pętli może być niedoceniana. Można na przykład wygłosić długi wykład, zobaczyć kiwające głowy i inteligentne oczy. Ale gdy próbujesz rozwiązać jakikolwiek problem, zaczyna się osłupienie i niewytłumaczalne problemy. Po wykładzie studenci prawdopodobnie mieli jedynie częściowe zrozumienie. Sytuację pogarsza fakt, że sami uczniowie nie potrafią wyrazić, na czym dokładnie polegają ich urojenia.
Któregoś dnia zdałem sobie sprawę, że uczniowie postrzegali moje przykłady jako hieroglify. To znaczy jak niepodzielne fragmenty tekstu, w których trzeba dodać jakąś „magiczną” literę i zadziała.
Czasami zauważyłem, że uczniowie myślą, że do rozwiązania konkretnego problemu potrzeba coś innego projekt, którego jeszcze nie omówiłem. Chociaż rozwiązanie wymagało jedynie niewielkiej modyfikacji przykładu.

Wpadłem więc na pomysł, aby nie skupiać się na składni wyrażeń, ale na idei refaktoryzacji powtarzalnego kodu za pomocą pętli. Kiedy uczniowie opanują tę ideę, przy odrobinie praktyki można ulepszyć każdą składnię.

Kogo i dlaczego uczę?

Ponieważ nie ma egzaminów wstępnych, w zajęciach mogą brać udział zarówno uczniowie silni, jak i bardzo słabi. Więcej o moich uczniach przeczytacie w artykule Portret studentów kursów wieczorowych
Dołożyłem wszelkich starań, aby każdy, kto chce nauczyć się programowania, mógł się tego nauczyć.
Moje zajęcia odbywają się indywidualnie i za każde z nich student płaci we własnym zakresie. Wydawać by się mogło, że studenci będą optymalizować koszty i żądać minimum. Jednak ludzie idą na zajęcia twarzą w twarz z żywym nauczycielem nie dla samej wiedzy, ale dla pewności tego, czego się nauczyli, dla poczucia postępu i akceptacji ze strony eksperta (nauczyciela). Jeśli uczniowie nie poczują postępów w nauce, opuszczą szkołę. Ogólnie rzecz biorąc, zajęcia można zorganizować w taki sposób, aby uczniowie odczuwali postęp w zwiększaniu liczby znanych struktur. To znaczy najpierw uczymy się szczegółowo, potem uczymy się, potem robimy chwilę, a teraz mamy gotowy kurs tysiąca jednej nocy, w którym przez dwa miesiące studiuje się same cykle, a na koniec - student, który napisał standardowa biblioteka pod dyktando. Jednak do rozwiązywania problemów praktycznych potrzebna jest nie tylko znajomość materiału, ale także samodzielność w jego zastosowaniu i poszukiwaniu nowych informacji. Dlatego uważam, że w przypadku kursów stacjonarnych właściwą zasadą jest nauczanie minimum i zachęcanie do niezależnego studiowania niuansów i powiązanych tematów. Jeśli chodzi o pętle, uważam konstrukcję while za minimum. Można z tego zrozumieć zasadę. Znając tę ​​zasadę, możesz opanować zarówno dla siebie, jak i dla siebie.

Aby osiągnąć opanowanie materiału przez słabych uczniów, opisanie składni nie wystarczy. Należy podawać prostsze, ale różnorodne zadania i bardziej szczegółowo opisywać przykłady. Ostatecznie prędkość rozwoju jest ograniczona zdolnością ucznia do przekształcania wyrażeń i poszukiwania wzorców. Dla inteligentnych uczniów większość zadań będzie nudna. Ucząc się z nimi, nie musisz nalegać na rozwiązanie 100% problemów. Moje materiały można obejrzeć pod adresem mój github. To prawda, repozytorium przypomina bardziej grymuar czarnoksiężnika - nikt oprócz mnie nie zrozumie, co gdzie jest, a jeśli nie zaliczysz testu, możesz oszaleć

Metodologia jest zorientowana na praktykę

Teorię wyjaśniono na przykładzie rozwiązania problemu. Na zajęciach z podstaw programowania, na których uczy się gałęzi i pętli, po prostu nie da się wygłosić przydatnego wykładu na jeden temat przez całą godzinę. Aby wyjaśnić koncepcję, wystarczy 15-20 minut. Główne trudności pojawiają się podczas wykonywania zadań praktycznych.
Początkujący nauczyciele mogą omówić operatory, gałęzie, pętle i tablice podczas jednego wykładu. Ale ich uczniowie staną przed problemem przyswojenia tej informacji.
Trzeba nie tylko opowiedzieć materiał, ale także upewnić się, że słuchacze go zrozumieją.

O opanowaniu tematu decyduje to, jak student radzi sobie z samodzielną pracą.
Jeśli uczniowi udało się rozwiązać problem na dany temat bez pomocy nauczyciela, oznacza to, że temat został opanowany. Aby zapewnić samotestowanie, każde zadanie opisano w tabeli ze scenariuszami testowymi. Zadania mają jasny porządek. Pomijanie zadań nie jest zalecane. Jeśli obecne zadanie jest zbyt trudne, przejście do następnego nie ma sensu. To jeszcze bardziej skomplikowane. Aby uczeń mógł opanować aktualne złożone zadanie, wyjaśnia się mu kilka technik na przykładzie pierwszego problemu. Właściwie cała treść tematu sprowadza się do technik pokonywania trudności. Cykle są raczej skutkiem ubocznym.

Pierwszym zadaniem jest zawsze przykład. Drugie różni się nieco i wykonywane jest „samodzielnie” zaraz po pierwszym, pod okiem nauczyciela. Wszystkie kolejne zadania mają na celu zwrócenie uwagi na różne drobne rzeczy, które mogą powodować nieporozumienia.

Wyjaśnieniem przykładu jest dialog, w którym uczeń musi powtórzyć propagację i weryfikację krzyżową, aby upewnić się, że opanował część materiału.

Będę banalny i powiem, że pierwszy przykład w temacie jest bardzo ważny. Jeśli dysponujesz materiałem do obszernej samodzielnej pracy, pominięcia w pierwszym przykładzie można poprawić. Jeśli poza przykładem nie ma nic innego, to uczeń najprawdopodobniej nie opanuje tematu.

Podczas czy na?

Jedną z kontrowersyjnych kwestii jest wybór konstrukcji na przykład: podczas lub dla. Pewnego razu mój znajomy praktykujący programista, który nie miał doświadczenia w nauczaniu, spędził godzinę na przekonywaniu mnie, że pętla for jest najłatwiejsza do zrozumienia. Argumenty sprowadzały się do tego, że „wszystko jest w nim jasne i ułożone na swoim miejscu”. Jednak podstawową przyczyną trudności dla prawdziwych początkujących jest idea samego cyklu, a nie jego pisanie. Jeśli dana osoba nie rozumie tego pomysłu, będzie miała trudności ze składnią. Gdy tylko pomysł zostanie zrealizowany, problemy związane z projektowaniem kodu znikają same.

W moich materiałach motyw pętli podąża za motywem rozgałęzień. Zewnętrzne podobieństwo if i while pozwala nam na bezpośrednią analogię: „kiedy warunek w nagłówku jest prawdziwy, wówczas wykonywane jest ciało”. Jedyną osobliwością cyklu jest to, że ciało jest wykonywane wiele razy.

Mój drugi argument jest taki, że while wymaga mniej formatowania niż for. Mniej formatowania oznacza mniej głupich błędów z brakującymi przecinkami i nawiasami. Początkujący nie rozwinęli jeszcze wystarczającej uwagi i skrupulatności, aby automatycznie unikać błędów składniowych.
Trzeci argument jest wyjaśniany w wielu dobrych książkach jako pierwszy argument.

Jeśli uczeń potrafi łatwo przekształcać wyrażenia, możesz o tym porozmawiać mimochodem. Następnie uczeń wybierze to, co mu się najbardziej podoba. Jeśli transformacje sprawiają trudności, lepiej nie odwracać uwagi. Pozwól uczniowi najpierw rozwiązać wszystko za pomocą while. Kiedy już opanujesz temat pętli, możesz przepisać rozwiązania, aby poćwiczyć konwersję while na for.
Pętle warunku końcowego są dość rzadką bestią. W ogóle nie poświęcam temu czasu. Jeśli uczeń opanuje idee identyfikowania wzorców i przekształcania wyrażeń, może to rozwiązać bez mojej pomocy.

Pokazując pierwszy przykład mocnym uczniom, zwracam uwagę na fakt, że w pierwszym przykładzie ważne jest zapisanie nie tylko rozwiązania, ale także całego łańcucha działań, które doprowadziły do ​​wyniku. Leniwi uczniowie mogą zaniedbać pisanie i skopiować tylko ostateczny algorytm. Muszą być przekonani, że pewnego dnia stanie przed nimi trudne zadanie. Aby go rozwiązać, musisz wykonać kroki jak w tym przykładzie. Dlatego ważne jest, aby nagrywać wszystkie etapy. W poniższych problemach możliwe będzie pozostawienie jedynie ostatecznej wersji rozwiązania.

Główną ideą automatyzacji jest to, że powierzamy komputerowi wykonywanie rutynowej pracy za osobę. Jedną z podstawowych technik jest pisanie pętli. Stosuje się go, gdy w programie zapisano kilka identycznych, powtarzających się akcji z rzędu.

Wyraźne jest lepsze niż ukryte

Wielokrotne wyświetlanie tej samej frazy w pierwszym zadaniu zapętlonym może wydawać się dobrym pomysłem. Na przykład:

Hurra, to działa!
Hurra, to działa!
Hurra, to działa!
Hurra, to działa!
Hurra, to działa!
Hurra, to działa!
Hurra, to działa!
Hurra, to działa!

Ta opcja jest zła, ponieważ wartość licznika nie jest widoczna na wyjściu. Jest to problem dla początkujących. Nie lekceważ jej. Początkowo to zadanie było pierwszym, a zadaniem wyprowadzenia szeregu liczb w porządku rosnącym było drugim. Konieczne było wprowadzenie dodatkowych terminów „cykl N czasów” i „cykl od A do B”, które w zasadzie oznaczają to samo. Aby nie tworzyć niepotrzebnych bytów, zdecydowałem się pokazać jedynie przykład z wynikiem ciągu liczb. Niewielu osobom udaje się nauczyć trzymać w głowie licznik i modelować w głowie zachowanie programu bez przygotowania. Niektórzy uczniowie po raz pierwszy spotykają się z modelowaniem mentalnym na temat cykli.
Po odrobinie praktyki daję zadanie powtórzenia tego samego tekstu do samodzielnego rozwiązania. Jeśli najpierw podasz licznik widoczny, a potem niewidoczny, uczniowie będą mieli mniej problemów. Czasami wystarczy podpowiedź „nie pisz licznika na ekranie”.

Jak to tłumaczą inni?

W większości materiałów edukacyjnych w Internecie składnia cyklu podawana jest w ramach „wykładu”. Na przykład na stronie developer.mozilla.org (obecnie) opisano kilka innych konstrukcji wraz z pętlą while. W tym przypadku w formie szablonów podawane są jedynie same projekty. Wynik ich wystrzelenia opisano słownie, ale nie ma ilustracji. Moim zdaniem takie przedstawienie tematu zwielokrotnia użyteczność takich materiałów przez zero. Uczeń może przepisać kod i sam go uruchomić, ale nadal potrzebuje standardu do porównania. Jak zrozumieć, że przykład został przepisany poprawnie, jeśli nie ma z czym porównać wyniku?
Kiedy podany jest tylko szablon, bez przykładu, dla ucznia staje się to jeszcze trudniejsze. Jak zrozumieć, że fragmenty kodu są poprawnie umieszczone w szablonie? Możesz spróbować napisać jakoś, a następnie biegnij. Ale jeśli nie ma standardu porównania wyniku, uruchomienie też nie pomoże.

W kursie C++ dotyczącym intuicyjności składnia pętli jest opisana na trzeciej stronie wykładu 4 na temat „operatory”. Przy wyjaśnianiu składni pętli szczególny nacisk położony jest na termin „operator”. Termin jest przedstawiany jako zbiór faktów, takich jak „symbol; to jest instrukcja”, „{} jest instrukcją złożoną”, „treść pętli musi być instrukcją”. Nie podoba mi się to podejście, ponieważ wydaje się ukrywać ważne relacje za jednym terminem. Analizowanie kodu źródłowego programu na terminy na tym poziomie jest potrzebne twórcom kompilatorów w celu wdrożenia specyfikacji języka, ale nie studentom w ramach pierwszego przybliżenia. Nowicjusze w programowaniu rzadko są na tyle skrupulatni, aby zwracać tak dużą uwagę na terminy. Rzadko zdarza się osoba, która zapamiętuje i rozumie nowe słowa za pierwszym razem. Prawie nikt nie potrafi poprawnie zastosować terminu, którego się właśnie nauczył. Dlatego uczniowie otrzymują wiele błędów typu „Napisałem while(a<7);{, ale program nie działa”.
Moim zdaniem na początek lepiej podać składnię konstrukcji od razu w nawiasach. Opcja bez nawiasów powinna być wyjaśniona tylko wtedy, gdy uczeń ma konkretne pytanie: „dlaczego nie ma nawiasów i to działa”.

W książce Okulova „Podstawy programowania” z 2012 roku wprowadzenie do pętli rozpoczyna się od wzorca for, następnie podaje zalecenia dotyczące jego użycia, a następnie od razu przechodzi do eksperymentalnej części lekcji. Rozumiem, że książka została napisana dla tej mniejszości bardzo zdolnych uczniów, którzy rzadko przychodzą na moje zajęcia.

W popularnych książkach zawsze zapisywany jest wynik fragmentów kodu. Na przykład „Java 8. Kompletny przewodnik” Shildta, wydanie z 2015 r. Najpierw podawany jest szablon, potem przykładowy program, a zaraz po nim wynik wykonania.

Jako przykład rozważmy pętlę while, która działa odwrotnie
odliczanie zaczyna się od 10, a wyświetla się dokładnie 10 linii „miar”:

//Продемонстрировать применение оператора цикла while
class While {
    public static void main(String args []) {
        int n = 10;
        while (n > 0) {
            System.out.println("такт " + n);
            n--;
        }
    }
}

Po uruchomieniu program ten generuje dziesięć „cykli” w następujący sposób:
такт 10
такт 9
такт 8
такт 7
такт 6
такт 5
такт 4
такт 3
такт 2
такт 1

Podejście polegające na opisaniu szablonu, przykładowego programu i wyniku programu zostało również zastosowane w książce „Javascript for Kids” oraz w kursie js na w3schools.com. Format strony internetowej pozwala nawet na interaktywność tego przykładu.

Książka Stroustrupa „Principles and Practice Using C++” z 2016 roku poszła jeszcze dalej. Pierwszym krokiem jest wyjaśnienie, jaki wynik ma zostać uzyskany, a następnie wyświetlony zostanie tekst programu. Co więcej, nie biorą za przykład przypadkowego programu, ale dają wycieczkę do historii. Pomaga to zwrócić na to uwagę: „Słuchaj, to nie jest jakiś bezużyteczny tekst. Widzisz coś znaczącego.”

Jako przykład iteracji rozważ pierwszy program wykonany na maszynie z programem zapisanym w pamięci (EDSAC). Został napisany przez Davida Wheelera w Laboratorium Komputerowym Uniwersytetu Cambridge w Anglii 6 maja 1949 roku. Ten program oblicza i drukuje prostą listę kwadratów.
0 0
1 1
2 4
3 9
4 16
...
98 9604
99 9801

W tym przypadku każdy wiersz zawiera liczbę, po której następuje znak tabulacji („t”) i kwadrat tej liczby. Wersja C++ tego programu wygląda następująco:

//Вычисляем и распечатываем таблицу квадратов чисел 0-99
int main()
{
    int i = 0; // Начинаем с нуля
    while(i < 100){
        cout << i << 't' << square(i) << 'n';
        ++i;
    }
}

Co ciekawe, w tej książce nie opisano wzorca składni. Stroustrup w podręczniku instruktora (tłumaczenie) podkreśla, że ​​szanuje inteligencję swoich uczniów. Być może za przejaw takiej inteligencji uważa się umiejętność rozpoznania wzorca w kilku przykładach.

Jak sobie tłumaczę

Najbardziej przemyślane wydaje się podejście Stroustrupa: opisanie wyniku, następnie rozwiązanie problemu, a następnie samodzielna analiza przez ucznia. Dlatego postanowiłem przyjąć to za podstawę, ale opowiedzieć o tym na mniej historycznym przykładzie - zadaniu wyprowadzenia „spisu treści”. Tworzy rozpoznawalną kotwicę, dzięki czemu można następnie powiedzieć „zapamiętaj zadanie dotyczące spisu treści” i aby uczniowie dokładnie to zapamiętali. W moim przykładzie starałem się zapobiec dwóm kolejnym najczęściej występującym błędnym przekonaniom. Następnie napiszę o nich bardziej szczegółowo.

W tym zadaniu zapoznajemy się z technikami rozwiązywania złożonych problemów. Początkową decyzję należy podjąć prymitywnie i prosto. No to można pomyśleć jak ulepszyć to rozwiązanie.
Введение
Глава 1
Глава 2
Глава 3
Глава 4
Глава 5
Глава 6
Глава 7
Заключение

Z moich obserwacji wynika, że ​​podejście „szablon-przykład-wynik” w różnych kombinacjach w dalszym ciągu prowadzi do tego, że uczniowie postrzegają cykl jako hieroglif. Przejawiało się to w tym, że nie rozumieli, dlaczego istnieje warunek, aby tam pisać, jak wybierać między i++ a i- i innymi pozornie oczywistymi rzeczami. Aby uniknąć tych nieporozumień, w podejściu do cykli należy podkreślać znaczenie powtarzania identycznych działań, a dopiero potem sformalizowania ich za pomocą struktury. Dlatego przed podaniem składni pętli należy bezpośrednio rozwiązać problem. Prymitywne rozwiązanie problemu ze spisem treści wygląda następująco:

Console.WriteLine("Введение");
Console.WriteLine("Глава 1");
Console.WriteLine("Глава 2");
Console.WriteLine("Глава 3");
Console.WriteLine("Глава 4");
Console.WriteLine("Глава 5");
Console.WriteLine("Глава 6");
Console.WriteLine("Глава 7");
Console.WriteLine("Заключение");

Jak można to poprawić?
Zamień monotonne działania na cykl.
Jakie działania powtarzają się z rzędu bez zmian?
W tym fragmencie ich nie ma. Jednak polecenia wyświetlania słowa „Rozdział” z liczbą są do siebie bardzo podobne.
Dlatego kolejnym etapem jest znalezienie różnicy pomiędzy fragmentami. Dopiero w tym zadaniu wszystko jest jasne, wtedy nie będą powtarzane pojedyncze polecenia, ale bloki kodu o długości 5 lub więcej linii. Będziesz musiał szukać nie tylko na liście poleceń, ale także w konstrukcjach rozgałęzionych lub pętlowych.
W tym przykładzie różnica między poleceniami polega na liczbie znajdującej się po słowie „Rozdział”.
Po znalezieniu różnicy musisz zrozumieć wzór zmian. Inny fragment to liczba? Czy stale rośnie, czy maleje? Jak zmienia się wartość liczby pomiędzy dwoma zespołami stojącymi obok siebie?
W tym przykładzie liczba po słowie „Rozdział” zwiększa się w odstępach co 1. Znaleziono różnicę i ujawniono wzór. Teraz możesz zastąpić inny fragment zmienną.
Musisz zadeklarować taką zmienną przed pierwszym z powtarzających się fragmentów. Taka zmienna jest zwykle nazywana I lub j lub czymś bardziej szczegółowym. Jego wartość początkowa musi być równa pierwszej wartości wyświetlanej na ekranie. W przykładzie pierwszą wartością jest 1.
Jaką wartość początkową należy przyjąć, aby wyświetlić ciąg liczb „100, 101, 102, 103, 104, 105”?
Pierwszą liczbą w tym ciągu jest 100.
Po każdym poleceniu wyjściowym należy zwiększyć wartość tej zmiennej o 1. Ta jednostka jest krokiem zmiany.
Jaki krok będzie znajdował się w ciągu liczb „100, 102, 104, 106”?
Krok 2 w tym rzędzie.
Po zastąpieniu różniącego się fragmentu zmienną kod będzie wyglądał następująco:

Console.WriteLine("Введение");
int i;
i = 0;
Console.WriteLine("Глава " + i);
i = i + 1;
Console.WriteLine("Глава " + i);
i = i + 1;
Console.WriteLine("Глава " + i);
i = i + 1;
Console.WriteLine("Глава " + i);
i = i + 1;
Console.WriteLine("Глава " + i);
i = i + 1;
Console.WriteLine("Глава " + i);
i = i + 1;
Console.WriteLine("Глава " + i);
i = i + 1;
Console.WriteLine("Заключение");

Po zastosowaniu w kodzie techniki „wyraź wzór zmiennej” otrzymasz kilka grup identycznych akcji, które idą w rzędzie. Teraz powtarzające się czynności można zastąpić pętlą.

Kolejność rozwiązywania problemu, w którym należy użyć pętli, składa się z następujących kroków:

  1. Rozwiązuj problemy bezpośrednio, korzystając z wielu oddzielnych poleceń
  2. Znajdź wzór
  3. Wyraź wzór zmiennej
  4. Ułóż jako cykl

Następnie wprowadzane są nowe terminy, aby uczeń nie znalazł się w sytuacji „Wszystko rozumiem, ale nie potrafię tego powiedzieć”:
— licznik jest zawsze zmienną potrzebną do śledzenia liczby kroków w pętli. Zwykle jest to liczba całkowita porównywana z ograniczeniem.
— krok licznika — opis schematu zmian licznika.
- ograniczenie - liczba lub zmienna, z którą porównywany jest licznik, aby algorytm był ostateczny. Wartość licznika zmienia się, zbliżając się do limitu.
— treść pętli — zestaw poleceń, które będą powtarzane. Kiedy mówią „polecenie jest zapisane w pętli”, mają na myśli treść.
— iteracja pętli — jednorazowe wykonanie treści pętli.
— warunek pętli — wyrażenie logiczne określające, czy zostanie wykonana kolejna iteracja. (Może wystąpić tutaj zamieszanie związane ze strukturami rozgałęzionymi)
Trzeba być przygotowanym na to, że na początku uczniowie będą używać terminów w innych celach. Dotyczy to zarówno silnych, jak i słabych. Ustalenie wspólnego języka jest sztuką. Teraz napiszę krótko: musisz ustawić zadanie „zaznacz fragment kodu za pomocą <termin>” i samodzielnie poprawnie używaj tych terminów w rozmowie.
Po przekształceniu pętlą otrzymujemy fragment:

Console.WriteLine("Введение");
int i = 0;
while (i < 7) {
    Console.WriteLine("Глава " + i);
    i = i + 1;
}
Console.WriteLine("Заключение");

Główne nieporozumienie

Popularnym błędnym przekonaniem wśród uczniów jest to, że umieszczają w pętli czynności, które należy wykonać tylko raz. Na przykład tak:

;
int i = 0;
while (i < 7) {
    Console.WriteLine("Введение")
    Console.WriteLine("Глава " + i);
    i = i + 1;
    Console.WriteLine("Заключение");
}

Studenci spotykają się z tym problemem cały czas, zarówno na początku, jak i przy bardziej skomplikowanych zadaniach.
Kluczowa wskazówka w tym przypadku:

Ile razy należy powtarzać polecenie: raz czy wiele razy?

Polecenia służące do wypisania słów „Wprowadzenie” i „Wniosek” oraz zadeklarowania i zainicjowania zmiennej i nie przypominają innych, powtarzalnych działań. Są one wykonywane tylko raz, co oznacza, że ​​muszą zostać zapisane poza ciałem pętli.

Wszystkie trzy etapy rozwiązania powinny pozostać w kodzie, aby można było do nich później się odwołać w przypadku trudności. Wystarczy skomentować dwie pierwsze opcje, aby nie przeszkadzały.
Należy zwrócić uwagę ucznia na następujące fakty:
— W stanie pętli zwykle porównuje się licznik i limit. Licznik może zmieniać się w treści pętli, ale limit nie. Aby złamać tę zasadę, musisz sformułować przekonujące powody.
— Polecenia służące do wyświetlania słów „Wprowadzenie” i „Zakończenie” znajdują się poza treścią pętli. Musimy je wykonać 1 raz. „Wprowadzenie” - przed powtórzeniem czynności, „Wniosek” - po.
W procesie utrwalania tego tematu, opanowywania kolejnych, a także radzenia sobie z trudnościami, nawet mocnym uczniom warto zadać pytanie: „Ile razy trzeba wykonać tę czynność? Jeden czy wiele?

Rozwój dodatkowych umiejętności

W trakcie studiowania cykli studenci rozwijają także umiejętność diagnozowania i rozwiązywania problemów. Aby przeprowadzić diagnostykę, student musi przedstawić pożądany wynik i porównać go z wynikiem rzeczywistym. Działania naprawcze zależą od różnicy między nimi.
Ponieważ uczniowie na tym etapie wciąż nie mają pojęcia o „pożądanym” wyniku, mogą skupić się na danych testowych. Z reguły nikt na tym etapie nie rozumie jeszcze, co może pójść nie tak i jak sobie z tym poradzić. Dlatego zapisuję w notatniku opis typowych problemów i kilka sposobów ich rozwiązania. Wybór najodpowiedniejszego jest zadaniem samego ucznia.
Konieczne jest zapisanie pytań „czy wydarzyło się to, czego oczekiwano?”, „Która z tych sytuacji miała miejsce teraz?”, „Czy zastosowane rozwiązanie pomogło?”

  1. Liczba działań jest o 1 mniejsza lub większa od oczekiwanej. Rozwiązania:
    — zwiększyć początkową wartość licznika o 1.
    — zamień ścisły operator porównania (< lub >) na nieścisły (<= lub >=).
    — zmienić wartość graniczną na 1.
  2. Akcje w pętli wykonywane są bez zatrzymywania, w nieskończoność. Rozwiązania:
    — dodaj polecenie zmiany licznika, jeśli go brakuje.
    — napraw polecenie zmiany licznika tak, aby jego wartość zbliżała się do limitu.
    — usuń polecenie zmiany ograniczenia, jeśli znajduje się w treści pętli.
  3. Liczba akcji w pętli jest o więcej niż 1 mniejsza lub większa od oczekiwanej. Akcja w pętli nie została wykonana ani razu. Najpierw musisz poznać rzeczywiste wartości zmiennych tuż przed rozpoczęciem pętli. Rozwiązania:
    — zmienić wartość początkową ograniczenia
    — zmień wartość początkową licznika

Problem 3 zwykle polega na użyciu niewłaściwej zmiennej lub niezresetowaniu licznika do zera.

Po tym wyjaśnieniu uczeń może nadal mieć różne błędne wyobrażenia na temat działania pętli.
Aby rozwiać te najczęstsze, daję Ci następujące zadania:

  1. W którym użytkownik wprowadza limit, początkową wartość licznika lub krok licznika.
  2. W którym wartość licznika musi zostać użyta w jakimś wyrażeniu arytmetycznym. Wskazane jest użycie licznika w wyrażeniu radykalnym lub w mianowniku, aby różnica była nieliniowa.
  3. W którym wartość licznika nie jest wyświetlana na ekranie podczas wykonywania pętli. Na przykład wyświetlenie wymaganej liczby identycznych fragmentów tekstu lub narysowanie figury z grafiką żółwia.
  4. W którym musisz najpierw wykonać kilka powtarzalnych czynności, a potem inne.
  5. W którym musisz wykonać inne czynności przed i po powtórzeniu

Do każdego zadania należy podać dane testowe i oczekiwany wynik.

Aby zrozumieć, jak szybko możesz się poruszać, musisz przeczytać warunki tych problemów i zadać sobie pytanie: „czym różnią się od przykładu?”, „Co należy zmienić w przykładzie, aby je rozwiązać?” Jeśli uczeń odpowie sensownie, pozwól mu rozwiązać choć jedno na zajęciach, a resztę samodzielnie w domu. Jeśli rozwiązanie się powiedzie, możemy zacząć wyjaśniać warunki panujące w pętlach.
Jeśli masz problemy z samodzielnym rozwiązywaniem problemów, musisz przepracować wszystko na zajęciach. Aby rozwiązanie problemu nie przypominało rysowania sowy, radzę najpierw rozwiązać problem w sposób nieuniwersalny. Czyli tak, żeby rozwiązanie przeszło pierwszy test i nie korzystało z konstrukcji pętli. No to zastosuj przekształcenia, żeby osiągnąć uniwersalność rozwiązania.

Pętle i gałęzie

Moim zdaniem warto osobno nadać tematowi „cykle w obrębie gałęzi”. Dzięki temu później będziesz mógł zobaczyć różnicę między wielokrotnym sprawdzaniem warunku a sprawdzaniem go raz.
Zadania konsolidacji będą polegały na wyprowadzaniu liczb od A do B, które wprowadza użytkownik:
- zawsze w kolejności rosnącej.
- rosnąco lub malejąco w zależności od wartości A i B.

Temat „rozgałęziania się w pętlach” należy poruszać dopiero po opanowaniu przez ucznia technik: „zastępowania wzorca zmienną” i „zastępowania powtarzalnych czynności cyklem”.
Głównym powodem używania gałęzi wewnątrz pętli są anomalie we wzorcu. W środku pęka w zależności od danych początkowych.
Tym uczniom, którzy potrafią szukać rozwiązania łącząc proste techniki, wystarczy powiedzieć „rozgałęzienia można zapisać w pętlach” i dać problem „na przykład” w całości do samodzielnego rozwiązania.
Przykładowe zadanie:

Użytkownik wprowadza liczbę X. Wyświetla w kolumnie liczby od 0 do 9 i stawia znak „+” naprzeciwko liczby równej X.

Jeśli wpisano 00+
1
2
3
4
5
6
7
8
9

Jeśli wpisano 60
1
2
3
4
5
6+
7
8
9

Jeśli wpisano 90
1
2
3
4
5
6
7
8
9+

Jeśli wpisano 7770
1
2
3
4
5
6
7
8
9

Jeśli krótkie wyjaśnienie nie wystarczy do napisania za pomocą pętli, należy znaleźć uniwersalne rozwiązanie tego samego problemu bez pętli.
Otrzymasz jedną z dwóch opcji:
Pożądany

string temp;
temp = Console.ReadLine();
int x;
x = int.Parse(temp);
if (x==0) {
    Console.WriteLine(0 + "+");
} else {
    Console.WriteLine(0);
}
if (x==1) {
    Console.WriteLine(1 + "+");
} else {
    Console.WriteLine(1);
}
if (x==2) {
    Console.WriteLine(2 + "+");
} else {
    Console.WriteLine(2);
}
if (x==3) {
    Console.WriteLine(3 + "+");
} else {
    Console.WriteLine(3);
}
if (x==4) {
    Console.WriteLine(4 + "+");
} else {
    Console.WriteLine(4);
}
if (x==5) {
    Console.WriteLine(5 + "+");
} else {
    Console.WriteLine(5);
}
if (x==6) {
    Console.WriteLine(6 + "+");
} else {
    Console.WriteLine(6);
}
if (x==7) {
    Console.WriteLine(7 + "+");
} else {
    Console.WriteLine(7);
}
if (x==8) {
    Console.WriteLine(8 + "+");
} else {
    Console.WriteLine(8);
}
if (x==9) {
    Console.WriteLine(9 + "+");
} else {
    Console.WriteLine(9);
}

Możliwy

string temp;
temp = Console.ReadLine();
int x;
x = int.Parse(temp);
if (x==0) {
    Console.WriteLine("0+n1n2n3n4n5n6n7n8n9");
}
if (x==1) {
    Console.WriteLine("0n1+n2n3n4n5n6n7n8n9");
}
if (x==2) {
    Console.WriteLine("0n1n2+n3n4n5n6n7n8n9");
}
if (x==3) {
    Console.WriteLine("0n1n2n3+n4n5n6n7n8n9");
}
if (x==4) {
    Console.WriteLine("0n1n2n3n4+n5n6n7n8n9");
}
if (x==5) {
    Console.WriteLine("0n1n2n3n4n5+n6n7n8n9");
}
if (x==6) {
    Console.WriteLine("0n1n2n3n4n5n6+n7n8n9");
}
if (x==7) {
    Console.WriteLine("0n1n2n3n4n5n6n7+n8n9");
}
if (x==8) {
    Console.WriteLine("0n1n2n3n4n5n6n7n8+n9");
}
if (x==9) {
    Console.WriteLine("0n1n2n3n4n5n6n7n8n9+");
}

Podobne zadanie daję z góry, studiując temat rozgałęzień.
Jeśli uczeń zaproponuje „możliwą” opcję, musisz mu powiedzieć, że może być wiele rozwiązań tego samego problemu. Różnią się jednak odpornością na zmiany wymagań. Zadaj pytanie: „Ile miejsc w kodzie wymagałoby poprawienia, gdybym musiał dodać kolejną cyfrę?” W wersji „możliwej” konieczne będzie dodanie jeszcze jednego oddziału i dodanie nowego numeru w 10 innych miejscach. W „pożądanym” wystarczy dodać tylko jedną gałąź.
Ustaw zadanie polegające na odtworzeniu „pożądanej” opcji, następnie znajdź wzór w kodzie, wykonaj zamianę zmiennej i napisz pętlę.
Jeśli masz pomysł jak rozwiązać ten problem w inny sposób bez pętli, napisz proszę w komentarzach.

Pętle w pętlach

W tym temacie należy zwrócić uwagę na następujące kwestie:
— liczniki pętli wewnętrznej i zewnętrznej muszą być różnymi zmiennymi.
— licznik pętli wewnętrznej musi być wielokrotnie resetowany (tzn. w treści pętli zewnętrznej).
— w zadaniach wyprowadzania tekstu nie można najpierw wpisać jednej litery w kilku wierszach, a potem drugiej. Najpierw musisz wydrukować wszystkie litery pierwszego wiersza, następnie wszystkie litery drugiego i tak dalej.

Wyjaśnienie tematu pętli w pętlach najlepiej zacząć od wyjaśnienia znaczenia resetowania licznika do zera.
Przykładowe zadanie:

Użytkownik wprowadza dwie cyfry: R i T. Wydrukuj dwie linie znaków „#”. Pierwsza linia powinna zawierać znaki R. Druga linia zawiera elementy T. Jeśli którakolwiek liczba jest ujemna, wyświetl komunikat o błędzie.

R=5, T=11#####
###########

R=20, T=3#####################
# # #

R=-1, T=6Wartość R musi być nieujemna

R=6, T=-2Wartość T musi być nieujemna

Oczywiście ten problem również ma co najmniej dwa rozwiązania.
Pożądany

string temp;
int R;
int T;
temp = Console.ReadLine();
R = int.Parse(temp);
temp = Console.ReadLine();
T = int.Parse(temp);
int i = 0;
while (i < R)
{
    Console.Write("#");
    i = i + 1;
}
Console.WriteLine();
i = 0;
while (i < T)
{
    Console.Write("#");
    i = i + 1;
}

Możliwe nr 1

string temp;
int R;
int T;
temp = Console.ReadLine();
R = int.Parse(temp);
temp = Console.ReadLine();
T = int.Parse(temp);
int i = 0;
while (i < R)
{
    Console.Write("#");
    i = i + 1;
}
Console.WriteLine();
int j = 0;
j = 0;
while (j < T)
{
    Console.Write("#");
    j = j + 1;
}

Różnica polega na tym, że w „możliwym” rozwiązaniu do wygenerowania drugiej linii użyto drugiej zmiennej. Powinieneś nalegać na użycie tej samej zmiennej w obu pętlach. Ograniczenie to można uzasadnić faktem, że rozwiązanie z jednym licznikiem na dwa cykle będzie ilustracją pojęcia „zerowanie licznika”. Zrozumienie tego terminu jest konieczne przy rozwiązywaniu następujących problemów. W ramach kompromisu możesz zapisać oba rozwiązania problemu.

Typowy problem z użyciem jednej zmiennej licznika dla dwóch pętli wygląda następująco:
R=5, T=11#####
######

Liczba znaków w drugiej linii nie odpowiada wartości T. Jeżeli potrzebujesz pomocy w rozwiązaniu tego problemu, to warto zajrzeć do notatek o typowych problemach z pętlami. To jest objaw nr 3. Diagnozuje się go, jeśli bezpośrednio przed drugim cyklem dodasz wyjście wartości licznika. Naprawiono poprzez zresetowanie. Ale lepiej nie mówić tego od razu. Student musi spróbować sformułować przynajmniej jedną hipotezę.

Istnieje oczywiście inne rozwiązanie. Ale nigdy nie widziałem tego wśród studentów. Na etapie studiowania cykli opowieść o nich odwróci uwagę. Możesz wrócić do tego później, ucząc się o funkcjach łańcuchowych.
Możliwe nr 2

string temp;
int R;
int T;
temp = Console.ReadLine();
R = int.Parse(temp);
temp = Console.ReadLine();
T = int.Parse(temp);
Console.WriteLine(new String('#', R));
Console.WriteLine(new String('#', T));

Następne wymagane zadanie:

Wyświetl liczby od 0 do 9. Każda liczba powinna znajdować się w osobnej linii. Liczbę cyfr w wierszu (W) wprowadza się z klawiatury.

W=10
1
2
3
4
5
6
7
8
9

W=100000000000
1111111111
2222222222
3333333333
4444444444
5555555555
6666666666
7777777777
8888888888
9999999999

Jeśli uczeń opanował technikę zastępowania zmiennej, poradzi sobie dość szybko. Możliwym problemem będzie ponownie resetowanie zmiennej. Jeśli nie radzisz sobie z transformacją, oznacza to, że się spieszyłeś i musisz rozwiązać prostsze problemy.

Dziękuję za uwagę. Polub i zasubskrybuj kanał.

PS Jeśli znajdziesz literówki lub błędy w tekście, daj mi znać. Można tego dokonać zaznaczając fragment tekstu i wciskając „⌘ + Enter” na Macu oraz „Ctrl/Enter” na klasycznych klawiaturach, lub poprzez prywatne wiadomości. Jeśli te opcje nie są dostępne, napisz o błędach w komentarzach. Dziękuję!

W ankiecie mogą brać udział tylko zarejestrowani użytkownicy. Zaloguj się, Proszę.

Sonda dla czytelników bez karmy

  • 20,0%Uczę zawodowo, +12

  • 10,0%Uczę zawodowo, -11

  • 70,0%Nie uczę, +17

  • 0,0%Nie uczę, -10

  • 0,0%Inne0

Głosowało 10 użytkowników. 5 użytkowników wstrzymało się od głosu.

Źródło: www.habr.com

Dodaj komentarz