Cómo enseñar a superar dificultades y al mismo tiempo escribir ciclos.

A pesar de que hablaremos de uno de los temas básicos, este artículo está escrito para profesionales con experiencia. El objetivo es mostrar qué conceptos erróneos tienen los principiantes en programación. Para los desarrolladores practicantes, estos problemas hace tiempo que se resolvieron, se olvidaron o no se notaron en absoluto. El artículo puede resultarle útil si de repente necesita ayudar a alguien con este tema. El artículo establece paralelismos con material de varios libros sobre programación de Schildt, Stroustrup y Okulov.

Se eligió el tema de los ciclos porque muchas personas quedan excluidas de él cuando dominan la programación.

Esta técnica está diseñada para estudiantes débiles. Como regla general, las personas fuertes no se quedan estancadas en este tema y no es necesario idear técnicas especiales para ellas. El objetivo secundario del artículo es trasladar esta técnica de la clase “funciona para todos los estudiantes, pero solo un maestro” a la clase “funciona para todos los estudiantes, todos los maestros”. No pretendo una originalidad absoluta. Si ya está utilizando una metodología similar para enseñar este tema, escriba en qué se diferencia su versión. Si decides usarlo, cuéntanos cómo te fue. Si se describe una técnica similar en un libro, escriba el nombre.


Trabajé esta técnica durante 4 años, estudiando individualmente con alumnos de diferentes niveles de formación. En total son unos cincuenta alumnos y dos mil horas de clases. Al principio, los estudiantes siempre se quedaban estancados en este tema y se marchaban. Después de cada alumno, se ajustó la metodología y los materiales. Durante el año pasado, los estudiantes ya no se quedaron estancados en este tema, así que decidí compartir mis hallazgos.

¿Por qué tantas cartas? ¡Los ciclos son tan elementales!

Como escribí anteriormente, tanto para los desarrolladores practicantes como para los estudiantes fuertes, se puede subestimar la complejidad del concepto de bucles. Por ejemplo, puedes dar una conferencia larga, ver cabezas asintiendo y ojos inteligentes. Pero al intentar solucionar cualquier problema, comienza el estupor y problemas inexplicables. Después de la conferencia, los estudiantes probablemente sólo tuvieron una comprensión parcial. La situación se ve agravada por el hecho de que los propios estudiantes no pueden expresar cuál es exactamente su engaño.
Un día me di cuenta de que los estudiantes percibían mis ejemplos como jeroglíficos. Es decir, como fragmentos de texto indivisibles a los que hay que añadir alguna letra “mágica” y funcionará.
A veces noté que los estudiantes piensan que para resolver un problema específico es necesario algo más un diseño que aún no he cubierto. Aunque la solución requirió sólo una ligera modificación del ejemplo.

Entonces se me ocurrió la idea de que la atención no debería estar en la sintaxis de las expresiones, sino en la idea de refactorizar código repetitivo mediante bucles. Una vez que los estudiantes dominen esta idea, cualquier sintaxis se puede mejorar con un poco de práctica.

¿A quién y por qué enseño?

Como no hay exámenes de ingreso, las clases pueden incluir tanto a estudiantes fuertes como a estudiantes muy débiles. Puedes leer más sobre mis alumnos en el artículo. Retrato de estudiantes del curso nocturno
Me esforcé por garantizar que todos los que quieran aprender a programar puedan aprenderlo.
Mis clases se realizan de forma individual y el alumno paga su propio dinero por cada una. Parecería que los estudiantes optimizarán costes y exigirán el mínimo. Sin embargo, las personas acuden a clases presenciales con un profesor en vivo no por el conocimiento en sí, sino por la confianza de lo aprendido, por una sensación de progreso y por la aprobación del experto (profesor). Si los estudiantes no sienten progreso en su aprendizaje, se irán. En general, las clases se pueden estructurar de manera que los estudiantes sientan que progresan al aumentar el número de estructuras familiares. Es decir, primero estudiamos mientras en detalle, luego estudiamos durante, luego hacemos mientras, y ahora tenemos listo un curso de mil una noches, en el que solo se estudian ciclos durante dos meses, y al final - un alumno que escribió una biblioteca estándar bajo dictado. Sin embargo, para resolver problemas prácticos no sólo se necesita conocimiento del material, sino también independencia en su aplicación y en la búsqueda de nueva información. Por tanto, para los cursos presenciales, creo que el principio correcto es enseñar lo mínimo y fomentar el estudio independiente de matices y temas relacionados. En el tema de los bucles, considero que la construcción while es la mínima. Puedes entender el principio a partir de ello. Conociendo el principio, podrás dominar tanto el "for" como el "do- while" por ti mismo.

