Você está na página 1de 51

eman ta zabal zazu

Universidad del Pas Vasco

Euskal Herriko Unibertsitatea

Fundamentos de Programacin:

Prcticas de C

Ingeniera Tcnica de Telecomunicacin

Bilbao, septiembre de 2009

ii

Fundamentos de Programacin: Prcticas de C.

Copyright c 2008, 2009 Gorka Prieto Agujeta, c 2009 Maider Huarte Arrayago

Fundamentos de Programacin: Prcticas de C by Gorka Prieto is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License. To view a copy of this license, visit

by-sa/3.0/us/;

http://creativecommons.org/licenses/

or, (b) send a letter to Creative Commons, 171 2nd Street,

Suite 300, San Francisco, California, 94105, USA.

Fundamentos de Programacin: Prcticas de C por Gorka Prieto est licenciado bajo una licencia Creative Commons Reconocimiento-Compartir bajo la misma licencia 2.5 Espaa License. Para ver una copia de esta licencia, visita

http://creativecommons.org/licenses/by-sa/2.5/es/;
nia, 94105, USA.

o, (b) manda una

carta a Creative Commons, 171 2nd Street, Suite 300, San Francisco, Califor-

Resumen
Con las siguientes prcticas se pretende aanzar los conceptos de programacin estructurada que se van viendo en las clases de teora de C. Tras la realizacin de las prcticas se habr implementado una aplicacin en C de unas 400 lneas de cdigo que permitir jugar desde la consola al juego Hundir la ota. En el juego se llevar un seguimiento de puntuaciones de distintos jugadores, se permitir guardar y recuperar partidas, y adems tambin se permitir que un usuario externo pueda disear sus propias pantallas. Para ello se partir de un programa sencillo y se ir incluyendo en cada prctica un concepto nuevo de los vistos en teora, comprobando la mejora que aporta sobre la versin anterior del programa. Al principio de cada prctica se debe realizar una copia del directorio con todos los cheros de la prctica anterior y, sobre esos cheros, se incluirn las nuevas funcionalidades.

iii

iv

RESUMEN

ndice general
Resumen

iii

0. Familiarizacin con el Entorno

0.1. 0.2. 0.3. 0.4.

Primer programa

. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1 4 5 5

Compilacin sin errores . . . . . . . . . . . . . . . . . . . . . . . . . . Compilacin con errores Depuracin . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1. Asignaciones y Operaciones Bsicas

1.1. 1.2. 1.3.

Declaracin de variables Salida por pantalla

. . . . . . . . . . . . . . . . . . . . . . . . .

7 8 8

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

Entrada por teclado . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2. Sentencias Selectivas

11

2.1. 2.2. 2.3.

Procesando la entrada del usuario . . . . . . . . . . . . . . . . . . . . Validando la entrada del usuario . . . . . . . . . . . . . . . . . . . . . Finalizando el juego . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11 11 12

3. Sentencias Repetitivas

13

3.1. 3.2.

Vamos a dibujar el tablero . . . . . . . . . . . . . . . . . . . . . . . . Mltiples entradas . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13 15

4. Funciones

17

4.1. 4.2.

Diseo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Re-estructurando el cdigo . . . . . . . . . . . . . . . . . . . . . . . .

17 18

vi

NDICE GENERAL

4.3.

El primer barco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

18

5. Arrays Unidimensionales

21

5.1. 5.2.

Creando la ota . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mostrando los tiros . . . . . . . . . . . . . . . . . . . . . . . . . . . .

21 22

6. Arrays Bidimensionales

25

6.1. 6.2.

Cambiando a arrays bidimensionales

. . . . . . . . . . . . . . . . . .

25 27

Flota hundida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7. Cadenas de Caracteres

29

7.1. 7.2.

Dando un nombre al usuario . . . . . . . . . . . . . . . . . . . . . . . Procesando la entrada del usuario . . . . . . . . . . . . . . . . . . . .

29 30

8. Estructuras

31

8.1. 8.2. 8.3.

Posicin Jugador Barco

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

31 32 32

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Ficheros binarios

35

9.1. 9.2.

Salvando partidas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Registrando las puntuaciones . . . . . . . . . . . . . . . . . . . . . .

35 37

10.Ficheros de texto

41

10.1. Creando la pantalla . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2. Cargando la pantalla . . . . . . . . . . . . . . . . . . . . . . . . . . .

41 42

Ejemplo de partida

43

Prctica 0 Familiarizacin con el Entorno


En esta primera clase se trata de que el alumno se familiarice con el entorno de programacin Eclipse. Para ello se crear un workspace y se tratarn los conceptos de edicin, compilacin y depuracin.

0.1. Primer programa


Para empezar a trabajar con Eclipse, lo primero ser arrancar la aplicacin haciendo doble click en su acceso directo. Enseguida se nos abrir una ventana con informacin sobre Eclipse: la versin (3.2 en nuestro caso), el copyright, etc. A partir de ese momento, empezar nuestra interaccin con Eclipse:

1. Cuando se nos abra la ventana con ttulo est dando la opcin de elegir lo que meteremos en un

Workspace Launcher, Eclipse nos llama el workspace. Se trata de un workspace


ser

directorio, nuestro directorio de trabajo. En nuestro caso, cada prctica la

workspace

diferente. Para ello, la ruta del

de la siguiente forma:

/home/user1/workspace/<nombre del alumno>/<no de prctica>


Por ejemplo, si el alumno Iker quiere trabajar en la prctica 0, tendr que escribir el

workspace

siguiente:

/home/user1/workspace/Iker/0
En caso de querer entrar a un

workspace

que ya existe (el de una prctica

antigua, por ejemplo), bastar con desplegar el men haciendo click en la echita o buscndolo mediante el botn 2. La primera vez que se entra en un de bienvenida

Browse.

Welcome.

workspace, Eclipse nos muestra una pgina

Para las prcticas no la vamos a utilizar, as que hay

que cerrarla para poder empezar a trabajar, haciendo click en el aspa.

PRCTICA 0.

F AMILIARIZACIN CON EL ENTORNO

Figura 1: Entorno de Desarrollo Integrado (IDE) Eclipse

3. Una vez cerrada la ventana de bienvenida, estaremos ante lo que llamaremos la perspectiva de desarrollo de Eclipse, es decir, una ventana con diferentes zonas de informacin, como la que vemos en la gura 1. 4. Para empezar a escribir un programa en C, entraremos en el men:

File->New->Project
5. Se nos abrir la ventana

New Project,

en la que elegiremos:

C-> Managed Make C Project


6. A continuacin se nos pide un nombre para el proyecto. En nuestro caso, si el

workspace se corresponde con la prctica, el proyecto se corresponder con un


ejercicio. As, por cada ejercicio habr que hacer un proyecto diferente. Como nombre, le pondremos el nmero del ejercicio. Pulsamos 7. En la siguiente ventana simplemente pulsaremos 8. Eclipse puede abrirnos una ventana llamada

Next

para seguir.

Finish

sin cambiar nada.

