Registrarse

[C#] Aprende a programar desde 0 de la mano de Xiros

Xiros

¡Pokémon Omega con actualización del 30/8!
Miembro de honor
¡Buenas a todos! Viendo el creciente interés de muchos en la comunidad por aprender a programar, recordé que hace unos años preparé un material de programación para enseñar a programar a un amigo. No lo completé, puesto a qué algunas "clases" no las documenté, pero tengo bastante material escrito.

El mismo está orientado para aprender a programar desde 0, y si bien se usa C#, el objetivo del mismo es enseñar los conceptos esenciales de programación y aprender a razonar como programador, que seguro les servirán para luego poder trabajar y aprender cualquier otro lenguaje.

El material va a estar organizado en capítulos que iré publicando en el correr de los días, y al final de cada uno de ellos encontrarán una serie de ejercicios. Si los hacen, les pido que si publican sus resultados lo hagan en un spoiler, y los invito a realizar todas las preguntas que quieran si tienen dudas.

Ni que hablar que tener conceptos básicos de programación servirá mucho en la creación de fangames, sin importar si son usando decomp, rpg Maker, unity o lo que sea. Saber de programación facilitará el scripting y la creación de nuevas mecánicas.

En la parte que publico hoy aún no veremos código de C#, pero son conceptos extremadamente importantes que está bueno tener claros antes de empezar a escribir código real.
Tal vez le parezca extraño empezar un tutorial de programación sin escribir código ni viendo palabras en inglés, pero confíen en mí que les servirá para sentar unas buenas bases y evitar frustraciones futuras.

Introducción

Para poder realizar un software, es necesario escribir el código del mismo. Dicho código debe estar escrito en un determinado lenguaje de programación, el cual luego es transformado a un código que la computadora puede interpretar.

En la actualidad, existen infinidades de lenguajes de programación, cada uno con sus particularidades. En general, algunos son más aptos para realizar determinados tipos de software que otros, y cada uno tiene su propia curva de aprendizaje. Si bien en este curso utilizaremos el lenguaje de programación C# de base para la realización de ejercicios, se buscará que los conocimientos dictados sirvan para aprender a programar en general y no únicamente para ese lenguaje.

Pseudocódigo

En este capítulo introductorio, dejaremos de lado todos los lenguajes de programación y utilizaremos un “falso lenguaje” que se conoce como pseudocódigo, que simplemente sirve para describir la forma en que se deben hacer y pensar las cosas, pero sin entrar a los detalles de como hacerlas realmente. De esta forma, se podrá empezar a entender la forma en la que se debe pensar y razonar al momento de programar.

Empezando a pensar como programador(a)

Imaginemos que estamos planificando un viaje para ir a Machu Picchu. En una primera instancia, podemos plantear una lista de las cosas que tenemos que hacer para poder cumplirlo. La primer lista podría ser similar a la siguiente:

Código:
Planificar viaje a Machu Picchu
Comprar artículos necesarios
Realizar viaje
Si bien tenemos una primera aproximación de lo que queremos hacer, en realidad los problemas planteados en este caso son bastante más complejos, entonces será necesario dividir los mismos para poder resolverlos. Esto nos lleva a utilizar la estrategia “dividir para conquistar”, que implica dividir a un problema complejo en una serie de problemas de menor complejidad. Al resolver dichos “sub-problemas” y combinar las soluciones, se logra resolver el problema complejo.

Tomemos el ejemplo de realizar el viaje como el problema complejo a resolver. Para hacerlo más simple, consideremos únicamente el día del viaje de ida.

En este caso, imaginé los siguientes sub-problemas, pero otra persona podría identificar otros distintos e incluso otra forma de resolver los mismos problemas.

Código:
Ir al aeropuerto
Hacer check in
Tomar avión
Retirar valijas
Ir al hotel
En nuestro primer “código”, empezamos a explicar el cómo se debe resolver el problema de llegar hacia machu picchu. Cada uno de estos pasos son problemas que nuevamente se pueden volver a subdividir en problemas más simples.

Ir al aeropuerto

Código:
Agarrar pasaporte y valijas
Pedir taxi
Subir valijas en maletero de taxi
Llegar al aeropuerto a las 9 de la mañana
Pagar al taxista
Bajar valijas del maletero
Entrar al aeropuerto
Hacer check in

Código:
Ir al mostrador
Hacer fila
Entregar pasaporte
Si tengo valijas
    Despachar valijas
Retirar tarjeta de embarque
En este caso, podemos ver que despachar valijas únicamente se va a realizar en caso que se tenga valijas, y recién luego de despacharlas se retirará la tarjeta de embarque. En caso de no tener valijas, se procederá únicamente a retirar la tarjeta de embarque.

"Despachar valijas" también es complejo, por lo cual lo podemos seguir subdividiendo.

Despachar valijas

Código:
Mientras tengo valijas
Agarrar valija
Pesar valija
Poner sticker valija
Despacharla
Si hubo sobrepeso
Pagar sobrepeso
En el ejemplo de "despachar valijas", podemos ver la instrucción "mientras". En este caso, mientras tengo valijas, voy ejecutando las siguientes acciones para cada valija. Es decir, si tengo 2 valijas, primero agarro una, la peso, le pongo el sticker y la despacho. Luego vuelvo a arriba a donde se encuentra la instrucción "mientras" y vuelvo a realizar las mismas acciones, pero ahora con la segunda valija. Finalmente, en caso que tenga sobrepeso en alguna de mis valijas, debo pagar el sobrepeso correspondiente.

A su vez, podemos ver como cada vez las instrucciones son más simples, por lo cual llegará un punto en el cual ya no tiene sentido seguirlas subdividiendo, ya que se consideran "problemas resueltos".

Flujo del programa

Secuencia
Las instrucciones del programa se van leyendo en orden de arriba hacia abajo, uno por uno. Esto se puede ver en el siguiente ejemplo de preparar tostadas:
Código:
    Enchufar tostadora
    Agarrar pan de molde
    Poner pan de molde en tostadora
    Poner a tostar el pan
    Quitar de tostadora cuando se encuentra listo
En este caso, se ejecuta todo en orden, lo que tiene sentido, ya que es imposible poner a tostar el pan si todavía no lo agarré.

Decisión
No siempre se desea que se ejecuten todas las instrucciones, si no que en algunos casos tiene más sentido que se ejecuten determinadas instrucciones si se cumple una condición, y otras en caso que no se cumpla.

Por ejemplo:

Código:
Si está lloviendo
    Comprar tortafritas
En otro caso
    Comprar churros
Comer el alimento comprado
Iteración
La iteración se utiliza cuando se desea repetir ciertas instrucciones hasta que se cumpla determinada condición. Existen diversas versiones de iteraciones, entre ellas las principales, "Mientras" y "Repetir X veces".

Mientras

Mientras se ejecuta siempre que se cumpla una condición, cuando la misma ya no se cumple entonces se sale de la instrucción mientras y se continúa ejecutando de forma secuencial. Ejemplo:

Código:
Sacar ropa del lavarropas
Agarrar balde con palillos
Mientras tengo ropa para colgar
    Agarrar prenda
    Agarrar dos palillos
    Colgar prenda
Guardar balde de palillos
Repetir X veces
Se utiliza para ejecutar unas instrucciones una determinada cantidad de veces. Su estructura sería:
Repetir X cantidad de veces

Un ejemplo sería:
Código:
Repetir 20 veces
    Hacer abdominal
Ejercicios
  1. Siguiendo el ejemplo del viaje a Machu Picchu, hacer el pseudocódigo de "Retirar valijas" y de "Ir al hotel".
  2. Utilizando pseudocódigo, describir el proceso de lavar la cocina.
  3. Anotar los pasos necesarios de la corrección de un examen por parte de un profesor.
  4. Describir los pasos del proceso de cambiar una rueda pinchada de un auto.
  5. Anotar los pasos necesarios para la realización de panqueques, considerando que se tiene un preparado en un recipiente y no se sabe con exactitud la cantidad de panqueques que se podrán cocinar.
  6. Un alumno se está preparando para dar una presentación en clase de un programa que realizó, en la cual tiene que presentar unas diapositivas y mostrar una demo del mismo. Para asegurarse que le va a ir bien, decide practicar 20 veces lo que va a hacer. Describir el proceso con pseudocódigo.
  7. Se dispone de la siguiente esquina (ver figura). Se desea cruzar de A a D respetando los semáforos. Para simplificar, considerar que únicamente hay luz verde y roja. Escribir en pseudocódigo los pasos para describir dicho proceso.



Bibliografía
Algunos de los ejemplos y parte del material teórico de un libro "Programación 1" de mi Universidad

Parte 2: Concepto de variables (pendiente)

Parte 3: Pasando lo aprendido a C# (pendiente)

For

Al igual que con while, la sentencia for se puede utilizar para realizar iteraciones. Es decir, para repetir una y otra vez un bloque de código hasta que se cumpla cierta condición. Todo lo que puede ser escrito utilizando for se podría hacer con while.
For básicamente es un tipo especial de while, en el cual se va incrementando/decrementando una variable hasta que cumple determinada condición.

Estructura de for:
Código:
for(variable; condición; cambio de valor de variable){
        Código a ejecutar  
}
La variable es la que se utiliza en el for, y que a medida que va ejecutándose la iteración va a ir cambiando. Se asigna un valor inicial a la misma.
La condición indica hasta cuándo se debe ejecutar el for. Mientras cumpla la condición, se va a ejecutar el mismo.
El “cambio de valor de variable” lo que hace es cambiar el valor de la variable del for cada vez que se terminó de ejecutar el bloque del for. Dicho cambio de variable significa “incrementar” o “decrementar” el valor de la variable. Luego de realizar dicho cambio, se vuelve a evaluar la condición y, en caso que corresponda, se vuelve a ejecutar el bloque con el nuevo valor de la variable.

Para que quede más claro, veamos el siguiente ejemplo:
Código:
for(int i=1; i<11; i++)
{
    Console.WriteLine(i);
}
En este caso la variable es “i”, y se le asigna un valor inicial 1. El for se va a ejecutar siempre que se cumpla la condición que i sea menor que 11. Cada vez que termina de ejecutarse un bloque de for, se realiza lo que sería el cambio de variable. En este caso se hace i++, que es lo mismo que hacer i = i +1. Es decir, a la variable i se le suma uno. Luego de realizarse el cambio de variable, se vuelve a evaluar la condición, y en caso que corresponda, se vuelve a ejecutar el bloque de for, pero ahora con el nuevo valor de la variable, y así sucesivamente hasta que no se cumpla más la condición, que ahí se termina de ejecutar el for.

En este caso, el for anterior se podría haber escrito con while:
Código:
int i = 1;
while(i<11)
{
    Console.WriteLine(i);
    i++; //Que es lo mismo que hacer i=i+1
}
¿Cuándo usar for y cuándo usar while?

En general, while tiene más sentido cuando no se sabe de antemano la cantidad de iteraciones que se van a realizar. Si ya se sabe la cantidad de iteraciones que se van a realizar, entonces un for puede ser más claro y más corto de escribir, ya que queda la declaración, la condición y el incremento en una misma línea.

Además, en lenguajes como C#, si se declara la variable (por ejemplo i) en el for, la misma solo puede ser usada dentro del for, y no afuera del mismo. Esto sirve para los casos en los que no interesaría que la misma fuese usada fuera de dicho bloque.

Ejercicios

  1. Mostrar al usuario el cuadrado de los números del 1 al 10. Es decir, el resultado de hacer 1 al cuadrado, 2 al cuadrado, y así sucesivamente.
Ej. 1, 4, 9…
  1. Mostrar al usuario la suma final de los números del 1 al 10, y la multiplicación de los números pares.
  2. Pedir al usuario que ingrese un número mayor o igual a 0, y mostrar al usuario todos los números desde 0 hasta dicho número.
Ej. Si el usuario ingresa 5, se le debe mostrar 0, 1, 2, 3, 4, 5
  1. Pedir al usuario que ingrese un número desde y un número hasta (que debe ser mayor o igual a desde). Mostrar al usuario todos los números pares que se encuentran entre desde y hasta, incluyendo los bordes si corresponde.
Ej. Si el usuario ingresa 5 y 10, se muestra: 6, 8, 10.
  1. Pedir al usuario un número mayor o igual a 0. Hacer una "cuenta regresiva" hasta llegar a 0 desde dicho número.
Ej. Si el usuario ingresa 5, se muestra: 5, 4, 3, 2, 1, 0
  1. Pedir al usuario que ingrese un número. Mostrar los siguientes 5 números al número ingresado por el usuario.
Ej. Si el usuario ingresa 40, se muestra 41, 42, 43, 44, 45
  1. Se le pide al usuario un número para indicar cuantas cantidades de número se desea recibir. Luego se le pide esa cantidad de veces que seleccione un número, y al final se muestra al usuario el número más grande de ellos.
Ej. Si de cantidad selecciona 5, debe de ingresar 5 números. Si ingresa 4, 12, 8, 3 y 10, se debe mostrar 12, ya que es el número más grande.
  1. Pedir al usuario que ingrese un nombre, y luego la cantidad de veces que desea repetir dicho nombre. Repetir el nombre escrito la cantidad de veces seleccionada.
  2. Hacer de dos formas distintas que se imprima lo siguiente en la consola. En una de ellas solamente solamente se puede ingresar un único Console.Write("*") dentro del for. (Se puede usar Console.WriteLine, etc., siempre y cuando no contengan el asterisco.
********
********
********
********
  1. Hacer que se imprima lo siguiente en la consola. Al igual que el ejercicio anterior, solamente se puede ingresar un único Console.Write("*") dentro del for.
*****
****
***
**
*
  1. Hacer que se imprima lo siguiente en la consola. Al igual que el ejercicio anterior, solamente se puede ingresar un único Console.Write("*") dentro del for.
*
**
***
****
*****
  1. El usuario ingresa la cantidad de filas y cantidad de columnas, y se le muestra los asteriscos formando el rectángulo correspondiente. Por ejemplo, si se ingresan 3 filas y cuatro columnas, el resultado sería:
****
****
****
  1. Calcular Factorial de un número dado por el usuario utilizando for.

Métodos

Un método está compuesto por:
  • Nombre del método: Debe ser completamente descriptivo de lo que hace el método. A modo de ejemplo, un método que sume dos números se podría llamar "Sumar".
  • Parámetros de entrada: Las distintas variables que debe recibir el método para poder ejecutarse. Por ejemplo, en un método de sumar, se podría recibir como variables de entrada los dos números que se desean sumar.
  • Retorno: Es lo que retorna el método. Dicho retorno puede ser el resultado. Por ejemplo, en el método de sumar, se podría devolver el resultado de la suma para poder ser utilizada.

La estructura de los métodos son:
Código:
tipoRetorno NombreMetodo(parametro1, parametro2, parametro3…)
{
}
El ejemplo de la suma podría ser así (por ahora no prestar atención al "public"):
Código:
public int Sumar(int num1, int num2)
{
    return num1 + num2;
}
El tipo de retorno es int, ya que devuelve un entero. Los parámetros de entrada en este caso son enteros.

En caso que un método no devuelva nada, entonces se escribe "void" en el retorno:
Código:
public void MostrarSuma()
{
    int num1  = int.Parse(Console.ReadLine());
    int num2 = int.Parse(Console.ReadLine());
    int suma = Sumar(num1, num2); //Se usa el método sumar mostrado más arriba
    Console.WriteLine(suma);
}
Si un método declara que retorna un elemento, siempre debe devolver un elemento de dicho tipo en todos sus casos de ejecución.



¿Para qué sirve dividir el código en métodos?

  • Permite un código más legible y entendible. Cuando el código es muy grande, si no está dividido en métodos cuesta mucho poder entender el funcionamiento del mismo. Al tener un método que resuelve determinada cosa en particular, si el mismo tiene un nombre descriptivo hace que sea más fácil su entendimiento.
  • Permite utilizar un mismo método en distintas partes del código sin tener que estar reescribiendo las mismas funciones una y otra vez. Por ejemplo, si en 3 lugares distintos de la aplicación se desea calcular el factorial de un número, simplemente se llamaría al método de Factorial mandandole el número del cual se desea calcular. Si no se dividiese en métodos, habría que implementar en 3 lugares distintos el factorial, y donde dicha función luego tenga algún cambio habría que cambiarla en 3 lugares distintos.


Ejercicios:
  1. Hacer un método que reste dos números y retorne el resultado. Desde el Main pedir al usuario dos números, llamar al método de restar y luego mostrar al usuario el resultado recibido. La firma del método debe ser: public static int Restar(int num1, int num2). - Por ahora los métodos los declaramos con "public static".
  2. Transformar el ejercicio de la calculadora para que las distintas operaciones sean de distintos métodos.
  3. Hacer un método que reciba 2 números y devuelva el mayor. Desde el Main pedir al usuario 10 números, y utilizando el método calcular y mostrar cual es el número mayor de todos.
  4. Hacer un método que calcule el factorial de un número. Desde Main calcular el factorial de 5, calcular el factorial de 8, calcular el factorial de los números entre 10 y 15.
  5. Hacer un método que te devuelva un número al azar entre determinado rango (investigar). Obtener un número al azar entre 1 y 50, y pedirle al usuario que adivine dicho número. Sí dice el número correcto se le felicita y termina. Si dice un número más chico o si elige un número más grande se le indica para que vuelva a intentar adivinar hasta que lo adivine.
  6. Hacer un método que diga si dos números son divisibles entre sí.
  7. Hacer un método que diga si un número es perfecto.

Arrays

Un array es una estructura de datos que contiene un grupo de elementos. Dichos elementos son del mismo tipo, de decir, un Array por lo general puede contener un conjunto de números, un conjunto de strings, etc.

Al crear un array, se debe de indicar la cantidad de elementos que puede contener, y esa capacidad máxima no puede cambiar. A modo de ejemplo, si se inicializa un array de int con largo 5, como máximo este podrá tener 5 números. El tamaño del array siempre se debe de fijar al crear el mismo.

Ejemplo de creación de array en C#:

Código:
int[] arrayNumeros = new int[5];
En este caso, se puede ver que es un array de tipo int, que se llama "arrayNumeros", y a su vez tiene un tamaño de 5.

¿Cómo le agrego valores a un array?

Cada elemento de array es colocado en una posición del mismo. Siguiendo con el ejemplo anterior, al "arrayNumeros" tener una capacidad de 5, significa que puedo ingresar un número en la posición 0, en la posición 1, en la 2, 3 o en la 4. Como se puede notar, las posiciones de los array empiezan a contar desde 0, por lo que siempre van de 0 a Largo - 1.

En caso que quiera agregar un elemento en la primera posición, debo hacer:
Código:
arrayNumeros[0] = 3; //Agrego el número 3 a la posición 0
Si quiero agregar en la segunda posición:
Código:
arrayNumeros[1] = 8; //Agrego el número 8 a la posición 1
En el caso que se quiera asignar un elemento a una posición no permitida (en este caso por ejemplo podría ser 5, 6 o cualquier número mayor, al intentar ejecutar dicha línea de código el programa va a dar error (lanza una excepción, lo que veremos más adelante).

Cuando se inicializa un array, se le pone un valor por defecto en cada una de las posiciones. En caso de los int, se le pone por defecto el valor 0 a cada posición. En caso de los string, se le pone null (que significa ausencia de valor). Si se crea un array de bool, se les pone por defecto a todos "false".

¿Cómo puedo obtener un elemento de un array?

Código:
int elementoPosicion0 = arrayNumeros[0];
¿Cómo puedo saber el largo de un array?

Cada array tiene un atributo que se llama "Length", que te dice el largo del mismo. Por ejemplo:
Código:
int largoArray = arrayNumeros.Length; //Esto me devuelve 5
¿Cuándo usar un array?

Es útil cuando necesito tener un conjunto de datos cuya cantidad es de largo fijo, es decir, que no se planea agregar más adelante mayor cantidad de elementos que los que se permite. A diferencia de otras estructuras de colecciones de elementos como son las listas que tienen mayor flexibilidad, Array es más rápido.

Ejercicios:
  1. Crear un array de 5 números y asignarle un número a cada posición del array. Imprimir todos los números del array.
  2. Dado un array de números, imprimir los números en orden inverso al que se encuentran en el array.
Ejemplo:
[1, 6, 3, 7] = > Imprimir 7, 3, 6, 1
  1. Realizar un método que dado un array de strings de largo 10, retorne el string más largo (en caso que haya más de uno con el mismo largo, devolver cualquiera de ellos). Tener en cuenta que si un string tiene como valor null, no se le pueden usar las operaciones de string ya que daría error.
  2. Realizar un método que dado un array de números, retorne el número más grande en el array, y un método que devuelva el número más chico.
  3. Realizar un método que dado un array de int y un número, devuelva true en caso que el número se encuentre en el array.
  4. Dado un array de números y un número, indicar la cantidad de números del array que son mayores que dicho número.
  5. Realizar un método que dado un array de números y un número determinado, devuelva un nuevo array con los valores del anterior multiplicados por dicho número.
  6. Dado un array de strings, transformar todos los strings de dicho array para que su texto aparezca en mayúscula.
  7. Dado un array de números y un número, devolver un array con los números del array que son mayores que dicho número.
  8. Dados dos arrays de números, en el caso que sean de distinto largo retornar un array con el número 0. En caso de que tengan el mismo largo, retornar un array con la suma de cada número en su misma posición.
Ejemplo:
[3,2,1], [10, 20, 30] => [13, 22, 31]
[3,4,5,6],[1,2] => [0]
  1. Dado un array de números, imprimir la suma del número de cada posición de un array con el número de la posición siguiente, y en el caso de la última posición se suma con el número de la primer posición.
Ejemplo:
[5,4,3,2,7] => Imprime 9,7,5,9,12
  1. Dado un array de números que solamente contiene números del 1 al 12, devolver un array de strings de igual tamaño que tenga los nombres de los meses correspondientes al número. Ejemplo:
[1, 3, 8] => [Enero, Marzo, Agosto]
  1. Crear un método de “Mayores que”, que dados dos arrays de números, retorna un array de bool que indica si el elemento en cada posición del primer array es mayor que el del segundo. El array de bool debe ser del tamaño del primer array. En caso que el primer array sea más grande que el segundo, los elementos sobrantes deben de tener “false”. En caso que el segundo sea más grande, los elementos sobrantes del segundo no se consideran.
Ejemplo:
[3,2,4,5], [4,1, 2,6] => [false, true, true, false]
[3,2,4,5], [1,2,3] => [true, false, true, false]
[3,2], [1,2,3] => [true, false]
  1. Dados dos arrays de números, revisar si hay algún número repetido entre ellos. Ejemplo:
[5, 4, 3, 2] y [4, 9, 5, 1] => Retorna True porque ambos tienen el 4
[5, 3, 9, 1] y [2, 4, 6, 8] => Retorna False porque no hay ninguno repetido
[4,3,2] y [2] => Retorna true porque ambos tienen el 2
  1. Dado un array de números, revisar si hay algún número repetido (pensar!!).
Ejemplo:
[5, 4, 3, 2] = >Retorna False porque no hay ningún número repetido
[5, 3, 9, 3] => Retorna True porque hay número repetido (el 3)

¿Qué les pareció? Espero su feedback!
 
Última edición:

Xiros

¡Pokémon Omega con actualización del 30/8!
Miembro de honor
Actualizado con la parte 4.

Las partes 2 y 3 no las he escrito, así que primero me voy a dedicar a publicar las partes que ya tengo escritas (alrededor de 10 más).

Reitero, cualquier sugerencia que tengan, si llega a haber algo que no se entienda o hay algún concepto no del todo bien explicado, peguen el grito y veré como ajustarlo :)
 

Lunos

Enfrentando a La Organización
Miembro insignia
Código:
Si está lloviendo
    Comprar tortafritas
En otro caso
    Comprar churros
Comer el alimento comprado
Este es un excelente tutorial con ejemplos satisfactorios y faciles de entender. Te quiero Xiros.
Matar, porque ahora tengo ganas de comer churros y tortafritas.
 
Arriba