Para que los estudiantes débiles logren el dominio del material, no basta con describir la sintaxis. Es necesario dar tareas más simples pero variadas y describir ejemplos con más detalle. En última instancia, la velocidad de desarrollo está limitada por la capacidad del estudiante para transformar expresiones y buscar patrones. Para los estudiantes inteligentes, la mayoría de las tareas serán aburridas. Al estudiar con ellos, no tienes que insistir en resolver el 100% de los problemas. Mi material se puede ver en mi github. Es cierto que el repositorio se parece más al grimorio de un brujo: nadie más que yo entenderá dónde está y si no pasas la prueba, puedes volverte loco.

La metodología está orientada a la práctica.

La teoría se explica utilizando el ejemplo de la resolución de un problema. En una clase de fundamentos de programación donde se enseñan ramas y bucles, simplemente no es posible dar una conferencia útil sobre un tema durante una hora entera. 15-20 minutos son suficientes para explicar el concepto. Las principales dificultades surgen a la hora de realizar tareas prácticas.
Los profesores principiantes pueden recitar operadores, ramas, bucles y matrices en una sola conferencia. Pero sus alumnos se enfrentarán al problema de asimilar esta información.
Es necesario no sólo contar el material, sino también asegurarse de que los oyentes lo comprendan.

El hecho de dominar un tema está determinado por cómo el alumno afronta el trabajo autónomo.
Si un estudiante logró resolver un problema sobre un tema sin la ayuda de un profesor, entonces domina el tema. Para garantizar la autoevaluación, cada tarea se describe en una tabla con escenarios de prueba. Las tareas tienen un orden claro. No se recomienda saltarse tareas. Si la tarea actual es demasiado difícil, pasar a la siguiente es inútil. Es aún más complicado. Para que el alumno pueda dominar la compleja tarea actual, se le explican varias técnicas utilizando el ejemplo del primer problema. En realidad, todo el contenido del tema se reduce a técnicas para superar las dificultades. Los ciclos son más un efecto secundario.

La primera tarea es siempre un ejemplo. El segundo difiere ligeramente y se realiza "independientemente" inmediatamente después del primero bajo la supervisión de un profesor. Todas las tareas posteriores tienen como objetivo prestar atención a varias pequeñas cosas que pueden provocar conceptos erróneos.

La explicación del ejemplo es un diálogo en el que el estudiante necesita recurrir a la propagación y la validación cruzada para asegurarse de que domina una parte del material.

Seré banal y diré que el primer ejemplo sobre el tema es muy importante. Si tiene el material para un trabajo independiente extenso, las omisiones del primer ejemplo pueden corregirse. Si no hay nada más además del ejemplo, lo más probable es que el estudiante no domine el tema.

¿Mientras o para?

Uno de los temas controvertidos es la elección de la construcción del ejemplo: mientras o para. Una vez, un desarrollador amigo mío sin experiencia docente pasó una hora convenciéndome de que el bucle for era el más fácil de entender. Los argumentos se redujeron a "todo lo que contiene está claro y está dispuesto en su lugar". Sin embargo, la causa fundamental de las dificultades para los verdaderos principiantes es la idea del ciclo en sí, y no su escritura. Si una persona no comprende esta idea, tendrá dificultades con la sintaxis. Tan pronto como la idea se hace realidad, los problemas de diseño del código desaparecen por sí solos.

