Anuncios

Bienvenidos sean a este post, hoy veremos la primera de las denominadas «estructuras complejas».

Anuncios

Este como su nombre lo indica es un array que se hace a base de un struct, su sintaxis de creacion es la siguiente:

struct nombre_struct nombre_array[tamaño];
Anuncios

Para recuperar la informacion simplemente pasamos la posicion de este como si fuera un array seguido de la propiedad:

nombre_array[posicion].propiedad;
Anuncios

Y para modificar el valor de una propiedad simplemente debemos hacer lo siguiente:

nombre_array[posicion].propiedad = valor;
Anuncios

Para entenderlo un poco mejor vamos a tomar el ejemplo que vimos en el post anterior y vamos a modificarlo, en caso de no tenerlo pueden pasar por el post, generarlos y ver la explicacion o pueden descargarlos en su ordenador mediante el siguiente link:

Anuncios

En caso de haberlos descargado o generados recuerden que deben estar en el mismo directorio, nuestra primera modificacion sera en el archivo cartas.c donde agregaremos primero este enum antes del main:

enum { 
        cCartasEnMazo = 48,
        cCartasEnMano = 3,
        cCartasEnPalo = 12 
}
Anuncios

Esto nos definira tres constantes que nos indiciaran algunos ascpectos del juego como son:

  • La primera indica la cantidad de cartas en el mazo
  • La segunda indica la cantidad de cartas en las manos del jugador
  • Por ultimo la cantidad de cartas de cada palo
Anuncios

Nuestra siguiente modificacion sera en el main, donde lo cambiaremos de la siguiente forma:

int main()
{
        Carta mazo[ cCartasEnMazo ];

        mazo[3].palo = oro;
        mazo[3].valorPalo = (int)oro;
        mazo[3].numero = cuatro;
        mazo[3].valorNumero = (int)cuatro;

        MostrarCarta(&mazo[3]);
	printf("\n");
}
Anuncios

Primero definimos un array del tipo Carta llamado mazo, el tamaño queda determinado por la constante cCartasEnMazo, esto es mas recomendable hacerlo asi para que en caso de que se modifique la forma de jugar podamos cambiar de forma mas simple el total de cartas, despues estableceremos el valor de lo que seria nuestra cuarta carta, observen que primero establecemos el valor de la propiedad palo a traves de la constante, tambien lo mismo con el numero, y en el caso de los valores usamos unos casteos para indicar que debe almacenar los enteros de esas constantes, despues simplemente pasamos la direccion de memoria de este array en la posicion que ingresamos los datos a la funcion MostrarCarta, compilemos y veamos su salida:

tinchicus@dbn001vrt:~/lenguajes/C$ ./prog/cartas 
     cuatro de Oro
tinchicus@dbn001vrt:~/lenguajes/C$
Anuncios

Como podemos ver funciono perfectamente, una opcion que podemos usar tambien y un poco mejor es atraves de apuntadores, pueden modificar el main de la siguiente manera:

int main()
{
        Carta mazo[ cCartasEnMazo ];

        Carta* aCarta = &mazo[3];

        aCarta->palo = oro;
        aCarta->valorPalo = (int)oro;
        aCarta->numero = cuatro;
        aCarta->valorNumero = (int)cuatro;

        MostrarCarta(aCarta);
	printf("\n");
}
Anuncios

En este caso simplemente definimos un nuevo apuntador llamado aCarta y lo apuntaremos a la direccion de memoria de la posicion 3 de mazo, despues en lugar de usar el operador punto usamos a este otro operador para asignar el valor, por ultimo en lugar de pasar la direccion del array pasamos al apuntador nuevo, si lo compilan deben obtener el mismo resultado, con esto pudimos ver como hacerlo de la forma que explicamos anteriormente pero si recuerdan tenemos una funcion para iniciar a nuestra carta, para ello modificaremos el main de la siguiente manera:

int main()
{
	Carta mazo[ cCartasEnMazo ];
	Carta* aCarta = &mazo[3];

	IniciarCarta(aCarta, oro, cuatro);

	MostrarCarta(aCarta);
	printf("\n");
}
Anuncios

Observen que simplemente mantenemos el apuntador a la posicion del array de Carta y luego pasaremos los datos necesarios a la funcion para que trabaje, tal como haciamos antes, pero ahora no tenemos mas una carta sino todo el mazo por lo tanto debemos comenzar a manipularlo y para ello haremos un par de modificaciones, la primera sera quitar el enum que agregamos del archivo cartas.c y lo pasaremos al archivo cartas.h y despues agregaremos dos funciones para manejar el mazo, veamos la primera y para ello en el final del archivo agregaremos el siguiente segmento:

