Arreglos Multidimensionales en C#

En la clase anterior conocimos a los arreglos y definimos a estos como una lista en donde podemos guardar información. Aquellos arreglos también se llaman arreglos unidimensionales, porque su composición solo es de una dimensión (o de una sola lista). En palabras más sencillas, podemos crear arreglos más complejos, o arreglos de varias listas, gracias a esta característica. Para entenderlo un poco mejor, voy a dejar unos gráficos para diferencias la dimensión de los arreglos.

Como pueden observar, los arreglos unidimensionales se caracterizan por tener una sola lista, mientras que los otros por tener más. Los arreglos bidimensionales tienen filas y columnas, y se asemejan mucho a una tabla, y finalmente, los arreglos tridimensionales, es lo mismo que el anterior, pero con un arreglo dentro de cada casillero.

¿Se pueden crear arreglos de más dimensiones? Por supuesto, puedes crear arreglos de dimensiones infinitas, ya que C# te permite guardar un arreglo dentro de otro cuantas veces quieras, pero obviamente, eso sería una mala práctica dentro de la programación. Sin embargo, en el ámbito profesional te encontrarás con casos como esos, en donde tendrás que trabajar con mucha información y muchas listas, pero C# te ayudará a lidiar con esos problemas porque posee elementos más avanzados que aprenderemos más adelante.


Arreglos Bidimensionales

Un arreglo bidimensional es la combinación de listas horizontales con listas verticales, a las cuales las llamaremos filas y columnas respectivamente. Para declarar este tipo de arreglo, es necesario definir en primer lugar la cantidad de filas y luego la cantidad de columnas.

// Declaración simple
string[,] hobbies = new string[3, 4];
// Para declarar un arreglo bidimensional, siempre se considera una coma entre los corchetes
// Y para defiinir el tamaño, primero se considera las filas y luego las columnas

¿Y cómo funcionan los índices en este caso? Para ello vamos a revisar el siguiente gráfico.

Al ser un arreglo bidimensional, vamos a tener dos índices, donde la x representará a nuestras filas y la y a nuestras columnas, como ya he explicado más arriba. Por lo tanto, cada item de nuestro arreglo se identificará con (x,y). Para acceder al primer item, lo haremos con (0,0), mientras que para el último, lo haremos con (2,3). Vamos a llenar nuestro arreglo «hobbies» declarado más arriba, con los datos de nuestro gráfico.

hobbies[0, 0] = "Juan";
hobbies[0, 1] = "Leer";
hobbies[0, 2] = "Escribir";
hobbies[0, 3] = "Cantar";

hobbies[1, 0] = "María";
hobbies[1, 1] = "Jugar";
hobbies[1, 2] = "Bailar";
hobbies[1, 3] = "Leer";

hobbies[2, 0] = "Carlos";
hobbies[2, 1] = "Leer";
hobbies[2, 2] = "Nadar";
hobbies[2, 3] = "Correr";

Ahora imprimiremos todos los valores de nuestro arreglo, para ello, necesitaremos la ayuda de dos for, el primero recorrerá las X y el segundo las Y.

for(int x=0; x < 3; x++)
{
    for(int y=0; y < 4; y++)
    {
        Console.Write($"{hobbies[x, y]} ");
    }
    // Aquí haremos un salto de línea para que se vea más ordenado
    Console.WriteLine();
}

Y el resultado sería el siguiente.

Juan Leer Escribir Cantar
María Jugar Bailar Leer
Carlos Leer Nadar Correr

Como siempre, resolveremos un ejercicio para entender mucho mejor a los arreglos bidimensionales.

Ejercicio 1: Diseñe el siguiente arreglo bidimensional y ordene los números del 1 al 25 en forma de espiral.

Este ejercicio, si bien es cierto, parece un poco complejo, pero en realidad es bastante simple. Lo primero que tenemos que saber es como ir «pintando» cada lado del arreglo de manera individual. Por ejemplo, ¿cómo rellenamos de números la parte superior de nuestro arreglo? Para ello tenemos que tener en cuenta los índices y comenzar a jugar con ellos. La parte superior siempre tendrá como índice el x=0, mientras que la Y irá cambiando a medida que recorremos el arreglo con nuestro for. Para la parte inferior de nuestro arreglo, nuestro índice será x = [número total de filas] – 1, y la Y seguirá dependiendo de nuestro for. Si queremos pintar de manera vertical, tendremos que poner los valores al revés, por ejemplo, si queremos pintar la primera columna, el valor de X dependerá del for, mientras que la y=0, porque es la primera columna. Si queremos pintar la última, el valor de y será igual a y = [número total de columnas] – 1. Si queremos pintar de abajo hacia arriba, o de derecha a izquierda, recuerden que podemos poner nuestro for en viceversa. Probablemente toda esta explicación sea un poco confusa, pero lo entenderemos mejor con el ejemplo. Ahora les pondré un gráfico para saber como va a funcionar nuestro código.

