0 szavazat
(150 pont) által 

El tudná valaki nekem magyarázni lépésről lépésre, hogy az alábbi feladatban miért és hogyan jött ki ez az eredmény? Hogyan váltakoznak a loop-ok? Nagyon zavaros és szeretném megérteni, mielőtt továbbmegyek.

var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');

context.fillStyle='orange';

var squareSize = 50;
var squareMargin = 5;

for (var i = 0; i < 5; i++) {
  for (j = 5 - i; j < 6; j++) {
    context.fillRect((5-j)*squareSize + (5-j)*squareMargin+10, i*squareSize+i*squareMargin+10, squareSize, squareSize);
  }
}

https://jsbin.com/rizefob/1/edit?html,js,output

1 válasz

+1 szavazat
által 
által kiválasztott
 
Legjobb válasz

Szia!

Gondolj a for ciklusra úgy, mint egy mondatra: for (kezdeti érték; feltétel; változás) {műveletek} a következőt jelenti:

  1. Add meg a kezdeti értéket (ez a ciklusváltozóra vontakozik, pl. i)
  2. Ellenőrizd, hogy a feltétel igaz-e. Ha igen, hajtsd végre a műveleteket, ha nem, lépj ki a ciklusból, és ugorj a ciklus utáni utasításra.
  3. Ha a feltétel igaz volt, változtass!, és kezd a 2)-es ponttól megint.

Mit jelent ez a fenti esetben?

Bontsuk két részre a problémát, mi történik a külső ciklus szempontjából?

  1. Legyen i nulla.
  2. i < 5?, azaz 0 < 5?, persze, ezért hajtsd végre a ciklus műveletét, ami egy másik for ciklus. Itt a belső for ciklus összes ciklusa végrehajtódik, amíg a feltétele igaz.
  3. Növeld meg i értékét 1-el, így i=1,ugorj a 2)-es lépésre...

A külsö ciklus összesen ötször fog lefutni, i értékei rendre, 0, 1, 2, 3, 4 lesznek. Amikor i 5 lesz, akkor már nem lesz igaz a feltétel. Ezért a külső ciklus kilép.

Mi történik a belső ciklus szempontjából?

A belső ciklus a külső ciklus minden különböző i értékére végig fog futni, azaz összesen 5-ször. Itt az furfang, hogy a belső ciklus kezdeti értéke függ az aktuális i értéktől. Azaz attól függ, hogy hányszor fog lefutni a belső ciklus, hogy éppen hányadik futása van a külsőnek.

Amikor i=0, akkor j=5-i, azaz 5. 5<6? Persze. Lefut a ciklus egyszer. Mert a ciklus műveleti után, amikor már megnöveled j-t eggyel (6), akkor már nem igaz, hogy 6 < 6.

Amikor i=1, akkor j=5-i, azaz 4. 4<6? Persze. Lefut a ciklus egyszer. j+1=4+1=5. Lefut a ciklus mégegyszer. Amikor megnöveled j-t megint (6), akkor már nem igaz, hogy 6 < 6, ezért a belső ciklus a második esetben 2-szer fut le.

És így tovább. Itt érdemes megjegyezni, hogy amikor a belső ciklus elkezd futni, akkor j értéke mindig az alapképletből számolódik (j=5-i), és ez határozza meg, hogy a belső ciklus hányszor fut le.

A ciklusváltozók elérhetőek a belső ciklus téglalap rajzoló utasításában is. Igazából pont arra használjuk, hogy különböző téglalapokat rajzoljunk, de ezt az utasítást csak egyszer kelljen leírni.

Mi lesz az egyes futások i és j értéke?

  1. Külső ciklus, első futás i=0
    1. Belső ciklus, első futás: i=0, j=5-i=5-0=5
  2. Külső ciklus, második futás, i=i+1=0+1=1
    1. Belső ciklus, első futás: i=1, j=5-i=5-1=4
    2. Belső ciklus második futás: i=1, j=j+1=4+1=5
  3. Külső ciklus, második futás, i=i+1=1+1=2
    1. Belső ciklus, első futás: i=2, j=5-i=5-2=3
    2. Belső ciklus második futás: i=2, j=j+1=3+1=4
    3. Belső ciklus harmadik futás: i=2, j=j+1=4+1=5
  4. Külső ciklus, harmadik futás: i=i+1=2+1=3
    1. Belső ciklus első futás: i=3, j=5-i=5-3=2
      .... és így tovább