void IniciarMazo( Carta* aMazo )
{
	Numero n[]={ uno, dos, tres, cuatro, cinco, seis,
			siete, ocho, nueve, sota, caballo, rey };

	Carta* aC;

	for(int i=0; i < cCartasEnPalo; i++)
	{
		aC=&(aMazo[i + (0*cCartasEnPalo)]);
		IniciarCarta(aC, oro, n[i]);

		aC=&(aMazo[i + (1*cCartasEnPalo)]);
		IniciarCarta(aC, copa, n[i]);

		aC=&(aMazo[i + (2*cCartasEnPalo)]);
		IniciarCarta(aC, basto, n[i]);

		aC=&(aMazo[i + (3*cCartasEnPalo)]);
		IniciarCarta(aC, espada, n[i]);
	}
}
Anuncios
Anuncios

En este caso tenemos un argumento de tipo Carta pero que sera un apuntador, ya veremos porque, lo siguiente es crear un array del enum Numero, aqui volvemos a pasar las constantes de dicho enum, luego declaramos un nuevo apuntador de tipo Carta, auqi tendremos un bucle for que contara todas las cartas de cada palo, dentro tenemos el ultimo apuntador que declaramos, en ella almacenaremos la direccion del apuntador que pasamos como argumento, aqui sumaremos el valor de i del bucle con el valor de la constante cCartasEnPalo multiplicado por cada «palo», en el primer caso lo hacemos por 0 para que no afecte al valor de i y obtengamos el rango de 0 a 11, para el segundo caso cubrira el rango de 12 a 23 y asi con el resto, en todos los casos volvemos a llamara IniciarCarta para poder establecer el valor en cada posicon de nuestro «mazo», observen que en cada uno de los casos usamos un palo distinto para diferenciarlos, con todo esto comentado pasemos a agregar la otra funcion mediante el siguiente segmento:

void MostrarMazo( Carta* aMazo )
{
	printf("%d cartas en el mazo\n\n", cCartasEnMazo);

	int indice = 0;

	printf("El mazo ordenado: \n");

	for(int i=0; i < cCartasEnPalo; i++)
	{
		indice=i + (0*cCartasEnPalo);
		printf(" (%2d)", indice + 1);
		MostrarCarta(&(aMazo[indice]));

		indice=i + (1*cCartasEnPalo);
		printf(" (%2d)", indice + 1);
		MostrarCarta(&(aMazo[indice]));

		indice=i + (2*cCartasEnPalo);
		printf(" (%2d)", indice + 1);
		MostrarCarta(&(aMazo[indice]));

		indice=i + (3*cCartasEnPalo);
		printf(" (%2d)", indice + 1);
		MostrarCarta(&(aMazo[indice]));

		printf("\n");
	}
	printf("\n");
}
Anuncios

Esta sera la funcion que nos mostrara todo el mazo, mostraremos dos mensajes, en uno indicaremos el total de cartas e iniciaremos una variable llamada indice, luego tenemos un bucle donde pasara por todas las cartas en un palo, dentro de este tenemos cuatro segmentos iguales pero para cada palo, tomemos uno para analizarlo:

indice=i + (0*cCartasEnPalo);
printf(" (%2d)", indice + 1);
MostrarCarta(&(aMazo[indice]));
Anuncios

Primero estableceremos un valor para indice, este es de la misma forma como vimos anteriormente donde se sumara el valor de la vuelta del bucle (i) con la multiplicacion de la constante cCartasEnPalo multiplicado por un numero, en este caso al igual que antes es para cubrir el rango de 0 a 11, mostraremos el valor de indice pero le sumaremos uno para que cuente de 1 a 48, por ultimo con este indice mostraremos el numero y palo de la carta mediante MostrarCarta, es exactamente lo mismo para el resto de los bloques que se repiten, por ultimo tenemos un \n para bajar a la siguiente linea, con todo esto comentado veamos como quedo nuestro archivo cartas.h:

cartas.h


enum {
	cCartasEnMazo = 48,
	cCartasEnMano = 3,
	cCartasEnPalo = 12
};

typedef enum {
	oro = 1,
	copa,
	basto,
	espada
} Palo;

typedef enum {
	uno = 1, dos, tres, cuatro, cinco, seis,
	siete, ocho, nueve, sota, caballo, rey
} Numero;

typedef struct
{
	Palo palo;
	int valorPalo;
	Numero numero;
	int valorNumero;
} Carta;

void CartaAString(Carta* aCarta,char aCadenaCarta[20])