En mis materiales, el tema de los bucles sigue el tema de la ramificación. La similitud externa de if y while nos permite establecer una analogía directa: "cuando la condición en el encabezado es verdadera, entonces se ejecuta el cuerpo". La única peculiaridad del ciclo es que el cuerpo se ejecuta muchas veces.

Mi segundo argumento es que while requiere menos formato que for. Menos formato significa menos errores estúpidos en los que faltan comas y paréntesis. Los principiantes aún no han desarrollado suficiente atención y meticulosidad para evitar automáticamente errores de sintaxis.
El tercer argumento se explica en muchos buenos libros como el primer argumento.

Si el estudiante puede transformar expresiones fácilmente, entonces puede hablar de for de pasada. Luego el alumno elegirá lo que más le guste. Si las transformaciones causan dificultades, es mejor no distraer la atención. Deje que el estudiante primero resuelva todo usando while. Una vez que haya dominado el tema de los bucles, puede reescribir las soluciones para practicar la conversión de while a for.
Los bucles de poscondición son una bestia bastante rara. No le dedico ningún tiempo en absoluto. Si un estudiante domina las ideas de identificar patrones y transformar expresiones, puede resolverlo sin mi ayuda.

Al mostrar el primer ejemplo a estudiantes fuertes, llamo la atención sobre el hecho de que en el primer ejemplo es importante registrar no solo la solución, sino también toda la cadena de acciones que llevaron al resultado. Los estudiantes perezosos pueden descuidar la escritura y copiar sólo el algoritmo final. Necesitan estar convencidos de que algún día se les presentará una tarea difícil. Para resolverlo, deberá seguir los pasos como en este ejemplo. Por eso es importante registrar todas las etapas. En los siguientes problemas será posible dejar sólo la versión final de la solución.

La idea principal de la automatización es que confiamos a una computadora la tarea de realizar el trabajo rutinario de una persona. Una de las técnicas básicas es escribir bucles. Se utiliza cuando se escriben varias acciones repetidas idénticas en un programa seguidas.

Explícito es mejor que implícito

Puede parecer una buena idea mostrar la misma frase varias veces en la primera tarea de bucle. Por ejemplo:

¡Hurra, funciona!
¡Hurra, funciona!
¡Hurra, funciona!
¡Hurra, funciona!
¡Hurra, funciona!
¡Hurra, funciona!
¡Hurra, funciona!
¡Hurra, funciona!

Esta opción es mala porque el valor del contador no es visible en la salida. Este es un problema para principiantes. No la subestimes. Al principio, esta tarea era la primera y la tarea de derivar una serie de números en orden ascendente era la segunda. Fue necesario introducir términos adicionales “ciclo N veces” y “ciclo de A a B”, que son esencialmente lo mismo. Para no crear entidades innecesarias, decidí mostrar solo un ejemplo con el resultado de una serie de números. Pocas personas logran aprender a sostener un contador en su cabeza y modelar el comportamiento de un programa en su cabeza sin preparación. Algunos estudiantes encuentran por primera vez modelos mentales sobre el tema de los ciclos.
Después de un poco de práctica, me doy la tarea de repetir el mismo texto para resolverlo de forma independiente. Si das primero un contador visible y luego uno invisible, los estudiantes tendrán menos problemas. A veces la sugerencia “no escribas el contador en la pantalla” es suficiente.

¿Cómo lo explican los demás?

En la mayoría de los materiales educativos en Internet, la sintaxis del ciclo se proporciona como parte de una “conferencia”. Por ejemplo, en desarrollador.mozilla.org (actualmente), se describen varias otras construcciones junto con el bucle while. En este caso, sólo los diseños en sí se presentan en forma de plantillas. El resultado de su lanzamiento se describe con palabras, pero no hay ilustraciones. En mi opinión, tal presentación del tema multiplica por cero la utilidad de dichos materiales. El estudiante puede reescribir el código y ejecutarlo él mismo, pero aún necesita un estándar para comparar. ¿Cómo se puede entender que un ejemplo se ha reescrito correctamente si no hay nada con qué comparar el resultado?
Cuando sólo se da una plantilla, sin un ejemplo, se vuelve aún más difícil para el estudiante. ¿Cómo entender que los fragmentos de código están colocados correctamente en la plantilla? Puedes intentar escribir de alguna maneray luego ejecutar. Pero si no existe un estándar para comparar el resultado, el lanzamiento tampoco ayudará.