Open Associated Perspective?, a la que contestaremos que s despus de marcar la opcin Remember my decission.
Con eso evitaremos que nos lo vuelva a preguntar en otros proyectos del mismo workspace (gura 2).

9. Al crearse el proyecto, en la columna izquierda aparecer el icono de una carpeta abierta con el nombre del proyecto. Signica que se ha creado!.

0.1.

PRIMER PROGRAMA

Figura 2: Abrir la perspectiva adecuada

Para empezar a escribir un chero fuente, haremos click con el botn derecho del ratn sobre el proyecto, y en el men desplegable que nos sale, elegiremos:

New->Source File
10. Se nos abrir una ventana en la que se nos pide que indiquemos el nombre del chero fuente. Pondremos el mismo nombre que el del proyecto, terminndolo en

.c.

Despus, pulsaremos

Finish.

11. En la columna izquierda aparecern dos carpetas nuevas dentro de la del proyecto y el icono que indica que el chero fuente est creado; pero est vaco. La zona central ahora representa una hoja en blanco, en la que escribiremos nuestro programa. Empezaremos con un programa sencillo . . .

#include <stdio_ext.h> int main() { char nombre[20]; int edad; printf(Introduzca su nombre: ); fflush(stdout);

PRCTICA 0.

F AMILIARIZACIN CON EL ENTORNO

__fpurge(stdin); scanf(%s,nombre); printf(Introduzca su edad: ); fflush(stdout); __fpurge(stdin); scanf(%d,&edad); printf(Hola %s, tienes %d aos!!!!\n,nombre,edad); } return 0;

12. Guardaremos el chero haciendo click en el icono del disquete; Eclipse, por defecto, compila los cheros fuentes que tenga abiertos cada vez que guardemos alguno. Por este motivo, recomendamos no tener ms de un proyecto abierto a la vez. 13. Una vez compilado, en la ventana

Problems de la parte inferior de la zona del

chero fuente, veremos los problemas que hayan surgido durante la compilacin y el linkado. Estos problemas se nos indicarn en dos formas: errores y

warnings

(avisos).

Si hemos cometido errores sintcticos al escribir nuestro programa, el compilador lo indicar como errores, y no habr creado ningn ejecutable, es decir, todava no tendremos programa para ejecutar. Los

warnings

son avisos de problemas menos graves; si los problemas que

ha tenido el compilador han producido slo es recomendable que no haya no funcionar correctamente.

warning,

se habr creado un

ejecutable, por lo que podremos ejecutar nuestro programa. De todas formas,

warnings

porque con ellos el programa puede

0.2. Compilacin y ejecucin de un chero fuente sin errores


1. Si hemos copiado el cdigo anterior correctamente, lo nico que nos puede aparecer en

Problems

es un

warning

indicando que el chero no termina en

una lnea vaca . . . As que tendremos programa para ejecutar! 2. Iremos al men

Run->Run... Run.
Haremos doble click sobre la lnea

Se nos abrir la ventana

C/C+

Local

Application+ de la columna izquierda, y aparecer una nueva lnea debajo con el nombre del proyecto. En la zona de la derecha, aparecer una ventana en la que tendremos que introducir el valor de

C/C+

Main

Application+. Para ello

0.3.

COMPILACIN CON ERRORES

pulsaremos sobre el botn el binario

Binary

Browse y, en la ventana que se nos abre, elegiremos Run para empezar a ejecutar nuestro prograConsole que est al lado de la de Problema.

que se llame como el proyecto.

Finalmente, pulsaremos el botn ma.

3. La ejecucin ocurrir en la ventana

Lo veremos con slo pulsar su nombre . . .

0.3. Compilacin de un chero fuente con errores sintcticos


1. Provocaremos un error sintctico si, por ejemplo, comentamos la lnea de declaracin de la variable edad. En compilar. 2. El error aparece con una breve explicacin y el nmero de lnea en la que se ha producido. Haciendo doble click sobre el error, nos llevar a la lnea en la que ha detectado el error. Sin embargo, no siempre el lugar donde se ha detectado el error es donde se puede arreglar . . .

Problems

aparecer un error al guardar y

0.4. Compilacin, ejecucin y depuracin de un chero fuente con errores de edicin


1. Provocaremos un error de redaccin que no produce un error sintctico . . . pero impide que el programa funcione bien. Para ello, cambiaremos el ltimo por este otro:

printf

printf(Hola %d, tienes %d aos!!!!\n,nombre,edad);


2. Guardaremos y compilaremos. Esta vez no habr errores en

Problems. Ejecu-

taremos el programa como antes . . . y todo funcionar bien hasta llegar al nal. Ahora, en el saludo no sale el nombre introducido, sino un nmero . . . pero nosotros le hemos introducido un nombre . . . 3. Estamos ante un error de funcionamiento, que se corrige depurando. En este caso, el nombre puede haberse guardado mal, o el problema es que se visualiza mal. Para depurar, entraremos esta vez en ventana En

Debug,

muy parecida a la de

Run,

Run->Debug.

Se nos abrir la

que utilizaremos para depurar.

Debug haremos lo mismo que hacemos en Run para ejecutar. Despus, para comenzar la depuracin, pulsaremos el botn Debug.

PRCTICA 0.

F AMILIARIZACIN CON EL ENTORNO

Figura 3: Perspectiva de depuracin

4. La primera vez que se depura en un

workspace, Eclipse pregunta si estamos de

acuerdo en cambiar la perspectiva . . . como en el punto anterior. La perspectiva de depuracin tiene diferentes zonas, como se ve en la gura 3. 1: Variables en memoria 2: Fichero Fuente 3: Consola 5. El cursor en el chero fuente estar sobre la primera llave de bloque