{
	switch(aCarta->numero)
	{
		case uno: strcpy(aCadenaCarta, "as "); break;
		case dos: strcpy(aCadenaCarta, "dos "); break;
		case tres: strcpy(aCadenaCarta, "tres "); break;
		case cuatro: strcpy(aCadenaCarta, "cuatro "); break;
		case cinco: strcpy(aCadenaCarta, "cinco "); break;
		case seis: strcpy(aCadenaCarta, "seis "); break;
		case siete: strcpy(aCadenaCarta, "siete "); break;
		case ocho: strcpy(aCadenaCarta, "ocho "); break;
		case nueve: strcpy(aCadenaCarta, "nueve "); break;
		case sota: strcpy(aCadenaCarta, "sota "); break;
		case caballo: strcpy(aCadenaCarta, "caballo "); break;
		case rey: strcpy(aCadenaCarta, "rey "); break;
		default: strcpy(aCadenaCarta, "??? "); break;
	}

	switch(aCarta->palo)
	{
		case oro: strcat(aCadenaCarta,"de Oro"); break;
		case copa: strcat(aCadenaCarta,"de Copas"); break;
		case basto: strcat(aCadenaCarta,"de Bastos"); break;
		case espada: strcat(aCadenaCarta,"de Espadas"); break;
		default: strcat(aCadenaCarta,"de ????"); break;
	}
}

void IniciarCarta(Carta* aCarta, Palo p, Numero n)
{
	aCarta->palo		= p;
	aCarta->valorPalo	= (int)p;
	aCarta->numero		= n;
	aCarta->valorNumero	= (int)n;
}

void MostrarCarta(Carta* aCarta)
{
	char cadenaCarta[20] = {0};
	CartaAString(aCarta, cadenaCarta);
	printf("%18s", cadenaCarta);
}

void IniciarMazo( Carta* aMazo )
{
	Numero n[]={ uno, dos, tres, cuatro, cinco, seis,
			siete, ocho, nueve, sota, caballo, rey };

	Carta* aC;

	for(int i=0; i < cCartasEnPalo; i++)
	{
		aC=&(aMazo[i + (0*cCartasEnPalo)]);
		IniciarCarta(aC, oro, n[i]);

		aC=&(aMazo[i + (1*cCartasEnPalo)]);
		IniciarCarta(aC, copa, n[i]);

		aC=&(aMazo[i + (2*cCartasEnPalo)]);
		IniciarCarta(aC, basto, n[i]);

		aC=&(aMazo[i + (3*cCartasEnPalo)]);
		IniciarCarta(aC, espada, n[i]);
	}
}

void MostrarMazo( Carta* aMazo )
{
	printf("%d cartas en el mazo\n\n", cCartasEnMazo);
	int indice = 0;

	printf("El mazo ordenado: \n");

	for(int i=0; i < cCartasEnPalo; i++)
	{
		indice=i + (0*cCartasEnPalo);
		printf(" (%2d)", indice + 1);
		MostrarCarta(&(aMazo[indice]));

		indice=i + (1*cCartasEnPalo);
		printf(" (%2d)", indice + 1);
		MostrarCarta(&(aMazo[indice]));

		indice=i + (2*cCartasEnPalo);
		printf(" (%2d)", indice + 1);
		MostrarCarta(&(aMazo[indice]));

		indice=i + (3*cCartasEnPalo);
		printf(" (%2d)", indice + 1);
		MostrarCarta(&(aMazo[indice]));

		printf("\n");
	}
	printf("\n");
}
Anuncios

Nuestro ultimo paso sera modificar el main del archivo cartas.c de la siguiente manera:

int main()
{
        Carta mazo[ cCartasEnMazo ];

        IniciarMazo(&mazo[0]);

        MostrarMazo(&mazo[0]);
}
Anuncios

Seguimos definidendo un array de tipo Carta con el total de las cartas que establecimos con la constante cCartasEnMazo, despues llamamos a IniciarMazo y le pasaremos la direccion de memoria de la posicion 0 de nuestro array mazo, lo sigueinte sera mostrar el mazo mediante la funcion MostrarMazo y devuelta le pasamos la direccion de memoria de la posicion 0, con todo esto comentado veamos como es el codigo final del archivo cartas.c:

cartas,c

#include <stdio.h>
#include <string.h>
#include "cartas.h"

int main()
{
        Carta mazo[ cCartasEnMazo ];

        IniciarMazo(&mazo[0]);

        MostrarMazo(&mazo[0]);
}
Anuncios

Con todo esto comentado ahora si pasemos a compilarlo, ejecutarlo y ver como es su salida:

Anuncios

Como pueden ver es bastante simple de utilizar dado que es como cualquier array pero creado a partir de un struct, en los proximos posts continuaremos con otros tipos de estructuras complejas.

Anuncios

En resumen, hoy hemos a array de estructuras, que son, como se componen, como trabajan, sus distintas formas de trabajar, para finalmente ver un ejemplo donde nos permitio cambiar la forma de trabajar con nuestro mazo, en lugar de carta por carta utilizamos el mazo completo pero sin perder lo visto anteriormente, espero les haya sido de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios
pp258

Donación

Es para mantenimento del sitio, gracias!

$1.50