En el curso de C++ sobre Intuitivo, la sintaxis del bucle está oculta en la tercera página de la Conferencia 4 sobre el tema "operadores". Al explicar la sintaxis de los bucles, se pone especial énfasis en el término "operador". El término se presenta como un conjunto de hechos como “símbolo; esto es una declaración", "{} es una declaración compuesta", "el cuerpo del bucle debe ser una declaración". No me gusta este enfoque porque parece ocultar relaciones importantes detrás de un término. Los desarrolladores de compiladores necesitan analizar el código fuente de un programa en términos de este nivel para implementar la especificación del lenguaje, pero no los estudiantes como primera aproximación. Los recién llegados a la programación rara vez son lo suficientemente meticulosos como para prestar tanta atención a los términos. Es raro que una persona recuerde y comprenda palabras nuevas a la primera. Casi nadie puede aplicar correctamente un término que acaba de aprender. Por lo tanto, los estudiantes reciben muchos errores como "Escribí while(a<7);{, pero el programa no funciona".
En mi opinión, al principio es mejor dar la sintaxis de la construcción inmediatamente entre paréntesis. La opción sin paréntesis solo se debe explicar si el estudiante tiene una pregunta específica: “por qué no hay paréntesis y funciona”.

En el libro de Okulov de 2012, “Fundamentos de programación”, una introducción a los bucles comienza con el patrón for, luego ofrece recomendaciones para su uso y luego pasa inmediatamente a la sección experimental de la lección. Entiendo que el libro fue escrito para esa minoría de estudiantes muy capaces que rara vez vienen a mis clases.

En los libros populares, siempre se escribe el resultado de los fragmentos de código. Por ejemplo, la edición de 8 de "Java 2015. The Complete Guide" de Shildt. Primero, se proporciona una plantilla, luego un programa de ejemplo e inmediatamente después, el resultado de la ejecución.

Como ejemplo, considere un bucle while que hace lo contrario.
cuenta regresiva comenzando desde 10, y se muestran exactamente 10 líneas de “compases”:

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

Una vez ejecutado, este programa genera diez "ciclos" de la siguiente manera:
такт 10
такт 9
такт 8
такт 7
такт 6
такт 5
такт 4
такт 3
такт 2
такт 1

El enfoque de describir una plantilla, un programa de ejemplo y el resultado del programa también se utiliza en el libro "Javascript para niños" y en el curso de js en w3schools.com. El formato de la página web incluso permite que este ejemplo sea interactivo.

El libro de Stroustrup de 2016 Principios y práctica del uso de C++ fue aún más lejos. El primer paso es explicar qué resultado se debe obtener, y luego se muestra el texto del programa. Además, no toman como ejemplo simplemente un programa aleatorio, sino que ofrecen un recorrido por la historia. Esto ayuda a llamar la atención: “Mira, esto no es sólo un texto inútil. Ves algo significativo".

Como ejemplo de iteración, considere el primer programa ejecutado en una máquina de programa almacenado (EDSAC). Fue escrito por David Wheeler en el Laboratorio de Computación de la Universidad de Cambridge, Inglaterra, el 6 de mayo de 1949. Este programa calcula e imprime una lista simple de cuadrados.
0 0
1 1
2 4
3 9
4 16
...
98 9604
99 9801

Aquí, cada línea contiene un número seguido de un carácter de tabulación ('t') y el cuadrado de ese número. La versión C++ de este programa se ve así:

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

Curiosamente, el patrón de sintaxis no se describe en este libro. Stroustrup en el manual del instructor (traducción) destaca que respeta la inteligencia de sus alumnos. Quizás la capacidad de identificar un patrón en varios ejemplos se considere una manifestación de dicha inteligencia.

como me explico

El enfoque de Stroustrup: describir el resultado, luego resolver el problema y luego un análisis independiente por parte del estudiante, parece el más reflexivo. Por lo tanto, decidí tomarlo como base, pero contarlo usando un ejemplo menos histórico: la tarea de derivar un "índice". Forma un ancla reconocible para que luego puedas decir “recuerda la tarea sobre el índice” y para que los estudiantes recuerden exactamente esto. En mi ejemplo, intenté evitar dos de los conceptos erróneos más comunes. A continuación escribiré sobre ellos con más detalle.

En esta tarea se nos presentan técnicas para resolver problemas complejos. La decisión inicial debe ser primitiva y sencilla. Bueno, entonces puedes pensar en cómo mejorar esta solución.
Введение
Глава 1
Глава 2
Глава 3
Глава 4
Глава 5
Глава 6
Глава 7
Заключение

Según mis observaciones, el enfoque “plantilla-ejemplo-resultado” en varias combinaciones todavía lleva al hecho de que los estudiantes perciben el ciclo como un jeroglífico. Esto se manifestó en el hecho de que no entendían por qué había una condición para escribir allí, cómo elegir entre i++ e i, y otras cosas aparentemente obvias. Para evitar estos conceptos erróneos, el enfoque al hablar de ciclos debe enfatizar el significado de repetir acciones idénticas y solo entonces formalizarlas usando una estructura. Por lo tanto, antes de dar la sintaxis del bucle, es necesario resolver el problema de frente. Una solución primitiva al problema de la tabla de contenido se ve así:

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("Заключение");

¿Cómo puede ser mejorado?
Reemplace las acciones monótonas con un ciclo.
¿Qué acciones se repiten seguidas sin cambios?
No hay ninguno en este fragmento. Sin embargo, los comandos para mostrar la palabra “Capítulo” con un número son muy similares entre sí.
Por tanto, el siguiente paso es encontrar la diferencia entre los fragmentos. Sólo en esta tarea todo es obvio, entonces no se repetirán comandos individuales, sino bloques de código de 5 líneas o más. Tendrá que buscar no sólo en la lista de comandos, sino también en construcciones de bifurcación o bucle.
En el ejemplo, la diferencia entre los comandos está en el número después de la palabra "Capítulo".
Una vez que se encuentra la diferencia, es necesario comprender el patrón de cambio. ¿El fragmento diferente es el número? ¿Está aumentando o disminuyendo constantemente? ¿Cómo cambia el valor de un número entre dos equipos uno al lado del otro?
En el ejemplo, el número después de la palabra "Capítulo" aumenta en incrementos de 1. Se encuentra la diferencia, se revela el patrón. Ahora puedes reemplazar el fragmento diferente con una variable.
Debe declarar dicha variable antes del primero de los fragmentos repetidos. Esta variable suele denominarse I o j o algo más detallado. Su valor inicial debe ser igual al primer valor mostrado en pantalla. En el ejemplo, el primer valor es 1.
¿Qué valor inicial se debe tomar para mostrar la serie de números “100, 101, 102, 103, 104, 105”?
El primer número de esta serie es 100.
Después de cada comando de salida, debe aumentar el valor de esta variable en 1. Esta unidad es el paso de cambio.
¿Qué paso habrá en la serie de números “100, 102, 104, 106”?
Paso 2 en esta fila.
Después de reemplazar el fragmento diferente con una variable, el código se verá así:

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("Заключение");

Después de aplicar la técnica de “expresar el patrón de una variable” en el código, se obtienen varios grupos de acciones idénticas que van seguidas. Ahora las acciones repetidas se pueden reemplazar con un ciclo.

La secuencia para resolver un problema en el que es necesario utilizar bucles consta de los siguientes pasos:

  1. Resuelva “de frente” con muchos comandos separados
  2. encontrar un patrón
  3. Expresar el patrón de una variable.
  4. Diseño como ciclo

A continuación, se introducen nuevos términos para que el alumno no se encuentre en la situación de “lo entiendo todo, pero no puedo decirlo”:
— un contador es siempre una variable que se necesita para rastrear el número de pasos en un bucle. Normalmente, un número entero que se compara con la restricción.
— paso de contador: descripción del patrón de cambios de contador.
- restricción: un número o variable con el que se compara el contador para que el algoritmo sea definitivo. El valor del contador cambia para acercarse al límite.
— cuerpo del bucle: un conjunto de comandos que se repetirán. Cuando dicen "el comando está escrito dentro de un bucle", se refieren al cuerpo.
— iteración del bucle: ejecución única del cuerpo del bucle.
— condición de bucle: expresión lógica que determina si se ejecutará otra iteración. (Aquí puede haber confusión con las estructuras ramificadas)
Es necesario estar preparado para el hecho de que al principio los estudiantes utilizarán términos para otros fines. Esto se aplica tanto a los fuertes como a los débiles. Establecer un lenguaje común es un arte. Ahora escribiré brevemente: debes configurar la tarea "resaltar el fragmento de código con <término>" y usar estos términos correctamente en la conversación.
Después de la transformación con un bucle, se obtiene el fragmento:

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

El principal error

Un error común entre los estudiantes es que colocan acciones dentro de un bucle que solo debe realizarse una vez. Por ejemplo así:

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

Los estudiantes se topan con este problema todo el tiempo, tanto al principio como en problemas más complejos.
Sugerencia clave en este caso:

¿Cuántas veces debes repetir el comando: una o muchas veces?

Los comandos para imprimir las palabras "Introducción" y "Conclusión" y declarar e inicializar la variable i no son como otras acciones repetitivas. Se ejecutan sólo una vez, lo que significa que deben escribirse fuera del cuerpo del bucle.

Las tres etapas de la solución deben permanecer en el código para que pueda consultarlas más adelante en caso de dificultades. Basta comentar las dos primeras opciones para que no interfieran.
Se debe llamar la atención del estudiante sobre los siguientes hechos:
— En una condición de bucle, normalmente se comparan un contador y un límite. El contador puede cambiar en el cuerpo del bucle, pero el límite no. Para romper esta regla, es necesario formular razones de peso.
— Los comandos para mostrar las palabras "Introducción" y "Conclusión" se encuentran fuera del cuerpo del bucle. Necesitamos realizarlos 1 vez. "Introducción" - antes de repetir las acciones, "Conclusión" - después.
En el proceso de consolidar este tema, dominar los siguientes y afrontar las dificultades, es útil incluso para los estudiantes más fuertes hacerse la pregunta: “¿Cuántas veces es necesario realizar esta acción? ¿Uno o muchos?

Desarrollo de habilidades adicionales.

En el proceso de estudio de los ciclos, los estudiantes también desarrollan la habilidad de diagnosticar y resolver problemas. Para realizar el diagnóstico, el estudiante debe presentar el resultado deseado y compararlo con el resultado real. Las acciones correctivas dependen de la diferencia entre ellas.
Dado que los estudiantes en esta etapa todavía tienen poca idea del resultado "deseado", pueden concentrarse en los datos de la prueba. Por regla general, en esta fase nadie entiende todavía qué puede salir mal y cómo solucionarlo. Por eso, escribo en un cuaderno una descripción de problemas típicos y varias formas de solucionarlos. Elegir el más adecuado es tarea del propio alumno.
Se necesita un registro para preguntar “¿sucedió lo que se esperaba?”, “¿Cuál de estas situaciones sucedió ahora?”, “¿La solución aplicada ayudó?”

  1. El número de acciones es 1 menos o más de lo esperado. Soluciones:
    — aumentar el valor inicial del contador en 1.
    — reemplace el operador de comparación estricto (< o >) por uno no estricto (<= o >=).
    — cambie el valor límite a 1.
  2. Las acciones en bucle se realizan sin parar, sin cesar. Soluciones:
    — agregue un comando de cambio de contador si falta.
    — fijar el comando de cambio de contador para que su valor se acerque al límite.
    — elimina el comando de cambio de restricción si está en el cuerpo del bucle.
  3. El número de acciones en un bucle es más de 1 menos o más de lo esperado. La acción del bucle no se ejecutó ni una sola vez. Primero debe averiguar los valores reales de las variables justo antes de que comience el ciclo. Soluciones:
    — cambiar el valor inicial de la restricción
    — cambiar el valor inicial del contador

El problema 3 generalmente implica usar la variable incorrecta o no restablecer el contador a cero.

Después de esta explicación, es posible que el estudiante todavía tenga varios conceptos erróneos sobre cómo funcionan los bucles.
Para disipar los más comunes, te doy las siguientes tareas:

  1. En el que el usuario introduce el límite, el valor inicial del contador o el paso del contador.
  2. En el cual se debe utilizar el valor del contador en alguna expresión aritmética. Es recomendable utilizar un contador en la expresión radical o en el denominador para que la diferencia sea no lineal.
  3. En el que el valor del contador no se muestra en la pantalla mientras se ejecuta el bucle. Por ejemplo, mostrar la cantidad necesaria de fragmentos de texto idénticos o dibujar una figura con gráficos de tortugas.
  4. En el que es necesario realizar primero algunas acciones repetitivas y luego otras.
  5. En el que necesitas realizar otras acciones antes y después de repetir.

Para cada tarea es necesario proporcionar datos de prueba y el resultado esperado.

Para comprender qué tan rápido puede avanzar, debe leer las condiciones de estos problemas y preguntar: "¿En qué se diferencian del ejemplo?", "¿Qué se debe cambiar en el ejemplo para resolverlos?". Si el alumno responde de manera significativa, déjele que resuelva al menos una en clase y el resto en casa solo. Si la solución tiene éxito, entonces podemos comenzar a explicar las condiciones dentro de los bucles.
Si tienes problemas para resolver problemas por tu cuenta, debes resolver todo en clase. Para evitar que la solución del problema recuerde a dibujar un búho, recomiendo primero resolver el problema de una manera no universal. Es decir, para que la solución pase la primera prueba y no utilice la construcción del bucle. Bueno, entonces aplique transformaciones para lograr la universalidad de la solución.

Bucles y ramas

En mi opinión, es útil tratar el tema “ciclos dentro de ramas” por separado. Para que luego puedas ver la diferencia entre verificar una condición varias veces y verificarla una vez.
Las tareas de consolidación consistirán en generar números de A a B, que ingresa el usuario:
- siempre en orden ascendente.
- ascendente o descendente según los valores de A y B.

El tema de "ramificación dentro de bucles" debe avanzarse sólo después de que el estudiante haya dominado las técnicas: "reemplazar un patrón con una variable" y "reemplazar acciones repetitivas con un ciclo".
La razón principal para usar ramas dentro de bucles son las anomalías en el patrón. En el medio se rompe dependiendo de los datos iniciales.
Para aquellos estudiantes que sean capaces de buscar una solución combinando técnicas simples, basta con decir "las ramificaciones se pueden escribir dentro de bucles" y dar el problema "por ejemplo" completamente para que lo resuelvan de forma independiente.
Tarea de ejemplo:

El usuario ingresa el número X. Muestra los números del 0 al 9 en una columna y coloca un signo '+' frente al número que es igual a X.

Si se ingresó 00+
1
2
3
4
5
6
7
8
9

Si se ingresó 60
1
2
3
4
5
6+
7
8
9

Si se ingresó 90
1
2
3
4
5
6
7
8
9+

Si se ingresó 7770
1
2
3
4
5
6
7
8
9

Si una breve explicación no es suficiente para escribir con un bucle, entonces es necesario lograr una solución universal al mismo problema sin un bucle.
Obtendrá una de dos opciones:
Deseado

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);
}

Posible

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+");
}

Les doy una tarea similar por adelantado, mientras estudio el tema de la ramificación.
Si al estudiante se le ocurre una opción "posible", entonces debe decirle que puede haber muchas soluciones para el mismo problema. Sin embargo, se diferencian en su resistencia a los cambios de requisitos. Haga la pregunta: "¿Cuántos lugares del código deberían corregirse si tuviera que agregar otro número?" En la versión “posible”, deberá agregar una sucursal más y agregar un nuevo número en otros 10 lugares. En el "deseado" basta con agregar una sola rama.
Configure la tarea para reproducir la opción "deseada", luego busque un patrón en el código, realice un reemplazo de variable y escriba un bucle.
Si tiene una idea sobre cómo resolver este problema sin bucle de alguna otra manera, escriba en los comentarios.

Bucles dentro de bucles

En este tema es necesario prestar atención a lo siguiente:
— los contadores para los bucles interior y exterior deben ser variables diferentes.
— el contador del bucle interior debe restablecerse muchas veces (es decir, en el cuerpo del bucle exterior).
— en las tareas de producción de texto, no se puede escribir primero una letra en varias líneas y luego la segunda. Primero debes imprimir todas las letras de la primera línea, luego todas las letras de la segunda, y así sucesivamente.

Lo mejor es empezar explicando el tema de los bucles dentro de bucles explicando la importancia de poner el contador a cero.
Tarea de ejemplo:

