Escolar Documentos
Profissional Documentos
Cultura Documentos
Fundamentos de Programacin:
Prcticas de C
ii
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/
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.
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
Primer programa
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1 4 5 5
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
7 8 8
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
2. Sentencias Selectivas
11
Procesando la entrada del usuario . . . . . . . . . . . . . . . . . . . . Validando la entrada del usuario . . . . . . . . . . . . . . . . . . . . . Finalizando el juego . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11 11 12
3. Sentencias Repetitivas
13
3.1. 3.2.
13 15
4. Funciones
17
4.1. 4.2.
17 18
vi
NDICE GENERAL
4.3.
El primer barco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
5. Arrays Unidimensionales
21
5.1. 5.2.
21 22
6. Arrays Bidimensionales
25
6.1. 6.2.
. . . . . . . . . . . . . . . . . .
25 27
Flota hundida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7. Cadenas de Caracteres
29
7.1. 7.2.
29 30
8. Estructuras
31
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
31 32 32
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9. Ficheros binarios
35
9.1. 9.2.
35 37
10.Ficheros de texto
41
41 42
Ejemplo de partida
43
1. Cuando se nos abra la ventana con ttulo est dando la opcin de elegir lo que meteremos en un
workspace
de la siguiente forma:
workspace
siguiente:
/home/user1/workspace/Iker/0
En caso de querer entrar a un
workspace
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.
PRCTICA 0.
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:
Next
para seguir.
Finish
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
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.
__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
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
ha tenido el compilador han producido slo es recomendable que no haya no funcionar correctamente.
warning,
se habr creado un
warnings
Problems
es un
warning
una lnea vaca . . . As que tendremos programa para ejecutar! 2. Iremos al men
Run->Run... Run.
Haremos doble click sobre la lnea
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
0.3.
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.
Problems
printf
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
Debug haremos lo mismo que hacemos en Run para ejecutar. Despus, para comenzar la depuracin, pulsaremos el botn Debug.
PRCTICA 0.
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
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
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
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
int
PRCTICA 1.
Otra de tipo
char
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
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.
char int
A continuacin mostrar un mensaje de texto pidiendo al usuario que introduzca la coordenada. Por ejemplo:
1.3.
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.
10
PRCTICA 1.
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.
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.
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.
Mediante un bucle
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
A B
13
14
PRCTICA 3.
SENTENCIAS REPETITIV AS
C
El resultado nal debera ser algo similar a lo mostrado a continuacin:
5 6
9 10 11 12 13 14 15 16 17 18 19
for
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.
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.
salir
de tipo
char
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
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
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
Funcin
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
char
que
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.
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
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.
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.
20
PRCTICA 4.
FUNCIONES
Funcin
CreaFlota char
y otro 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.
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
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
CreaFlota
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.
CompruebaTiro
para que le
pase los arrays con las posiciones de los barcos y el nmero de elementos
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.
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
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
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
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,
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.
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
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!!!
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
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.
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.
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.
Funcin
IniciaJugador PideNombre
de la prctica anterior.
Reemplaza a la funcin
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.
8.3.
BARCO
33
A continuacin tiene un campo de tipo que est el barco. Este campo valdr
'V'
'D'
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.
Recorre este array mediante un bucle llamando a la funcin de forma adecuada para que dibuje los tres barcos.
DibujaBarco
34
PRCTICA 8.
ESTRUCTURAS
Funcin
SalvaPartida
(usamos el puntero por eciencia en el paso de parmetros), un
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
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.
Jugador,
35
36
PRCTICA 9.
FICHEROS BINARIOS
int
que valdr 0 en
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.
Jugador
puntero al array de barcos y otro puntero al array de tiros. Comprueba las tres posibilidades de nalizacin del juego (juego superado,
game over
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.
Jugador,
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
Detener
9.2.
37
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
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
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:
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.
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
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
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,
CargaPantalla
Funcin
main
Ahora deber consultar los parmetros que se le pasen, para ello habr que actualizar su prototipo de forma adecuada. Cuando llame a
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
15 3 3