Jó gyakorlás ha felírod a teljes sort.

Segíthet az is, ha beraksz egy console.log('i=', i, 'j=', j) sort a context.fillRectelé a belső ciklusba, így látod, hogy mi történik.

Megpróbálhatod azt is, hogy a fenti mondatokat, amiket leírtam azt a négyzet rajzolása helyett kiírja neked a program (az "első", "második" stb-t ki lehet írni számmal).

által 
és azt el tudnád magyarázni, hogy a fillrect függvény paraméterei miért azok, amik?
által 
Persze.

Megmondom őszintén, nem emlékszem a fillRect függvény paraméterezésére, ezért felmentem az MDN (Mozilla Developer Network) honlapjára, ami egy remek referencia ha HTML-el, CSS vagy Javascripttel esetleg a böngésző specifikus interfészekkel (pl DOM-al - Document Object Model-el, vagy az esetünkben a Canvassal) szeretnél valamit csinálni.

**Az MDN a webfejlesztők bibiliája.**

Beírtam az oldalra, hogy fillRect-et és kiválasztottam az első találatot. Hasonló az eredmény, ha a google-be írod be, hogy `MDN fillrect`.

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillRect

Itt le van írva a pontos paraméterezés és használat, valamint a paraméterek jelentése is:

`void ctx.fillRect(x, y, width, height);`

A void azt jelenti, hogy ez a függvény nem ad vissza értéket, csak van úgymond mellékhatása (side effect), ami az, hogy kirajzol egy téglalapot.

Ha tovább olvasod a leírást, láthatod, hogy az `x` és `y` értékek a téglalap bal felső sarkának koordinátái, a `width` a szélessége, a `height`  a magassága.

Az oldal egy szemléletes példát is hoz, illetve láthatod annak az eredményét.

**Jó de miért pont ez?**

A konkrét kérdésed az volt, hogy miért ezek a paraméterek. Ahhoz, hogy kirajzolj egy téglalapot, legalább 4 paramétert kell megadnod. Lehetne ez a négy paraméter pl a bal felső és jobb alsó sarok koordinátái is (x1, y1, x2, y2). Ez egy önkényes programozói döntés volt, amikor megalkották a `CanvasRenderingContext2D` API-ját (Application Programming Interface).

**Mit jelent az API?**

Ha készítesz egy programot, amit más fejlesztők is használnak, ki kell találnod, hogy hogyan tudják használni.  Az API az a (jobb esetben dokumentált) megállapodás a program fejlesztői és használói között, aminek a segítségével eléred a funckióit, pl ha van egy Canvasod, és szeretnél rá egy téglalapot rajzolni, azt hogyan tudod megtenni.

Nehéz jó API-t készíteni, ami logikus, könnyen bővíthető és jól használható. Ezért ez nem is igazán jellemző a Webes világban. Ezzel együtt kell élni.
által 
Szia!

Én ezt máshogy oldottam meg, de csak véletlenül sikerült. :)

A kód:

var y = 10;
for (z = 10; z <= 230; z = z + 55) {
  for (x = 10; x <= z; x = x + 55) {
    context.fillRect(x,y,50,50);
  }
  y = y + 55;
}

Nem értem, hogy a 2. Külső ciklus, második futás alkalmával miért fut le kétszer a belső ciklus, hisz az x és a z értéke is 65. Tehát csak egyszer kellene lefutni, az xy 65-ös koordinátában. Hogy jelenhet meg az x=10, y=65-ös koordinátában is a második sorban, hisz a belső ciklus első lefutása végén hozzá lett adva az x-hez az 55?
által 
Megértettem a console.log használatával! :)
Azért fut le kétszer, mert újra indul a belső ciklus, tehát az x először újra 10, s csak utána lesz 65.
...