El usuario ingresa dos números: R y T. Imprime dos líneas de caracteres "#". La primera línea debe contener caracteres R. La segunda línea contiene piezas T. Si algún número es negativo, muestra un mensaje de error.

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

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

R=-1, T=6El valor R no debe ser negativo.

R=6, T=-2El valor T no debe ser negativo.

Evidentemente, este problema también tiene al menos dos soluciones.
Deseado

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;
}

Posible #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;
}

La diferencia es que en la "posible" solución, se usó una segunda variable para generar la segunda línea. Debes insistir en usar la misma variable para ambos bucles. Esta limitación puede justificarse por el hecho de que una solución con un contador para dos ciclos sería un ejemplo del término "reinicio del contador". Comprender este término es necesario para resolver los siguientes problemas. Como compromiso, puede conservar ambas soluciones al problema.

Un problema típico al usar una variable de contador para dos bucles se ve así:
R=5, T=11#####
# # # # # #

El número de caracteres en la segunda línea no corresponde al valor de T. Si necesita ayuda con este problema, debe consultar las notas sobre problemas típicos con los bucles. Este es el síntoma número 3. Se diagnostica si agrega una salida de valor de contador inmediatamente antes del segundo ciclo. Corregido reiniciando. Pero es mejor no contarlo de inmediato. El estudiante debe intentar formular al menos una hipótesis.

