jardínBit

Ciclos: while y for

Los ciclos, bucles o loops son expresiones que nos permiten programar operaciones repetitivas con pocas líneas de código.

La función de draw() es un caso especial de ciclo en cuanto a que se repite pero de acuerdo a nociones de tiempo (30 veces por segundo)

[Ciclo de animación]

1 Ciclo while

El ciclo while (“mientras”) es la expresión fundamental para indicar ciclos en Processing.

Consiste en un bloque de código que se va a repetir mientras una condición booleana sea verdadera (true).

[Variables y expresiones booleanas]

Es importante que dentro del ciclo suceda al menos una operación que haga que la condición eventualmente se evalúe como falsa (false). De no ser así, habremos establecido un bucle infinito y veremos cómo Processing se traba.

1.1 while con acumulador

Un ejemplo que dibuja puntos distribuidos horizontalmente, entre 0 y 200 en X, y a una altura de 200 en Y:

// cambia el grosor de los puntos
strokeWeight(5);

// posición inicial del primer punto
float x = 0;
// repite el bloque de código mientras x sea menor a 200
while( x < 200 ){ 
    point( x, 200); // dibuja un punto
    x = x + 5; // incrementa a x 
}

La variable x funciona como acumulador, y tomará los valores 0, 5, 10, 15, 20 … 190, 195. Cuando llega a 200, la condición ya no se cumple y el ciclo termina.

[Variables: Contadores, Acumuladores, Banderas]

1.2 while con contador

En este otro ejemplo con resultado visual similar, usamos una variable como contador:

// cambia el grosor de los puntos
strokeWeight(5);

// valor inicial del contador
int cuenta = 0;

// repite el bloque de código mientras el contador sea menor a 20
while( cuenta < 20 ){ 
    point( cuenta*5, 200); // dibuja un punto de acuerdo al valor de cuenta

    // incrementa el contador por 1
    cuenta = cuenta + 1;
}

Aquí, cuenta tomará los valores 0, 1, 2, 3, 4, 5 … 18, 19. Cuando llega a 20 la condición ya no se cumple, y el ciclo termina. Se habrán dibujado 20 puntos.

Esta es otra forma de obtener 20 repeticiones, pero el resultado visual será un poco distinto. ¿Puedes encontrar cuál es la diferencia?

// cambia el grosor de los puntos
strokeWeight(5);

// valor inicial del contador
int cuenta = 1;

// repite el bloque de código mientras el contador sea menor igual a 20
while( cuenta <= 20 ){ 
    point( cuenta*5, 200); // dibuja un punto de acuerdo al valor de cuenta

    // incrementa el contador por 1
    cuenta = cuenta + 1;
}

1.2.1 Repeticiones contadas

Una ventaja de este formato es que podemos especificar cuántas veces queremos que se repita alguna acción, aunque no haya en juego alguna otra variable que indique el final como en el caso del acumulador.

Por ejemplo, el siguiente código dibuja 100 puntos en posiciones aleatorias dentro de todo el canvas:

int cuenta = 1;

while ( cuenta <= 100 ){
    point( random(width), random(height) );
    cuenta = cuenta + 1;
}

2 Ciclo for

Probablemente es el tipo de ciclo más utilizado en programas gráficos como los que hacemos en processing.

Como sea, es una construcción que se basa en un caso específico del ciclo while, así que cualquier operación que podamos realizar con for también se puede realizar con while.

El ciclo for suele utilizarse como una expresión en la que indicamos que ciertas operaciones han de repetirse un número específico de veces.

Desafortunadamente su sintaxis es muy extraña, y hay que practicarla mucho para dejar de tener fallas:

for(int i=0; i<10; i++){
   // repite este bloque de código 10 veces
}

Entre los paréntesis del for, hay tres partes separadas entre ellas por punto y coma:

Lo que normalmente hace el ciclo for es:

  1. Declarar una variable para contar (i) que empieza en 0
  2. Evaluar si la condición booleana es verdadera (por ejemplo, si la variable es menor al número escrito); si sí, continúa, si no, termina el ciclo
  3. Ejecutar el bloque de código en su interior
  4. Incrementar en 1 el valor de la variable para contar (i)
  5. Regresar al paso 2

Durante la primera iteración del ciclo, la variable para contar (i) vale 0, la siguiente vez 1, después 2, y así sucesivamente.

En nuestro ejemplo, el último valor al que llega la variable para contar es 9, porque a partir de 10, la condición booleana empieza a tener un resultado false.

2.1 Ejemplo: líneas horizontales

Podríamos dibujar 10 líneas horizontales, separadas a la misma distancia entre ellas, de la siguiente forma:

line(0, 0, width, 0);
line(0, 5, width, 5);
line(0, 10, width, 10);
line(0, 15, width, 15);
line(0, 20, width, 20);
line(0, 25, width, 25);
line(0, 30, width, 30);
line(0, 35, width, 35);
line(0, 40, width, 40);
line(0, 45, width, 45);

Escribir 10 líneas así tal vez no es mucho problema, pero sí se vuelve inconveniente el hacer 100 o 1000.

Para traducir esa expresión a un ciclo for, lo que tenemos que hacer es identificar el patrón que hay: qué tienen en común las funciones, qué cambia, y cómo cambia lo que cambia.

En nuestro caso, podemos ver que:

2.1.1 Versión paramétrica

Ya con el patrón identificado, podemos pasar a abstraerlo dentro de un ciclo:

for(int i=0; i<10; i++){ // repite 10 veces:
  line(0, i*5, width, i*5);
}

Nota que las coordenadas X se quedaron igual, constantes, y las coordenadas Y ahora están en función de la variable que cuenta (i).

cuando i es 0, la expresión se convierte en:

line(0, 0, width, 0);

cuando i es 1, la expresión se convierte en:

line(0, 5, width, 5);

cuando i es 2, la expresión se convierte en:

line(0, 10, width, 10);

y así sucesivamente.

Una ventaja es que si ahora queremos dibujar 100 o 1000 líneas con esa plantilla, solo hemos de cambiar un número en nuestra expresión:

for(int i=0; i<100; i++){ // repite 100 veces:
  line(0, i*5, width, i*5);
}

2.1.2 Versión acumulador

Otra posibilidad es utilizar una variable y para ese parámetro de las líneas, e incrementarla en cada iteración del ciclo:

float y = 0;

for( int i=0; i<10; i++){ // repite 10 veces:
    line( 0, y, width, y); // "plantilla" de la línea
    y = y + 5; // realiza el cambio en cada iteración
}

[Variables: Contadores, Acumuladores, Banderas]

3 Notas relacionadas

En este tutorial se ahonda en más posibilidades de dibujo con ciclos for:

Tutorial: Patrones con líneas con ciclos

Y estas notas expanden en variaciones más complejas: