PHPlay

Curso de PHP gratis · Capítulo 6 de 13 · con Mara Vuelta

Bucles en PHP: while, for, do-while, break y continue

Los bucles son lo que hace a los ordenadores útiles: repetir sin cansarse. Aquí aprenderás while, for y do-while, y a controlarlos con break y continue.

while: mientras...

while repite un bloque mientras su condición sea verdadera:

while (condición) {
    // se repite
}

El funcionamiento exacto:

  1. Evalúa la condición.
  2. Si es falsa, sale del bucle y sigue con lo de después.
  3. Si es verdadera, ejecuta el bloque entero y vuelve al paso 1.

Cada repetición se llama iteración. Observa en el paso a paso cómo la ejecución vuelve una y otra vez a la línea del while.

<?php
$vueltas = 3;
while ($vueltas > 0) {
    echo "¡Vuelta! Quedan $vueltas\n";
    $vueltas--;
}
echo "El molino se para\n";
Salida
¡Vuelta! Quedan 3
¡Vuelta! Quedan 2
¡Vuelta! Quedan 1
El molino se para

Anatomía de un bucle

Casi todos los bucles tienen tres partes:

  1. Inicialización: $i = 0;
  2. Condición: $i < 5
  3. Actualización: $i++

Si olvidas la actualización, la condición nunca cambia y el bucle no termina nunca: un bucle infinito. En PHP real, el programa se cortaría al llegar al tiempo máximo de ejecución (max_execution_time, normalmente 30 segundos); en PHPlay te avisaré antes.

Pergamino del porque

Este es el error más común con los bucles. Antes de ejecutar, pregúntate siempre: ¿qué hace que esta condición llegue a ser falsa?

<?php
$i = 0;
while ($i < 5) {
    echo $i, " ";
    $i++;
}
echo "\nAl salir, i vale $i\n";
Salida
0 1 2 3 4 
Al salir, i vale 5
Pregunta

¿Cuántas veces se imprime "hola"? $i = 10; while ($i < 5) { echo "hola"; $i++; }

  1. 0
  2. 1
  3. 5
  4. Infinitas
Ver respuesta

A. 0

La condición se comprueba ANTES de la primera iteración: 10 < 5 es falso, así que el bloque no se ejecuta nunca.

for: el bucle con contador

Cuando sabes cuántas veces quieres repetir, for junta las tres partes en una línea:

for (inicialización; condición; actualización) {
    ...
}

Es exactamente equivalente al while de la página anterior, pero más compacto y más difícil de olvidar la actualización.

Por convención, los contadores se llaman $i, $j, $k...

<?php
for ($i = 1; $i <= 5; $i++) {
    echo "7 x $i = ", 7 * $i, "\n";
}
for ($n = 10; $n > 0; $n -= 3) {
    echo $n, " ";
}
echo "\n";
Salida
7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
10 7 4 1 

do-while: al menos una vez

do { ... } while (condición); comprueba la condición al final. Por eso el bloque se ejecuta al menos una vez, aunque la condición sea falsa desde el principio.

Se usa poco, pero es perfecto para cosas como "pide un dato hasta que sea válido": siempre hay que pedirlo una primera vez.

<?php
$intentos = 10;
do {
    echo "Intento $intentos\n";
    $intentos++;
} while ($intentos < 3);
echo "Se ejecutó una vez aunque 10 < 3 es falso\n";
Salida
Intento 10
Se ejecutó una vez aunque 10 < 3 es falso

break y continue

Dos palabras para controlar un bucle desde dentro:

  • break sale del bucle inmediatamente.
  • continue salta el resto de esta iteración y pasa a la siguiente.

Con bucles anidados, break 2 sale de dos niveles a la vez.

<?php
for ($i = 1; $i <= 10; $i++) {
    if ($i % 3 == 0) {
        continue;
    }
    if ($i > 7) {
        break;
    }
    echo $i, " ";
}
echo "\n";
Salida
1 2 4 5 7 

Bucles dentro de bucles

Un bucle puede contener otro: es un bucle anidado. Por cada iteración del de fuera, el de dentro se ejecuta completo.

Si el de fuera da 3 vueltas y el de dentro 4, el cuerpo interior se ejecuta 3 × 4 = 12 veces. Es la forma natural de recorrer cualquier cosa en 2D: una tabla, una imagen... o un campo.

<?php
for ($fila = 1; $fila <= 3; $fila++) {
    for ($col = 1; $col <= 4; $col++) {
        echo "[$fila,$col]";
    }
    echo "\n";
}
Salida
[1,1][1,2][1,3][1,4]
[2,1][2,2][2,3][2,4]
[3,1][3,2][3,3][3,4]

BIT-8 recorre el campo

Con un bucle, BIT-8 recorre una fila entera. Y aquí el campo "donut" se vuelve un aliado: si el campo mide tam() casillas y te mueves tam() veces al ESTE, vuelves a la casilla de la que saliste.

Así, para recorrer TODO el campo:

$n = tam();
for ($y = 0; $y < $n; $y++) {
    for ($x = 0; $x < $n; $x++) {
        cosechar();
        mover(ESTE);
    }
    mover(NORTE);
}

Al terminar cada fila BIT-8 ya está otra vez en la columna 0, listo para subir. Da igual el tamaño del campo: el mismo programa sirve para 3x3 o para 8x8.

<?php
// Cosechar sin parar (hasta agotar la batería)
while (true) {
    if (puede_cosechar()) {
        cosechar();
    }
    mover(NORTE);
}
Truco

En un programa normal, while (true) sin un break es un error. Pero BIT-8 tiene batería: cuando se agota, el programa se detiene de forma segura. Por eso es la forma típica de programar tu granja.

Pregunta

En un campo de 4x4, ¿cuántas veces se ejecuta cosechar() en el recorrido de la izquierda?

  1. 4
  2. 8
  3. 16
  4. 20
Ver respuesta

C. 16

4 filas × 4 columnas = 16 iteraciones del bucle interior.

El tablero de ajedrez

El operador módulo % es muy útil dentro de los bucles:

  • $i % 2 == 0 → $i es par.
  • ($x + $y) % 2 == 0 → las casillas de un tablero de ajedrez: se alternan como las blancas y las negras.

¿Por qué te interesa? Porque los árboles crecen despacio si tienen otro árbol al lado. Si los plantas en patrón de ajedrez, ninguno toca a otro (solo en diagonal).

<?php
$n = 5;
for ($y = 0; $y < $n; $y++) {
    for ($x = 0; $x < $n; $x++) {
        if (($x + $y) % 2 == 0) {
            echo "T ";
        } else {
            echo ". ";
        }
    }
    echo "\n";
}
Salida
T . T . T 
. T . T . 
T . T . T 
. T . T . 
T . T . T 

Ejercicios de Bucles en PHP resueltos

Intenta resolverlos antes de mirar la solución. En el juego puedes ejecutarlos y comprobarlos automáticamente.

Misión del dron 1. Cosecha total

Todo el campo de Mara está maduro: 16 casillas de hierba.

Cosecha las 16 casillas del campo 4x4 usando bucles (nada de copiar 16 veces).

Esta misión mueve al dron BIT-8 por un campo de cultivo: juégala en PHPlay para ver tu código animado.

Pistas
  • Un bucle para las filas y, dentro, otro para las columnas.
  • Al final de cada fila, mover(NORTE);. El campo es un donut: moverte 4 veces al ESTE te devuelve a la columna 0.
Ver solución
<?php
for ($y = 0; $y < 4; $y++) {
    for ($x = 0; $x < 4; $x++) {
        cosechar();
        mover(ESTE);
    }
    mover(NORTE);
}

Encargo 2. La tabla del molino

Mara quiere colgar en la pared la tabla del número $n (ya existe).

Imprime la tabla de multiplicar de $n del 1 al 10, una línea por resultado:

7 x 1 = 7
7 x 2 = 14
...
7 x 10 = 70
Pistas
  • for ($i = 1; $i <= 10; $i++)
  • Dentro: echo "$n x $i = ", $n * $i, "\n";