Por supuesto, existe otra solución. Pero nunca lo he visto entre los estudiantes. En la etapa de estudio de los ciclos, la historia al respecto distraerá la atención. Puede volver a él más tarde cuando aprenda sobre funciones de cadena.
Posible #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));

Siguiente tarea requerida:

Muestra los números del 0 al 9. Cada número debe estar en su propia línea. El número de dígitos en una línea (W) se ingresa desde el teclado.

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

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

Si un estudiante ha dominado la técnica de reemplazar una variable, lo hará con bastante rapidez. Un posible problema nuevamente será restablecer la variable. Si no puedes manejar la transformación, significa que tenías prisa y necesitas resolver problemas más simples.

Gracias por su atención. Dale me gusta y suscríbete al canal.

PD: Si encuentra errores tipográficos o en el texto, hágamelo saber. Esto se puede hacer seleccionando parte del texto y presionando “⌘ + Enter” en Mac, y “Ctrl / Enter” en teclados clásicos, o mediante mensajes privados. Si estas opciones no están disponibles, escriba sobre los errores en los comentarios. ¡Gracias!

Solo los usuarios registrados pueden participar en la encuesta. Registrarsepor favor

Encuesta para lectores sin karma

  • 20,0%Doy clases profesionalmente, +12

  • 10,0%Doy clases profesionalmente, -11

  • 70,0%yo no enseño, +17

  • 0,0%yo no enseño, -10

  • 0,0%Otro (0

10 usuarios votaron. 5 usuarios se abstuvieron.

Fuente: habr.com

Añadir un comentario