Muy bien, si aún no se entiende la solución, vamos a ver como queda en nuestro código.

// Declaramos las variables para definir filas y columnas
// Para este ejercicio lo vamos a dejar en 5 para ambos
// Ya que el arreglo es de 5 x 5
int row = 5;
int column = 5;
// Definimos nuestro arreglo poniendo las filas primero y luego las columnas
int[,] spiral = new int[row, column];
// Definimos el contador, esta variable me ayudará a pintar los casilleros del arreglo
int count = 1;

// Para empezar, vamos a llenar nuestro arreglo de ceros
// Digamos que es una manera de "inicializarlo"

for (int x = 0; x < row; x++)
{
    for(int y = 0; y < column; y++)
    {
        spiral[x, y] = 0;
    }
}

// Ahora comienza los bueno...
// Para resolver este ejercicio, vamos a ir rellenando nuestro arreglo con los números de la manera que nos han pedido
// Primero se empieza por la parte superior, luego por la parte derecha, después la parte inferior, y finalmente la parte izquierda
// Luego tiene que repetirse el proceso a manera de bucle, pero ya no vamos a pintar todo, sino los espacios restantes.
// ¿Cómo identificar los espacios que no están pintados? Fácil, vamos a preguntar con un IF si están en 0.
// ¿Hasta cuando debemos repetir el bucle? Hasta que nuestro contador (count) haya llegado a su límite, que es 25 (o el valor de filas por columas)

// Declaramos nuestra variable que nos ayudará a pintar desde arriba
int top = 0;
// Declaramos nuestra variable que nos ayudará a pintar desde abajo
int bottom = row - 1;
// Declaramos nuestra variable que nos ayudará a pintar desde la derecha
int left = 0;
// Declaramos nuestra variable que nos ayudará a pintar desde la izquierda
int right = column - 1;

// Con el while crearemos el bucle para que este se ejecute hasta que count llegue a su límite.
while (count <= row * column)
{
    // Pintamos la parte superior
    for (int i = 0; i < column; i++)
    {
        // Validamos si el casillero está libre
        if (spiral[top, i] == 0)
        {
            // Las filas se mantienen estáticas y solo cambia el valor de i
            spiral[top, i] = count;
            // Actualizamos el count
            count++;
        }
    }
    // Aumentamos en 1 nuestra variable top para el siguiente bucle
    top++;

    // Pinta la parte derecha
    for (int i = 0; i < row; i++)
    {
        if (spiral[i, right] == 0)
        {
            // Las columnas se mantienen estáticas
            spiral[i, right] = count;
            count++;
        }
    }
    // Reducimos en 1 nuestra variable right para el siguiente bucle
    right--;

    // Pintamos la parte inferior
    // Según el orden del espiral, ahora debemos recorrer en viceversa
    // Declaramos nuestro for descendiente, este empezará desde el número de columnas - 1 y terminará en 0
    for (int i = column - 1; i >= 0; i--)
    {
        if (spiral[bottom, i] == 0)
        {
            // Las filas se mantienen estáticas
            spiral[bottom, i] = count;
            count++;
        }
    }
    // Reducimos en 1 nuestra variable bottom para el siguiente bucle
    bottom--;

    // Pintamos la parte izquierda
    // For descendente porque tenemos que recorrer de abajo hacia arriba
    for (int i = row - 1; i >= 0; i--)
    {
        if (spiral[i, left] == 0)
        {
            // Las columnas se mantienen estáticas
            spiral[i, left] = count;
            count++;
        }
    }
    // Aumentamos en 1 nuestra variable left para el siguiente bucle
    left++;
}

// Al final solo nos queda imprimir el arreglo y mostrarle al usuario
for (int x = 0; x < row; x++)
{
    for (int y = 0; y < column; y++)
    {
        Console.Write($"{spiral[x, y]} ");
    }
    Console.WriteLine();
}

Sí, un poco largo, pero no es tan difícil de entender, sin embargo, este código se puede mejorar, es decir, se puede hacer más legible y reducir muchas líneas para que no se vea tan grande. Eso se puede hacer a través de los métodos de C#, que ya estudiaremos más adelante. Ahora vamos a compilar nuestro código para ver como quedó todo.