{.

Pul-

sando F6, el programa se ejecutar paso a paso. Para depurar, es importante comprobar lo que hay en la consola y los valores de las variables, cada vez que ejecutemos un paso (pulsemos F6). As, podemos comprobar cmo no sale nada en la consola hasta ejecutar los

fflush,

o cmo

scanf

espera hasta que

introduzcamos algo por teclado. En nuestro caso, veremos que los valores guardados en las variables son las que se han introducido por teclado (pulsando sobre las variables en la zona 1). 6. Al llegar al ltimo el cambiar la

bre adecuado, as que es el

printf comprobaremos que la variable nombre tiene el nomprintf el que no hace lo que queremos . . . efectivamente, s por una d ha provocado este mal funcionamiento, que hemos

podido localizar gracias al depurador.

Prctica 1 Asignaciones y Operaciones Bsicas


En esta primera prctica se pretende familiarizar al alumno con la creacin y el manejo de variables simples. Adems se usarn algunas funciones bsicas de entrada por teclado y salida por pantalla que nos resultan de utilidad y en las que se profundizar ms adelante en el tema de funciones.

1.1. Declaracin de variables


Vamos a comenzar deniendo el tamao de nuestro tablero de de cmo ser este tablero:

hundir la ota

dentro del cual estarn los distintos barcos. La siguiente gura muestra un ejemplo

0 A B C D E F G H I J

En la funcin main crea las dos variables siguientes:

Una de tipo ser la 19.

int

que contenga el nmero de la ltima columna del tablero. Si

el tablero tiene 20 columnas y numeramos desde el 0 (0, 1, 2, . . . , 19) la ltima

PRCTICA 1.

ASIGNACIONES Y OPERACIONES BSICAS

Otra de tipo

char

que contenga la letra de la ltima la del tablero. Si el

tablero tiene 10 las (A, B, C, . . . , J) la ltima ser la J.

Desde el mismo cdigo fuente debes asignar ya un valor inicial a estas variables. Esto lo puedes hacer en la misma declaracin de la variable o mediante una nueva instruccin de asignacin. Prueba a compilar el programa y que todo funcione correctamente (sin ni errores).

warnings

1.2. Salida por pantalla


Un vez asignado un valor a estas dos variables que nos indican el tamao del tablero, mostrar por pantalla un mensaje al usuario similar al siguiente:

Bienvenido a "Hundir la Flota"! - El tamao del tablero es: 20 columnas x 10 filas. - La columna se indica con un nmero (0, 1, 2, ..., 19) - La fila se indica con una letra mayscula (A, B, C, ..., J)
Los nmeros y letras que aparecen en el mensaje se deben calcular en funcin de los valores contenidos en la variables. Probar a cambiar los valores de la variables y volver a recompilar y ejecutar el programa para ver cmo se actualiza el mensaje.

1.3. Entrada por teclado


A continuacin vamos a permitir que el usuario introduzca una coordenada por teclado y vamos a visualizar su valor. Para ello creamos dos nuevas variables que almacenen la coordenada:

Una de tipo Otra de tipo

char int

para almacenar la la. para almacenar la columna.

A continuacin mostrar un mensaje de texto pidiendo al usuario que introduzca la coordenada. Por ejemplo:

Introduce una coordenada (ej. B12) :

1.3.

ENTRADA POR TECLADO

Leer el valor que introduce el usuario dejando guardando la letra en la variable de tipo

char

y el nmero en la de tipo

int.

Finalmente mostrar al usuario la coordenada introducida con un mensaje similar al siguiente:

(Fila B, Columna 12)

10

PRCTICA 1.

ASIGNACIONES Y OPERACIONES BSICAS

Prctica 2 Sentencias Selectivas


Mediante el uso de sentencias selectivas podemos hacer que el programa realice comparaciones y en funcin del resultado ejecute unas instrucciones u otras. En esta prctica vamos a utilizarlas para comprobar que los datos introducidos por el usuario sean correctos.

2.1. Procesando la entrada del usuario


Partiendo del cdigo de la prctica anterior, vamos a habilitar la posibilidad de que el usuario introduzca la letra tanto en maysculas como en minsculas. Para ello:

Nada ms leer la entrada del usuario comprobar si la letra (correspondiente a la la) introducida est entre los valores 'a' y 'z'. Si es as, restarle 32 al cdigo ASCII para transformar la letra en una mayscula. Ahora ser este nuevo valor el que se utilice en el resto del cdigo, tanto para comprobar si est en un rango de valores vlido (siguiente apartado) como para visualizar la coordenada por pantalla.

2.2. Validando la entrada del usuario


Aadir las instrucciones necesarias para que, tras disponer de las coordenadas introducidas por el usuario ya procesadas, compruebe si son vlidas o no. En caso de que no sean vlidas, avisar de ello y salir. En concreto:

Comprobar si la la est entre 'A' y la letra correspondiente a la ltima la. Si no es as, se visualizar un mensaje por pantalla indicando el rango vlido de las.

11

12

PRCTICA 2.

SENTENCIAS SELECTIV AS

Comprobar si la columna est entre 0 y el nmero correspondiente a la ltima columna. Si no es as, se visualizar un mensaje por pantalla indicando el rango vlido de columnas.

2.3. Finalizando el juego


Finalmente realizamos una comprobacin adicional que servir al usuario para noticar que desea terminar de jugar (esto ser de utilidad ms adelante).

Aadir las instrucciones necesarias para que en caso de que el usuario introduzca como coordenada Z0 se muestre un mensaje indicando que el juego ha terminado y se nalice la aplicacin.

Prctica 3 Sentencias Repetitivas


Mediante las sentencias repetitivas podemos hacer que un fragmento de cdigo se repita un determinado nmero de veces a la vez que van cambiando sus variables. En esta prctica las vamos a utilizar en primer lugar para dibujar el tablero y en segundo lugar para permitir que el usuario introduzca mltiples coordenadas.

3.1. Vamos a dibujar el tablero


De nuevo partimos del cdigo de la prctica anterior. Vamos a cambiar el mensaje de inicio donde se explica cmo indicar la y columna, as como su rango vlido, por un dibujo del tablero (y es que vale ms una imagen que mil palabras). Como primera prueba, dibujamos los ejes de coordenadas:

Mediante un bucle

for mostrar por pantalla el nmero de cada columna segn 5 6 7 8 9 10 11 12 13 14

el siguiente formato:

Notar que al principio de la lnea hay dos espacios en blanco y que entre cada nmero hay otro espacio en blanco. Adems los nmeros de un slo dgito deben llevar un espacio en blanco adicional con el objetivo de ocupar lo mismo que los nmeros de dos dgitos. Mediante otro bucle

for fuera del anterior, mostrar en vertical la letra asociada

a cada la dejando una lnea en blanco antes de cada letra:

A B
13

14

PRCTICA 3.

SENTENCIAS REPETITIV AS

C
El resultado nal debera ser algo similar a lo mostrado a continuacin:

Bienvenido a "Hundir la Flota"! 0 A B C D E F G H I J Introduce una coordenada (ej. B12) :


El tablero as ya podra ser funcional, pero mejor si dibujamos las celdas. Para ello vamos a modicar el segundo bucle

5 6

9 10 11 12 13 14 15 16 17 18 19

for

anidando otros bucles dentro de l.

Substituir la lnea en blanco por una lnea que empiece por un espacio en blanco y que a continuacin repita tantas veces los caracteres  |__ (sin las comillas) como columnas tenga el tablero. Ejemplo:

|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__
En la lnea que muestra la letra, hacer que a continuacin repita el patrn |  (sin las comillas) tantas veces como columnas tenga el tablero.

De nuevo, el resultado nal debera ser algo similar a lo mostrado a continuacin:

3.2.

MLTIPLES ENTRADAS

15

Bienvenido a "Hundir la Flota"! 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ A| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ B| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ C| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ D| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ E| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ F| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ G| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ H| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ I| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ J| | | | | | | | | | | | | | | | | | | | Introduce una coordenada (ej. B12) :
Prueba a modicar el nmero de las y columnas y ver cmo efectivamente cambia el nmero de iteraciones del bucle y, por consiguiente, el tamao del tablero dibujado.

3.2. Mltiples entradas


Ahora que ya conocemos las sentencias repetitivas, vamos a utilizarlas para permitir que el usuario pueda introducir varias coordenadas en lugar de tan solo una.

Crear una variable Meter en un bucle

salir

de tipo

char

que inicialmente valga 0.

do-while la parte de cdigo correspondiente a la interaccin

con el usuario. De esta forma se le ir pidiendo que meta coordenadas. El bucle terminar cuando el usuario introduzca la combinacin Z0, momento en el que se mostrar el mensaje al usuario y se pondr a 1 la variable

salir.

A continuacin se muestra un ejemplo de la salida que debera mostrar el programa con la nueva modicacin:

16

PRCTICA 3.

SENTENCIAS REPETITIV AS

Bienvenido a "Hundir la Flota"! 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ A| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ B| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ C| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ D| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ E| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ F| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ G| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ H| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ I| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ J| | | | | | | | | | | | | | | | | | | | Introduce una coordenada (ej. B12) : g6 (Fila G, Columna 6) Introduce una coordenada (ej. B12) : l8 (Fila L, Columna 8) El rango vlido de filas es: A - J Introduce una coordenada (ej. B12) : l99 (Fila L, Columna 99) El rango vlido de filas es: A - J El rango vlido de columnas es: 0 - 19 Introduce una coordenada (ej. B12) : z0 --- Aplicacin finalizada a peticin del usuario ---

Prctica 4 Funciones
Por n podemos usar funciones!

La funcin principal ya va creciendo demasiado y el cdigo complicndose. Es normal que un programa medianamente complejo ocupe varios miles de lneas y sera muy complicado abordarlo empleando una nica funcin. Precisamente la programacin estructurada consiste en enfrentarse a este problema aplicando el principio de pequeas.

divide y vencers.

Las

funciones son el resultado de esta divisin del problema en partes ms

4.1. Diseo
Antes de comenzar a escribir la primera lnea de cdigo de cualquier programa se debe hacer un trabajo previo (tanto o ms importante que escribir el cdigo) y que consiste en realizar un buen diseo. Se debe pensar cmo estructurar el programa, es decir, en qu partes ms pequeas dividirlo y cmo comunicar estas partes. Ahora que ya sabemos cmo crear funciones propias, vamos a re-estructurar el cdigo antes de que siga creciendo y sea demasiado tarde. Como regla general la funcin

main

no debera ocupar ms de una pantalla y debera reejar todo lo que

hace el programa. Tpicamente lo que contendr ser llamadas a otras funciones que sern las que hagan el trabajo

engorroso.

Teniendo esto en cuenta, realiza un grco donde indiques en qu funciones vas a dividir el cdigo actual (el que viene de la prctica anterior) y un diagrama de ujo de cmo se van a utilizar esas funciones desde el

main.

En el resto de la prctica se propone un diseo que debers contrastar con el que hayas hecho t previamente y debatir en clase las ventajas de uno y de otro.

17

18

PRCTICA 4.

FUNCIONES

4.2. Re-estructurando el cdigo


Una vez hecho el diseo, vamos a separar el cdigo en las funciones que hemos considerado:

Funcin

DibujaTablero: int char


con la letra de la con el nmero de la ltima columna.

Toma dos parmetros de entrada, uno de tipo ltima la y otro de tipo

No devuelve ningn valor como salida. Dibuja el tablero con las dimensiones indicadas en los parmetros.

Funcin

LeeCoordenadas:

Toma como parmetros de entrada la ltima la y la ltima columna del tablero. Devuelve dos parmetros de salida, uno de tipo nada y otro de tipo

int

char

con la la seleccio-

con la columna seleccionada.

Adems asociado a su identicador devuelve un valor de tipo en caso contrario.

char

que

valdr 0 en caso de que el usuario haya indicado que desea terminar y 1

Esta funcin realiza la lectura de las coordenadas introducidas por teclado, comprobando si son correctas y solicitando al usuario que las vuelva a introducir en caso de que no sean correctas. Utilizar para ello el cdigo ya implementado en la prctica anterior.

Funcin

main: main para que use las dos funciones anteriores. Deber

Rehacer la funcin

mostrar el tablero y pedir una entrada de datos hasta que el usuario indique que desea nalizar, cosa que sabr gracias al valor de retorno de

LeeCoordenadas.

Recordad que en esta funcin tiene que quedar claro de una forma muy legible y simplicada lo que hace el programa.

4.3. El primer barco


Hasta ahora el juego no tiene mucho sentido ya que no se hace nada con las coordenadas que introduce el usuario. Para solucionar esto vamos a crear un primer barco muy simple. En posteriores prcticas aumentaremos el nmero y tipo de barcos disponibles. Nuestro primer barco va a ser de tan solo una casilla. Para ello vamos a aadir una nueva funcin y a ampliar la funcin

main:

4.3.

EL PRIMER BARCO

19

Funcin

CompruebaTiro:

Toma cuatro parmetros de entrada: las coordenadas introducidas por el usuario y las coordenadas con la posicin del barco. Devuelve un valor de tipo entero con la puntuacin del tiro. La puntuacin ser 0 si no se ha dado al barco y, de momento, 1 si s se le ha dado. Esta funcin es excesivamente simple, de hecho se podra poner el cdigo dentro del

main

y evitarse el crearla. Pero aqu es donde entra de nuevo

el diseo, y es que esta funcin se va a ir ampliando en las prcticas posteriores, con lo que ya dejamos el camino comenzado. Funcin

main:

Crear e inicializar las variables correspondientes para almacenar la posicin del barco. Crear una variable vidas de tipo entero e inicializarla con el nmero de tiros que queris permitir al jugador. Crear otra variable de tipo entero en el que se irn sumando los puntos que consiga el jugador y que inicialmente valdr 0. En el bucle principal, y tras leer las coordenadas del usuario, llamar a la funcin

CompruebaTiro.

Se deber comprobar el cdigo de retorno de

esta funcin de forma que:

Si es igual a cero, se le reste una vida al usuario. Se debe indicar al usuario que ha fallado y mostrarle el nmero de vidas restante. Adems si el usuario se queda sin vidas el programa debe nalizar.

Si es distinto de cero, su valor se suma a la variable que lleva los puntos. Se debe mostrar un mensaje al usuario indicando que ha acertado y el nmero de puntos acumulados.

Finalmente el programa antes de terminar debe indicar si se ha salido porque lo ha solicitado el usuario (Z0) o porque se le han acabado las vidas ( obtenida.

Game Over ). En este ltimo caso adems debe mostrarse la puntuacin

20

PRCTICA 4.

FUNCIONES

Prctica 5 Arrays Unidimensionales


En esta prctica vamos a introducir otro concepto muy importante, los arrays. Un array permite tener una coleccin de variables del mismo tipo. En concreto lo vamos a usar para permitir que nuestro juego tenga ms de un barco.

5.1. Creando la ota


En este apartado vamos a permitir crear una ota de barcos, de momento, todos de una nica casilla. Para ello vamos a crear una nueva funcin y actualizar otras ya existentes:

Funcin

CreaFlota char
y otro de tipo

Toma como entrada dos arrays, uno de tipo

int.

En

el primero guardar las las en las que estn los barcos que queramos poner y en el segundo las columnas correspondientes. De esta forma, por cada barco tendremos su la guardada en el primer array y su columna guardada en la misma posicin del segundo array.

Devuelve como salida un valor de tipo que se han creado.

int indicando el nmero de barcos

En esta funcin se debe inicializar estos arrays con las posiciones que elijamos para, por ejemplo, 3 barcos.

Funcin

CompruebaTiro

Ahora que tenemos varios barcos en lugar de tan solo uno, habr que actualizar esta funcin. Como parmetros de entrada, en lugar de la la y columna del barco, ahora tomar dos arrays con las las y columnas de todos los barcos de la ota. Adems, relacionado con estos arrays, recibir otro parmetro de tipo

int

que indicar el nmero de elementos vlidos en ambos arrays.

21

22

PRCTICA 5.

ARRAYS UNIDIMENSIONALES

Deber recorrer esos arrays para comprobar si el tiro ha dado a algn barco:

En caso armativo, escribir en las posiciones correspondientes al barco las coordenadas (Z,0). De esta forma evita que el usuario sume puntos disparando siempre a la misma posicin. Finalmente devolver un 1 como valor de retorno.

Funcin

En caso negativo devolver 0 como valor de retorno.

main int char


para las las de los barcos y para las columnas.

Deber crear dos arrays, uno de tipo otro de tipo

Deber llamar a la funcin

CreaFlota

pasndole estos dos arrays para

que los inicialice. Adems, tambin recoger el valor de retorno de la funcin para as saber cuntas de las posiciones del array tienen datos vlidos.

Se deber actualizar la llamada a la funcin vlidos en ambos arrays.

CompruebaTiro

para que le

pase los arrays con las posiciones de los barcos y el nmero de elementos

5.2. Mostrando los tiros


Bien, ya es hora de dar un poco de animacin a ese tablero que siempre aparece vaco. Para ello vamos a llevar un seguimiento de los tiros realizados para dibujar posiciones an sin usar, tiros acertados y tiros fallados. Para hacer esto, vamos a tener que crear nuevos arrays y modicar funciones existentes:

Funcin

main

Crear tres nuevos arrays para llevar un seguimiento de los tiros. Un array indicar la la del tiro, otro la columna y otro el resultado devuelto por

CompruebaTiro.

Adems habr que crear otra variable de tipo entero que lleve un seguimiento del nmero de tiros almacenados en estos tres arrays. Funcin

DibujaTablero

Ahora esta funcin deber mostrar las casillas vacas si an no se han usado y el valor de resultado del tiro en caso de que s se hayan usado. Para ello habr que pasarle como nuevos parmetros de entrada los tres nuevos arrays y el nmero de elementos vlidos en ellos.

A continuacin se muestra un ejemplo de cmo quedara la salida por pantalla con el cdigo como est ahora:

5.2.

MOSTRANDO LOS TIROS

23

Bienvenido a "Hundir la Flota"! 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ A| | | | 1| | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ B| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ C| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ D| | | | 0| 0| | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ E| | | | | | | | | 0| 0| 1| 0| | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ F| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ G| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ H| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ I| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ J| | | | | | | | | | | | | | | | | | | | Fallaste!!, te quedan 0 vidas. Puntuacin: 2 --- Game Over ---

24

PRCTICA 5.

ARRAYS UNIDIMENSIONALES

Prctica 6 Arrays Bidimensionales


El manejo del tablero nos ha venido pidiendo a gritos que usemos arrays bidimensionales, por n es el momento. En esta prctica vamos a ver cmo se simplica el cdigo por el hecho de usar estos arrays.

6.1. Cambiando a arrays bidimensionales


Usaremos un array bidimensional para almacenar la posicin y tipo de los barcos y otro array bidimensional para almacenar los tiros realizados junto con su resultado. Adems ahora podremos utilizar ya barcos de distintos tamaos.

El array de barcos en cada posicin (la, columna) contendr un 0 si no hay ningn barco que pase por ella y un nmero con el tamao del barco (nmero de casillas que ocupa) si s hay un barco que pase por ella. El array de tiros en cada posicin contendr un

-1 si an no se ha realizado un

tiro en esa posicin, un 0 si se ha disparado en esa posicin y no haba barco, y el tamao del barco en caso de que s hubiese barco.

La reserva de memoria de estos arrays la vamos a realizar de forma esttica. Para ello vamos a denir dos macros con las dimensiones del tablero, una con el nmero de las y otra con el nmero de columnas. Este cambio en la forma de representar los datos va a implicar las siguientes adaptaciones al cdigo que tenamos en la prctica anterior:

Funcin

main

Ya no hacen falta las variables que indican la dimensin del tablero, ya que ahora est indicada por las dos macros que hemos creado. Las variables que indicaban nmero y posicin de los barcos se pueden sustituir por un nico array bidimensional. Este array ser de tipo

int

25

26

PRCTICA 6.

ARRAYS BIDIMENSIONALES

y tendr las mismas dimensiones que el tablero. Cada posicin del array indicar si hay algn barco y su tamao en caso armativo.

Las variables utilizadas para llevar el seguimiento de los tiros tambin se podrn sustituir por un nico array bidimensional. Este array ser de tipo

int

y tendr las mismas dimensiones que el tablero. Cada posicin del

array indicar si se ha realizado un tiro y su resultado en caso armativo. Habr que actualizar los parmetros que se les pasa a las distintas funciones a las que llama. Los cambios a estas funciones se detallan a continuacin. Funcin

IniciaArrays CreaFlota

Reemplaza a la anterior funcin

Toma como parmetros los dos arrays bidimensionales, el que indica la posicin de los barcos y el que almacena los tiros realizados. Ya no devuelve ningn valor como parmetro de retorno asociado a su identicador. Inicializa los arrays con valores seguros. El de barcos todo con ceros y el

-1. Un 0 en el array de barcos indica que en esa posicin no hay ningn barco. Un -1 en el array de tiros indica que en esa posicin
de tiros todo con an no se ha realizado ningn tiro.

Finalmente almacena la posicin de dos barcos en el array de barcos. Uno horizontal que ocupe 3 casillas y otro vertical que ocupe 4 casillas. En cada casilla ocupada por cada barco se debe sobreescribir el 0 que estaba almacenado por un nmero que indique el tamao del barco correspondiente.

Funcin

DibujaTablero

Ahora no requiere que se le pasen las dimensiones del tablero ya que se pueden usar directamente las macros que indican el nmero de las y de columnas.

Para indicarle los tiros bastar con pasarle el array bidimensional correspondiente. A la hora de dibujar el tablero consultar por cada casilla la posicin correspondiente en el array bidimensional de tiros.

Si su valor es

-1,

es que an no se ha realizado ningn tiro en esa

posicin y deber dibujarse la casilla en blanco. En caso contrario habr que dibujarse en la casilla el valor almacenado en el array. Este valor ser 0 si se ha realizado un tiro y no haba barco y distinto de 0 en caso contrario. Funcin

LeeCoordenadas

6.2.

FLOTA HUNDIDA

27

Ya no requiere que se le indiquen las dimensiones del tablero para hacer la comprobacin. Ahora estas dimensiones las puede obtener directamente a partir de las macros creadas.

Habr que actualizar las comprobaciones ya que ahora no disponemos de una variable que indique la ltima la o columna, sino el nmero total de las y de columnas.

Como valor de la, en lugar de devolver la letra, se va a devolver el nmero de la la (manteniendo el tipo de dato como la columna se devuelve como siempre.

char).

El valor de

Funcin

CompruebaTiro

Se le pasan como parmetros la la y columna del tiro, as como los dos arrays bidimensionales con la posicin de los barcos y los tiros realizados. En primer lugar debe consultar el array con la posicin de los tiros para ver si el tiro ya se haba realizado en esa misma posicin. Para ello bastar con comprobar si el valor correspondiente en el array es distinto de en cuyo caso la funcin debe devolver 0 y terminar.

-1,

Si la posicin del array an no se haba usado (caso normal), almacenar en ella el valor que haya en la misma posicin del array de barcos. Este valor ser 0 si no hay ningn barco en esa posicin y distinto de cero en caso de que haya algn barco.

Finalmente devolver este valor como parmetro de retorno para que pueda ser consultado directamente por la funcin que la ha llamado (main) y saber si ha fallado o acertado para as actualizar las vidas o los puntos.

6.2. Flota hundida


Hasta ahora habamos pasado por alto un pequeo detalle: qu pasa cuando hemos hundido todos los barcos? . . . Lo que pasa es que el juego permite seguir disparando hasta que se acaben las vidas. Vamos a solucionar esto comprobando si la partida se puede dar por ganada.

Funcin

ComparaArrays

Toma como parmetros de entrada los arrays bidimensionales con la posicin de los barcos y los tiros realizados. Devuelve como parmetro de salida un

char que valdr 0 si quedan barcos

por hundir o 1 si se ha hundido toda la ota. Para ello debe comprobar si en las posiciones de los barcos el valor correspondiente del array de tiros es distinto de Funcin

-1.

main

28

PRCTICA 6.

ARRAYS BIDIMENSIONALES

Despus de comprobar el tiro debe llamar a la funcin para saber si la partida ha concluido.

ComparaArrays

En caso de que la partida concluya por haber hundido toda la ota, debe mostrar un mensaje de enhorabuena.

A continuacin se muestra un ejemplo de una posible salida por pantalla tras una partida:

Bienvenido a "Hundir la Flota"! 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ A| | 0| | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ B| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ C| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ D| | | | 3| 3| 3| | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ E| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ F| | | | | | | | | | | | | | | 0| 4| 0| | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ G| | | | | | | | | | | | | | | | 4| | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ H| | | | | | | | | | | | | | | | 4| | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ I| | | | | | | | | | | | | | | | 4| | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ J| | | | | | | | | | | | | | | | | | | | Tocado!!, vas 7 puntos. Enhorabuena, juego superado!!!

Prctica 7 Cadenas de Caracteres


En esta prctica vamos a usar un nuevo tipo de datos, las cadenas de caracteres. En C este tipo de datos se trata como un array unidimensional de caracteres acabado siempre en el carcter nulo. En la librera estndar se proporcionan distintas funciones bsicas que nos simplican el trabajo con cadenas de caracteres y con las que vamos a practicar.

7.1. Dando un nombre al usuario


Al empezar el juego vamos a pedirle al usuario su nombre. Este nombre lo utilizaremos en prcticas posteriores para realizar un seguimiento de las puntuaciones de distintos usuarios. Funcin

main

Crea una cadena de caracteres de un tamao mximo que deniremos en una macro. Antes de empezar el juego pide el nombre al usuario mediante la funcin que se explica a continuacin. Este nombre deber quedar guardado en la variable que se ha creado.

Cuando se termine el juego por cualquiera de los tres casos (se acaban las vidas, se hunde toda la ota, o el usuario pide terminar la partida) se debe mostrar un mensaje indicando el nombre del usuario y el nmero de puntos conseguidos.

Funcin

PideNombre

Utiliza como parmetro de entrada/salida un puntero a una cadena de caracteres ya reservada en memoria y con el tamao indicado por la macro.

Muestra un mensaje al usuario preguntndole por su nombre y lo lee por teclado guardndolo en la posicin indicada por el puntero.

29

30

PRCTICA 7.

CADENAS DE CARACTERES

7.2. Procesando la entrada del usuario


Al ejecutar el programa del apartado anterior habris observado que junto al nombre del usuario se guarda tambin el carcter de nal de lnea. Adems, si un usuario no introduce ningn nombre el programa mostrar el mensaje con las puntuaciones con el campo de nombre en blanco. A continuacin solucionamos estos y otros asuntos.

Funcin

ProcesaCadena

Utiliza como parmetro de entrada/salida un puntero a una cadena de caracteres acabada en el carcter nulo. Recorre esta cadena eliminando los espacios en blanco, tabuladores y saltos de lnea ('\n' y sobreescribindola.

'\r') y guarda el resultado en la misma direccin

Funcin

PideNombre ProcesaCadena tras leer la entrada del usuario. Annimo.

Debe llamar a la funcin

Despus de procesar la cadena, debe comprobar si sta est vaca y, en caso armativo, almacenar en ella como nombre de usuario

Prctica 8 Estructuras
Por n podemos usar estructuras! Las estructuras nos permiten agrupar una serie de datos de distintos tipos y que hacen referencia a un mismo elemento.

8.1. Posicin
En primer lugar vamos a empezar practicando con una estructura sencilla que usaremos para referenciar un punto en el tablero.

Estructura

Posicion char
que indica la la en el tablero.

Contiene un primer campo de tipo

Como segundo campo contiene la columna en el tablero almacenada como dato de tipo

int.

Funcin

LeeCordenadas Posicion
y almacena ah las coordenadas ledas

En lugar de los parmetros de la y columna, ahora toma por referencia una estructura de tipo del teclado.

Funcin

CompruebaTiro Posicion
con la posicin del tiro. Esta

En lugar de la la y columna del tiro, ahora toma como parmetro de entrada una estructura de tipo estructura se pasar por valor.

Funcin

main

Deber ser actualizada para que utilice la nueva estructura y llame de forma correcta a las funciones que se han modicado.

31

32

PRCTICA 8.

ESTRUCTURAS

8.2. Jugador
A continuacin vamos a crear otra estructura que nos permita referenciar de forma conjunta los datos del jugador. Esta estructura nos resultar de utilidad ms adelante cuando llevemos un seguimiento de puntuaciones de distintos usuarios o cuando queramos guardar y recuperar partidas.

Estructura

Jugador

Contiene un primer campo con el nombre del jugador. Est almacenado como una cadena de caracteres con tamao mximo el indicado por la macro que usamos en la prctica anterior.

Como segundo campo contiene la puntuacin del usuario almacenada como un dato de tipo

int.

Finalmente tiene otro campo con el nmero de vidas del jugador.

Funcin

IniciaJugador PideNombre
de la prctica anterior.

Reemplaza a la funcin

Toma como parmetro de entrada/salida un puntero a una estructura de tipo

Jugador.

Pide el nombre del usuario por teclado y, tras procesarlo segn se describi en la prctica anterior, lo devuelve en el campo correspondiente de la estructura.

Inicia a 0 el campo de la estructura que contiene la puntuacin del usuario. Inicia al mximo el nmero de vidas del jugador.

Funcin

main

Deber ser actualizada para que utilice la nueva estructura en lugar de las variables separadas que se usaban para el nombre del jugador, su puntuacin y las vidas restantes.

8.3. Barco
Vamos a complicarlo un poco ms. Por un lado vamos a usar una estructura como campo de otra estructura, y por otro lado vamos a trabajar con un array de estructuras. Para ello vamos a crear una estructura que almacene la posicin del barco y que usaremos para dibujar la ota al principio.

Estructura

Barco Posicion.

Contiene la posicin de un extremo del barco almacenada como un dato de tipo

8.3.

BARCO

33

A continuacin tiene un campo de tipo que est el barco. Este campo valdr

'V'

si el barco est en vertical y

'D'

char que indica la direccin en la 'H' si el barco est en horizontal,

si el barco est en diagonal.

Finalmente tiene otro campo de tipo

int que indica la longitud del barco.

Funcin

DibujaBarco Barco,
y el array bidimensional con las posiciones de

Toma dos parmetros de entrada: los datos del barco a dibujar como una estructura de tipo los barcos.

Dibuja en las casillas correspondientes del array bidimensional el barco indicado como parmetro.

Funcin

IniciaArrays

Conserva el cdigo que inicializa con valores seguros los dos arrays y elimina el cdigo en el que se dibujaban unos barcos iniciales. Crea un array de estructuras de tipo otro diagonal de longitud 4.

Barco e inicialzalo con las posiciones

de 3 barcos: uno horizontal de longitud 3, otro vertical de longitud 5 y

Recorre este array mediante un bucle llamando a la funcin de forma adecuada para que dibuje los tres barcos.

DibujaBarco

34

PRCTICA 8.

ESTRUCTURAS

Prctica 9 Ficheros binarios


Mediante el uso de cheros podemos hacer que la informacin generada a lo largo de la ejecucin del programa sea persistente, es decir, que no se pierda al nalizar el mismo. De esta forma podemos retomarla en una ejecucin posterior del programa. Esto la vamos a utilizar en esta prctica para poder salvar partidas entre otras cosas.

9.1. Salvando partidas


Dicho y hecho, ahora que ya podemos manejar cheros, vamos a guardar la partida en caso de que el usuario salga sin haber terminado el juego y vamos a reanudar la partida automticamente en la prxima ejecucin.

Funcin

SalvaPartida
(usamos el puntero por eciencia en el paso de parmetros), un

Toma como parmetros de entrada un puntero a un estructura de tipo

Jugador

puntero al array de barcos y otro puntero al array de tiros. Devuelve como valor asociado a su identicador un que haya ido bien.

int

que valdr 0 en

caso de que haya habido algn error al guardar la partida y 1 en caso de

Abre un chero binario y escribe los datos almacenados en los tres parmetros que se le han pasado a la funcin. Si hay algn error en este proceso, deber mostrar un mensaje de error y devolver 0.

Cierra el chero.

Funcin

CargaPartida
un puntero al array de barcos y otro puntero al array de tiros.

Toma como parmetros de entrada un puntero a un estructura de tipo

Jugador,

35

36

PRCTICA 9.

FICHEROS BINARIOS

Devuelve como valor asociado a su identicador un que haya ido bien.

int

que valdr 0 en

caso de que haya habido algn error al cargar la partida y 1 en caso de

Abre un chero binario y lee los datos almacenados en los tres parmetros que se le han pasado a la funcin. Si hay algn error en este proceso, deber mostrar un mensaje de error y devolver 0.

Cierra el chero.

Funcin

Terminar main

Como la gestin del n del juego se est complicando, vamos a quitarlo de la funcin y lo ponemos en esta funcin.

Toma como parmetros de entrada un puntero a un estructura de tipo

Jugador

(usamos el puntero por eciencia en el paso de parmetros), un

puntero al array de barcos y otro puntero al array de tiros. Comprueba las tres posibilidades de nalizacin del juego (juego superado,

game over

y partida abandonada) y muestra el mensaje correspon-

diente en pantalla.

Ahora adems, si el juego termina porque el usuario ha solicitado salir, se le preguntar al usuario si desea salvar la partida para retomarla la prxima vez que ejecute el programa. Si el usuario responde que s, se llamar a la funcin

SalvaPartida.

Esta funcin devolver 0 si ha habido algn error y 1 en caso de que todo haya ido bien.

Funcin

Iniciar main

Como la inicializacin del juego se est complicando, vamos a quitarla de la funcin y la ponemos en esta funcin.

Toma como parmetros de entrada un puntero a un estructura de tipo

Jugador,

un puntero al array de barcos y otro puntero al array de tiros.

Comprueba si existe el chero de partida guardada: Si no existe, llama a las funciones como hasta ahora. Si s existe, llama a la funcin

IniciaArrays

IniciaJugador

CargaPartida.

De nuevo la funcin devuelve 1 en caso de que todo vaya bien y 0 en caso de que haya habido algn error.

Funcin

main Iniciar
y

Deber actualizarse para hacer uso de las nuevas funciones

Detener

comprobando sus cdigos de retorno.

9.2.

REGISTRANDO LAS PUNTUACIONES

37

9.2. Registrando las puntuaciones


En este apartado vamos a hacer que se mantenga un registro actualizado de las puntuaciones ms altas. Para ello tras cada partida se va a ir actualizando un chero binario con las puntuaciones. En primer lugar crear una marco que indique el tamao mximo del registro de puntuaciones (5) y otra con el nombre del chero de puntuaciones. De esta forma usaremos las macros en las distintas funciones en lugar de repetir continuamente los valores, con lo que evitamos redundancia.

Funcin

SalvaPuntuaciones Jugador

Toma coma parmetro un puntero a un array de datos de tipo que contiene todas las puntuaciones.

Abre un chero de puntuaciones en modo de escritura binario truncando el chero si ya exista o creando uno nuevo en caso de que no. Guarda las puntuaciones hasta llegar a una con 0 puntos o hasta alcanzar el mximo de registros indicado en la macro correspondiente. Cierra el chero.

Funcin

CargaPuntuaciones Jugador

Toma como parmetro un puntero a un array de datos de tipo

previamente reservado y donde se almacenarn las puntuaciones. Abre el chero de puntuaciones en modo de lectura binario. Si el chero no existe, inicializar a 0 el campo de puntos del primer elemento del array. Esto servir para identicar cundo parar de leer los registros de puntuaciones.

Lee las puntuaciones del chero hasta acabar el chero o hasta llegar al mximo de registros permitidos. En caso de que se haya acabado el chero sin llegar al mximo de registros, habr que inicializar a 0 el campo de puntos del elemento del array siguiente al ltimo vlido, de esta forma no se considerar ese elemento ni los siguientes.

Cierra el chero.

Funcin

ActualizaPuntuaciones Jugador que repre-

Toma como parmetros un puntero a un dato de tipo

senta al jugador actual y otro puntero al array de puntuaciones. Se inserta la puntuacin actual en la posicin correspondiente. Para ello:

Si el jugador tiene 0 puntos la funcin termina sin hacer nada ms ya que no se van a registrar puntuaciones nulas. Precisamente el 0 lo utilizamos para indicar que ese elemento del array y los siguientes no contienen valores vlidos de puntuaciones.

38

PRCTICA 9.

FICHEROS BINARIOS

Si el jugador tiene una puntuacin no nula, se busca la posicin en la que ira en la tabla de puntuaciones, estando en primer lugar las puntuaciones mayores y en ltimo las menores. Si la puntuacin es menor que las de la tabla, se podr insertar la ltima siempre y cuando queden huecos libres en la tabla para llegar al mximo de registros indicados en la macro. Al insertar la puntuacin actual en un punto intermedio se debe tener en cuenta que habr que desplazar las puntuaciones menores ya existentes en la tabla descartando la ltima en caso necesario.

Funcin

VisualizaPuntuaciones

Toma como parmetro un puntero a las puntuaciones. Recorre el array de puntuaciones y las visualiza en ese orden indicando el nombre del jugador y su puntuacin.

Funcin

Terminar

Hay que actualizar esta funcin para que antes de salir del juego actualice el registro de puntuaciones y muestre el resultado. Para ello llamar a las nuevas funciones que hemos creado:

CargaPuntuaciones, ActualizaPuntuaciones, SalvaPuntuaciones y nalmente VisualizaPuntuaciones.


A continuacin se muestra un ejemplo de la salida del programa:

Bienvenido a "Hundir la Flota"! 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ A| | 0| | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ B| | | | | | 5| | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ C| | | | | | 5| | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ D| | | | | | 5| | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ E| | | | | | 5| | | | | 4| | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ F| | | | | | 5| | | | | | 4| | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ G| | | | | | | | | | | | | 4| | | | | | |

9.2.

REGISTRANDO LAS PUNTUACIONES

39

|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ H| | | | | | | | | | | | | | 4| | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ I| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ J| | | | | | | | | | | | | | | | | | | | Fallaste!!, te quedan 0 vidas. Puntuacin de Gorka: 9 --- Game Over --Puntuaciones: Gorka 9 aaa 6 Gorka 5

40

PRCTICA 9.

FICHEROS BINARIOS

Prctica 10 Ficheros de texto


Mediante los cheros de texto podemos almacenar informacin en un formato directamente legible por una persona. En esta prctica los vamos a emplear para permitir cargar pantallas diseadas con un editor de texto externo cualquiera.

10.1. Creando la pantalla


Mediante un editor de textos generar un chero formado por nmeros agrupados en las y columnas segn el tamao del tablero de juego, y separados por espacios en blanco. A continuacin se muestra un ejemplo de chero:

0 0 0 0 0 0 0 0 0 3

0 0 0 0 0 0 0 0 0 3

0 0 0 0 0 0 0 0 0 3

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 4 4 4 4 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 2 0

0 0 0 0 0 0 0 0 2 0

1 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 5 0 0 0 0 0 0 0

0 0 0 5 0 0 0 0 0 0

0 0 0 0 5 0 0 0 0 0

0 0 0 0 0 5 0 0 0 0

0 0 0 0 0 0 5 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

se usa un procesador de textos como OpenOce, asegurarse de guardar el chero en formato TXT y no ODT
41

1 Si

42

PRCTICA 10.

FICHEROS DE TEXTO

10.2. Cargando la pantalla


Ahora vamos a dar la opcin de que, si el usuario le pasa un parmetro al programa, ste lo interprete como el nombre de un chero que contiene la pantalla a cargar. Si el programa se invoca sin parmetros, seguir funcionando como hasta ahora.

Funcin

CargaPantalla

Toma como parmetros un puntero al array bidimensional con la posicin de los barcos y una cadena de caracteres con el nombre del chero que contiene la pantalla.

Como valor de retorno devuelve 1 si todo ha ido bien y 0 si ha ocurrido algn fallo. Abre el chero indicado en modo lectura de texto. Deber informar en caso de fallo y devolver el cdigo de error correspondiente. Va rellenando el array con las posiciones de los barcos con los nmeros contenidos en el chero. Cierra el chero y muestra un mensaje por pantalla indicando que se ha cargado una nueva pantalla y el nombre del chero correspondiente.

Funcin

Iniciar

Ahora toma como parmetro adicional el nombre del chero a cargar. Si se est retomando una partida pendiente o si el parmetro con el nombre del chero es

NULL,

no carga la nueva pantalla.

En caso de que se haya indicado un nombre de chero vlido, llamar a la funcin

CargaPantalla

pasndole los parmetros correspondientes.

Funcin

main

Ahora deber consultar los parmetros que se le pasen, para ello habr que actualizar su prototipo de forma adecuada. Cuando llame a

que ha recibido como primer parmetro o hayan pasado parmetros.

Iniciar, tendr que indicarle como nombre de chero el NULL en caso de que no se le

Ejemplo de partida
Hemos acabado la aplicacin!. Ahora puedes jugar unas partidas e intercambiar pantallas con tus compaeros o, mejor an, seguir aadiendo nuevas funcionalidades al juego ;)