Ver solución
<?php
for ($i = 1; $i <= 10; $i++) {
    echo "$n x $i = ", $n * $i, "\n";
}

Predicción 3. Vueltas y saltos

Mara garabatea un bucle en su pizarra. ¿Qué imprime?

Escribe exactamente la salida.

<?php
for ($i = 1; $i <= 3; $i++) {
    for ($j = 1; $j <= 3; $j++) {
        if ($j == 2) {
            continue;
        }
        if ($i == 3) {
            break;
        }
        echo "$i$j ";
    }
}
    Ver solución
    11 13 21 23 

    ¡Exacto! continue solo salta esa vuelta del bucle interior y break solo sale del interior.

    Caza de bugs 4. El molino que no para

    Este bucle debería contar del 0 al 4, pero el molino se ha quedado girando para siempre.

    Arregla el bucle para que imprima exactamente 01234.

    Código de partida:

    <?php
    $i = 0;
    while ($i < 5) {
        echo $i;
    }
    
    Pistas
    • ¿Qué hace que $i < 5 llegue a ser falso?
    • Falta actualizar el contador: $i++; dentro del bucle.
    Ver solución
    <?php
    $i = 0;
    while ($i < 5) {
        echo $i;
        $i++;
    }
    

    Misión del dron 5. La granja infinita

    La hierba vuelve a crecer al cabo de un rato. Un buen granjero no para... hasta que se acaba la batería.

    Consigue al menos 40 de heno con una sola ejecución (batería: 300), sin cortar nunca hierba verde. Usa un while.

    Esta misión mueve al dron BIT-8 por un campo de cultivo: juégala en PHPlay para ver tu código animado.

    Pistas
    • Dentro del bucle: cosecha si se puede y muévete.
    • Si solo te mueves al NORTE, repites siempre la misma columna. Recorre todo el campo: por ejemplo, NORTE hasta completar la columna y luego ESTE.
    • Truco: un contador de pasos y %: if ($pasos % 3 == 0) mover(ESTE); else mover(NORTE);
    Ver solución
    <?php
    $pasos = 0;
    while (true) {
        if (puede_cosechar()) {
            cosechar();
        }
        $pasos++;
        if ($pasos % 3 == 0) {
            mover(ESTE);
        } else {
            mover(NORTE);
        }
    }
    

    Misión del dron 6. El tablero de árboles

    Los árboles crecen despacio si tienen otro árbol al lado. Mara quiere un bosquecillo sano en su campo de 4x4.

    Planta un ÁRBOL en cada casilla donde ($x + $y) % 2 == 0 (8 árboles en total), sin que ningún árbol quede pegado a otro.

    Esta misión mueve al dron BIT-8 por un campo de cultivo: juégala en PHPlay para ver tu código animado.

    Pistas
    • Recorre el campo con dos bucles for usando $x y $y como contadores.
    • Dentro: if (($x + $y) % 2 == 0) { plantar(ARBOL); } antes de mover(ESTE);.
    Ver solución
    <?php
    for ($y = 0; $y < 4; $y++) {
        for ($x = 0; $x < 4; $x++) {
            if (($x + $y) % 2 == 0) {
                plantar(ARBOL);
            }
            mover(ESTE);
        }
        mover(NORTE);
    }
    

    Chuleta: lo esencial

    • while (cond) { }: comprueba antes de cada vuelta (puede no ejecutarse nunca).
    • do { } while (cond);: se ejecuta al menos una vez.
    • for ($i = 0; $i < $n; $i++) { }: inicialización; condición; actualización.
    • Bucle infinito: la condición nunca llega a ser falsa. ¿Qué la cambia?
    • break sale del bucle; continue salta a la siguiente vuelta; break 2 sale de dos niveles.
    • Anidados: el interior se ejecuta completo por cada vuelta del exterior (n × m veces).
    • $i % 2 == 0 → par. ($x + $y) % 2 == 0 → tablero de ajedrez.
    • BIT-8: while (true) hasta agotar la batería; moverse tam() veces vuelve al punto de partida.