1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

A pesar de que nuestro código lo hayamos construido para crear un arreglo de 5 * 5, este funciona para cualquier tamaño que le pongamos a nuestro arreglo, puedes probar cambiando los valores de las variables row y column.


Arreglos Tridimensionales

Si nuestro arreglo bidimensional tenía forma de tabla, este tipo de arreglo tiene forma de un cubo, es decir, ahora tendremos que declarar una variable más (Z) que vendría a ser la profundidad. Ahora vamos a ver como se declara este arreglo en C#.

// Declaración simple
string[,,] students = new string[2, 3, 4];
// Al ser un arreglo tridimenisonal, separamos con dos comas
// El primer valor serían las filas, luego las columnas y finalmente la profundidad

Ahora vamos a imaginar que cada fila es un alumno, cada columna una materia y finalmente la profundidad que vendría a ser la nota de cada materia. Con esos datos vamos a llenar nuestro arreglo.

// Alumnos de 5to
// Alumnos de sección A
students[0, 0, 0] = "Juan";
students[0, 0, 1] = "Marco";
students[0, 0, 2] = "Karen";
students[0, 0, 3] = "Denis";
// Alumnos de sección B
students[0, 1, 0] = "Jhon";
students[0, 1, 1] = "Larry";
students[0, 1, 2] = "Ringo";
students[0, 1, 3] = "Vilma";
// Alumnos de sección C
students[0, 2, 0] = "Gasper";
students[0, 2, 1] = "Jota";
students[0, 2, 2] = "Dina";
students[0, 2, 3] = "Pedro";

// Alumnos de 6to
// Alumnos de sección A
students[1, 0, 0] = "Joan";
students[1, 0, 1] = "Carlos";
students[1, 0, 2] = "Esther";
students[1, 0, 3] = "Vania";
// Alumnos de sección B
students[1, 1, 0] = "Kiara";
students[1, 1, 1] = "Stan";
students[1, 1, 2] = "Steph";
students[1, 1, 3] = "Carl";
// Alumnos de sección C
students[1, 2, 0] = "George";
students[1, 2, 1] = "Ben";
students[1, 2, 2] = "Andy";
students[1, 2, 3] = "Gloria";

El listado de estudiantes lo hemos separados por grado, que vendrían a ser las X o las filas, las secciones que vendrían a ser las Y o las columnas y los nombres que vendría a ser la Z o la profundidad. Finalmente, vamos a ver como recorrer este arreglo para imprimirlo.

for (int x=0; x < 2; x++)
{
    for (int y=0; y < 3; y++)
    {
        for (int z = 0; z < 4; z++)
        {
            Console.Write($"{students[x, y, z]} ");
        }
        Console.WriteLine();
    }
    Console.WriteLine();
}

El resultado sería el siguiente:

Juan Marco Karen Denis
Jhon Larry Ringo Vilma
Gasper Jota Dina Pedro

Joan Carlos Esther Vania
Kiara Stan Steph Carl
George Ben Andy Gloria

Para este tipo de arreglo no vamos a realizar ningún ejercicio, además de que no se me ocurre ninguno (pero me pueden dejar alguno en los comentarios si desean), así que pasaremos directamente a los ejercicios propuestos. Como nota, en el ámbito profesional, nunca he tenido necesidad de usar este tipo de arreglo.


Ejercicio 2: Cree un programa que genere un arreglo bidimensional de 5 * 5 y ordene los números en forma de zig zag.

1 2 6 7 15
3 5 8 14 16
4 9 13 17 22
10 12 18 21 23
11 19 20 24 25

Ejercicio 3: Cree un programa que genere un arreglo bidimensional de 12 * 12 y rellénalo con todos los valores de la tabla de multiplicar del 1 al 12.

Ejercicio 4: Cree un programa que genere un arreglo bidimensional de 3 * 3 y rellénalo de número aleatorios entre el 1 y el 9, pero que estos no se repitan, tampoco deben estar ordenados, como un sudoku.

¡Con eso hemos terminado la clase de hoy!


Recuerda que puedes comentar, suscribirte a nuestro blog y calificar la entrada para saber si el contenido te ha gustado. Si tienes alguna duda, no temas en preguntar. También te invitamos a seguir todas nuestras redes sociales y a unirte a nuestro servidor de discord. Te invito también a mis propias redes sociales en donde estaré colgando contenido adicional sobre programación, libros y videojuegos.