Ejecutamos el juego indicando que cargue una pantalla externa del chero

demo.txt:

$ ./juego demo.txt Pantalla "demo.txt" cargada Dime tu nombre: Gorka Bienvenido a "Hundir la Flota"! 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ A| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ B| | | | | | 0| | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ C| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ D| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ E| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ F| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ G| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ H| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ I| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ J| 3| 3| 3| | | | | | | | | | | | | | | | | Fallaste!!, te quedan 4 vidas.

43

44

EJEMPLO DE PARTIDA

Introduce una coordenada (ej. B12) : z0 Puntuacin de Gorka: 3 --- Aplicacin finalizada a peticin del usuario --Deseas guardar la partida para recuperarla ms adelante? (s/n): s Guardando partida ... ok!
Y ahora volvemos a ejecutar el juego para que retome la partida en la que estbamos:

./juego Cargando partida previa ... ok! Bienvenido a "Hundir la Flota"! 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ A| | | | | | | | | | | 1| | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ B| | | | | | | | | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ C| | | | | | | | | | | | | | 5| | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ D| | | | 0| | | | | | | | | | | 5| | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ E| | | | | | | 4| | | | | | | | | 5| | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ F| | | | | | | 4| | | | | | | | | | 5| 0| | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ G| | | | | | | 4| | | | | | | | | | | 5| | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ H| | | | | | | 4| | | | | | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ I| | | | | | | | | 2| 2| 0| | | | | | | | | |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__ J| 3| 3| 3| | | | | | | | | | | | | | | | | Tocado!!, vas 15 puntos. Puntuacin de Gorka: 15 Enhorabuena, juego superado!!! Puntuaciones:

45

Gorka aaa Gork

15 3 3

Você também pode gostar