mgr inż. Wacław Libront * Bobowa 2017-2019
ZSO Bobowa, ul. Długoszowskich 1, 38-350 Bobowa, tel: 0183514009, fax: 0183530221, email: sekretariat@zsobobowa.eu, www: zsobobowa.eu
Czym jest rekurencja? Takie „pudełko w pudełku, w pudełku…”. W funkcji rekurencyjnej musi być „strażnik”, którego zadaniem jest zakończenie wywoływania kolejnych funkcji – odkrywania kolejnych pudełek. Bez strażnika program będzie wykonywał się w nieskończoność, co grozi zawieszeniem się programu.
Kwadrat rekurencyjny
Funkcja
rysuje kwadraty, ale nie za pomocą poznanej pętli FOR, ale przez kolejne
wywołanie samej siebie. Funkcja najpierw "otwiera" kolejne "pudełka", i gdy
dojdzie do ostatniego (n=1) zaczyna je zamykać, i podczas zamykania rysowany
jest kwadrat z odpowiednimi parametrami.
Dla zobrazowania różnicy utworzono podobną funkcję działającą w pętli.
<canvas width="400" height="400" id="can"></canvas> <script> var c = can.getContext("2d"); // funkcja tradycyjna function nKwadrat(n) { c.strokeStyle = "blue"; for (var i = n; i > 0; i = i - 1) { c.strokeRect(i * 30, i * 30, 100, 100); } } //uruchomienie nKwadrat(4); // funkcja rekurencyjna function nKwadratR(n) { if (n > 1) { nKwadratR(n - 1); } c.strokeRect(n * 30, n * 30, 100, 100); } //uruchomienie nKwadratR(4) </script> |
Drzewa
Drzewa są typowym przykładem rekurencyjnego rysowania. Pojedyncza gałąź jest zwykłym
cienkim prostokątem.
Jak narysować Drzewo? Najpierw obracamy układ i rysujemy cienki prostokąt.
Następnie sprawdzamy czy długość gałęzi nie przekroczyła zakładanego minimum
i przesuwamy układ na koniec narysowanego prostokąta. Teraz rekurencyjnie wywołujemy rysowanie dwóch pochylonych w różne strony gałęzi.
Otrzymamy drzewo dokładnie symetryczne. Jeśli wprowadzimy odrobinę chaosu za pomocą losowego kąta obrotu…?
//drzewa var kat = 0.35; var Skala = 0.75; var l = 75; var minL = 5; var w = c.canvas.width; var h = c.canvas.height; c.translate(w/2, h); rysujGalaz(l, 0); function rysujGalaz(l, kierunek) { c.save(); //losowy kąt jesli chcemy rozne drzewa kat=(Math.random()*60)*Math.PI/180; c.rotate(kat * kierunek); c.fillRect(-l / 20, 0, l / 10, -l); if (l > minL) { c.translate(0, -l); rysujGalaz(l * Skala, -1); rysujGalaz(l * Skala, 1); } c.restore(); } |
Płatek Kocha
Płatek składa się z jednej linii.
Jeśli długość linii jest mniejsza od 5,
to rekurencyjnie rysowane są
4 linie w układzie
z "wybojem" (kąty 60°). I to wystarczy, aby narysować płatek Kocha.
Płatek można powtórzyć trzy razy, za każdym razem przesuwając się o długoć podstawowego boku płatka i obracając o 120 stopni - powstanie "seretka".
c.translate(100,100); function platek(bok){ c.save(); c.beginPath(); //linia c.moveTo(0,0); c.lineTo(bok,0); c.stroke(); if (bok>5) { var b=bok/3; platek(b); c.translate(b,0); c.rotate(-60*Math.PI/180); platek(b); c.translate(b,0); c.rotate(120*Math.PI/180); platek(b); c.translate(b,0); c.rotate(-60*Math.PI/180); platek(b); } c.restore(); } //płatek Kocha platek(200); //serwetka Kocha for (var i=0;i<3;i++){ platek(200); c.translate(200,0); c.rotate(120*Math.PI/180); } |
Szablon
<canvas width="400" height="400" id="can"></canvas> <script> var c = can.getContext("2d"); </script> |