Documente Academic
Documente Profesional
Documente Cultură
PR
NDICE
Cdigo .................................................................................................................... 2
buscaminas.h ............................................................................................... 2
buscaminas.c ............................................................................................... 3
int Segundos () ................................................................................ 3
void MostrarTablero (int modo) ..................................................... 3
void DestaparAnexas (int pos_x,int pos_y) .................................... 4
void Partida (int modo) ................................................................... 5
void CalcularMinas () ..................................................................... 8
void GenerarMinas () ...................................................................... 8
void ElegirTamano () ...................................................................... 9
void menu () ................................................................................... 10
void intro_1 () ........................................................................ 11
void intro_2 () ................................................................................ 11
void main () .................................................................................... 11
ficheros.c 12
void AnadirEnOrden (struct datos user, int modo) 12
void CargarResultados (int modo) ................................................. 12
void GrabarResultados (int modo) ................................................. 12
void MostrarResultados (int modo) ............................................... 13
void GuardarResultado (int tiempo, int modo) .............................. 13
void IntroducirContrasena (char **contrasena) ............................. 14
void GuardarPartida (int x, int y, int minas, int destapadas,
int banderas, int pos_x,
int pos_y, int seg, int modo_juego,
struct casilla **tablero) ............................... 14
void CargarPartida (int *x, int *y, int *minas, int *destapadas,
int *banderas, int *pos_x,
int *pos_y, int *seg, int *modo_juego,
struct casilla ***tablero) ............................. 15
Instrucciones .......................................................................................................... 17
Compilacin ........................................................................................................... 18
Acerca de Buscaminas Pro .................................................................................... 19
CDIGO
/*
buscaminas.h
declaracin de tipos
*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <string.h>
typedef enum{oculto, /* si la casilla no ha sido destapada */
visible,
/* si la casilla ha sido destapada */
mina,
/* si la casilla est marcada como mina */
dudoso} est;
/* si la casilla est marcada como dudosa */
struct casilla
{
char sel; /* es '>' si el cursor est en la casilla */
int ady; /* nmero de minas adyacentes, 9 si es una mina */
est estado;
};
/*
buscaminas.c
EPS - USP CEU
Ingeniera Informtica
Prctica 3 MPI: Buscaminas
Alumno: Bartolom Molina Menchn
Profesor: Dr. D. David Losada Carril
Curso: 2001/2002
Fecha: 15/4/2002
NOTA: este programa ha sido compilado con Microsoft Visual C++ 6.0 y contiene
funciones que no estn definidas en el ANSI C, por lo tanto es posible que
no sea compatible con muchos compiladores
*/
#include "buscaminas.h"
struct casilla **tablero;
int x,
/* prototipos de funciones */
void GenerarMinas ();
void menu ();
void main ();
/* protoripos de funciones definidas en ficheros.c */
void GuardarResultado (int, int);
void GuardarPartida (int, int, int, int, int, int, int, int, int, struct casilla **);
void CargarPartida (int *, int *, int *, int *, int *, int *, int *, int *, int *, struct casilla ***);
void MostrarResultados (int);
/* devuelve los segundos del reloj */
int Segundos ()
{
struct tm *tiempo;
time_t t;
time (&t);
tiempo = localtime(&t);
return tiempo->tm_sec;
}
/* muestra el tablero del juego por pantalla segn el modo:
0: modo normal
1: todas las casillas visibles (cuando se pierde)
2: todas las casillas tapadas (cuando el juego est en pausa) */
void MostrarTablero (int modo)
{
int ancho,
alto;
printf ("PR%c\n\n ",1);
/* imprime el eje de coordenadas x */
for (ancho=0; ancho<x; ancho++)
printf ("%3d",ancho);
printf ("\n ");
/* imprime lneas debajo del eje de coordenadas x */
for (ancho=0; ancho<x*3; ancho++)
printf ("%c",95);
/* imprime la primera lnea vertical del eje de coordenadas y */
banderas--;
/* si la casilla tampoco tiene adyacentes se hace una llamada
recursiva */
if (tablero[pos_x+i][pos_y+j].ady == 0)
DestaparAnexas (pos_x+i,pos_y+j);
tablero[pos_x+i][pos_y+j].estado = visible;
destapadas++;
}
}
/* gestiona la partida segun el modo:
0: modo normal
1: cuando se pierde
2: cuando el juego est en pausa */
void Partida (int modo)
{
int tiempo = Segundos (); /* decide cuando hay que cambiar los segundos */
system ("cls");
MostrarTablero (modo);
/* si se han destapado todas las casillas sin minas (cuando se gana) */
if (destapadas == (x*y)-minas)
{
printf ("\nHas ganado!!!\n");
printf ("\n1.. Volver a jugar");
printf ("\n2.. Volver al menu");
/* no se guardan los mejores de modos personalizados */
if (modo_juego)
printf ("\n3.. Guardar resultado");
/* se restauran los datos de la partida */
pos_x = pos_y = 0;
tiempo = seg;
seg = 1;
banderas = 0;
destapadas = 0;
switch (getch ())
{
case '1': /* volver a jugar en el mismo modo */
GenerarMinas ();
case '2':
case '3':
/* guardar el resultado */
/* no se guardan los mejores de modos personalizados */
if (modo_juego)
GuardarResultado (tiempo, modo_juego);
default:
Partida (0);
}
}
/* si se ha destapado alguna casilla con mina (se ha perdido) */
if (modo == 1)
{
printf ("\nHas perdido\n");
printf ("\n1.. Menu principal");
printf ("\n2.. Volver a intentarlo");
/* se restauran los datos de la partida */
pos_x = pos_y = 0;
seg = 1;
banderas = 0;
destapadas = 0;
switch (getch ())
{
case '1': /* volver al men principal */
menu ();
case '2':
default:
Partida (1);
}
}
/* si el juego est en pausa */
if (modo == 2)
{
printf ("\nPulsa una tecla para continuar la partida");
getch ();
Partida (0);
}
printf ("\nEnter:destapar m:mina d:dudosa o:desmarcar p:pausa g:guardar r:retirarse\n");
/* imprime el nmero de banderas restantes y el tiempo acumulado */
printf ("banderas restantes: %d\n", minas-banderas);
printf ("segundos:%4d",seg);
/* mientras no se pulse una tecla, seg se incrementa cada segundo */
while (!kbhit ())
{
if (tiempo != Segundos ())
{
printf ("\rsegundos:%4d",seg++);
tiempo = Segundos ();
}
}
switch (tolower (getch ()))
{
case 224: /* si se ha pulsado una tecla del cursor */
switch (getch ())
{
case 72: /* flecha arriba */
if (pos_y-1 >= 0)
{
tablero[pos_x][pos_y].sel = ' ';
pos_y = pos_y-1;
tablero[pos_x][pos_y].sel = '>';
}
Partida (0);
case 80:
/* flecha abajo */
if (pos_y+1 < y)
{
tablero[pos_x][pos_y].sel = ' ';
pos_y = pos_y+1;
tablero[pos_x][pos_y].sel = '>';
}
Partida (0);
case 75:
/* flecha izquierda */
if (pos_x-1 >= 0)
{
tablero[pos_x][pos_y].sel = ' ';
pos_x = pos_x-1;
tablero[pos_x][pos_y].sel = '>';
}
Partida (0);
case 77:
/* flecha derecha */
if (pos_x+1 < x)
{
tablero[pos_x][pos_y].sel = ' ';
pos_x = pos_x+1;
tablero[pos_x][pos_y].sel = '>';
}
Partida (0);
case 13:
case 'm':
case 'd':
case 'o':
case 'p':
case 'g':
case 'r':
menu ();
default:
printf ("\nOpcion incorrecta, pulse enter para elegir una opcion");
getch ();
Partida (0);
}
}
/* calcula de cada casilla las minas que tiene alrededor y guarda el valor en
tablero[ancho][alto].ady; guarda un 9 si la casilla contiene una mina y un 0
si no tiene minas adyacentes */
void CalcularMinas ()
{
int alto,
ancho,
i,
j;
/* recorre las columnas del tablero */
for (ancho=0; ancho<x; ancho++)
/* recorre las filas del tablero para cada columna */
for (alto=0; alto<y; alto++)
/* calcula las casillas adyacentes con mina */
for (i=-1; i<2; i++)
for (j=-1; j<2; j++)
if (tablero[ancho][alto].ady != 9)
if
(((ancho+i>=0)&&(ancho+i<x))&&((alto+j>=0)&&(alto+j<y)))
if (tablero[ancho+i][alto+j].ady == 9)
tablero[ancho][alto].ady++;
Partida (0);
}
/* genera las minas de forma aleatoria */
void GenerarMinas ()
{
int ancho,
alto,
minas_aux;
minas_aux = minas;
/* reserva memoria para el tablero */
tablero = (struct casilla **)malloc(x*sizeof (struct casilla *));
for (ancho=0; ancho<x; ancho++)
tablero[ancho] = (struct casilla *)malloc(y*sizeof (struct casilla));
/* se inicializa el generador de nmeros aleatorios */
srand(time(NULL));
/* se recorre el tablero */
for (ancho=0; ancho<x; ancho++)
{
for (alto=0; alto<y; alto++)
/* si hay o se va a poner una mina en la casilla */
if (((minas_aux)&&(rand()%20 == 0))||(tablero[ancho][alto].ady == 9))
{
if (tablero[ancho][alto].ady != 9)
minas_aux--;
tablero[ancho][alto].ady = 9;
}
/* si la casilla no tiene mina */
else
tablero[ancho][alto].ady = 0;
/* si se ha recorrido toda la tabla y todava no se han colocado todas las
minas, se vuelve a recorrer el tablero */
if ((ancho == x-1)&&(minas_aux))
ancho = -1;
}
/* se quita el cursor de todas las casillas */
for (ancho=0; ancho<x; ancho++)
/* modo intermedio */
x = 16;
y = 16;
minas = 40;
modo_juego = 2;
GenerarMinas ();
case '3':
/* modo experto */
x = 25;
y = 16;
minas = 99;
modo_juego = 3;
GenerarMinas ();
case '4':
/* modo personalizado */
system ("cls");
modo_juego = 0;
printf ("Introduzca la anchura del tablero (2-25): ");
scanf (" %d",&x);
/* comprueba la anchura del tablero */
if ((x > 25)||(x < 2))
{
printf ("\n\nla anchura del tablero no puede ser mayor de 30 ni menor de 2"
", pulse enter para continuar");
getch ();
ElegirTamano ();
}
printf ("\nIntroduzca la altura del tablero (2-22): ");
scanf (" %d",&y);
/* comprueba la altura del tablero */
if ((y > 22)||(y < 2))
{
printf ("\n\nla altura del tablero no puede ser mayor de 22 ni menor de 2"
", pulse enter para continuar");
getch ();
ElegirTamano ();
}
/* volver al men */
menu ();
default:
printf ("\nOpcion incorrecta, pulse enter para elegir una opcion");
getch ();
ElegirTamano ();
}
}
/* imprime un men por pantalla con las opciones del juego */
void menu ()
{
system ("cls");
printf ("\t\t**** BUSCAMINAS PRO ****");
printf ("\n\nSeleccione una opcion:\n");
printf ("\n1.. Nueva partida");
printf ("\n2.. Cargar Partida");
printf ("\n3.. Los mejores modo principiante");
printf ("\n4.. Los mejores modo intermedio");
printf ("\n5.. Los mejores entre los mejores (modo experto)");
printf ("\n6.. Mostrar creditos");
printf ("\n0.. Salir");
switch (getch ())
{
case '1': /* nueva partida */
system ("cls");
ElegirTamano ();
break;
case '2':
/* cargar partida */
CargarPartida (&x, &y, &minas, &destapadas, &banderas, &pos_x, &pos_y, &seg, &modo_juego, &tablero);
case '3':
/* top principiantes */
MostrarResultados (1);
case '4':
/* top intermedio */
MostrarResultados (2);
case '5':
/* top expertos */
MostrarResultados (3);
case '6':
/* mostrar crditos */
system ("cls");
main ();
case '0':
default:
printf ("\nOpcion incorrecta, pulse enter para elegir una opcion");
getch ();
menu ();
}
}
10
11
/*
ficheros.c
contiene las funciones relacionadas con el manejo de ficheros del juego
*/
#include "buscaminas.h"
/* estructura que contiene los datos de un usuario ganador */
struct datos
{
char nombre[100];
int tiempo;
}usuario [10];
/* protoripos de funciones definidas en buscaminas.c */
void menu ();
void Partida (int);
/* introduce un usuario en su puesto si su tiempo es de los 10 mejores */
void AnadirEnOrden (struct datos user, int modo)
{
struct datos usr_aux;
int i;
for (i=0; i<10; i++)
{
if (user.tiempo < usuario[i].tiempo)
{
usr_aux = usuario[i];
usuario[i] = user;
AnadirEnOrden (usr_aux, modo);
break;
}
/* si todava no hay 10 mejores, el usuario se mete entre los mejores */
if (usuario[i].tiempo == 0)
{
usuario[i] = user;
break;
}
}
}
/* carga el array "resultados" (10 mejores) con los datos de un fichero de texto */
void CargarResultados (int modo)
{
int i = 0;
FILE *resultados;
if (modo == 1)
/* modo principiante */
resultados = fopen ("principiante.top","a+");
if (modo == 2)
/* modo intermedio */
resultados = fopen ("intermedio.top","a+");
if (modo ==3)
/* modo experto */
resultados = fopen ("experto.top","a+");
while (!feof (resultados))
{
fread (&usuario[i], sizeof (struct datos), 1, resultados);
i++;
}
fclose (resultados);
}
/* graba el array "resultados" (10 mejores) en un fichero de texto */
void GrabarResultados (int modo)
{
int i;
FILE *resultados;
if (modo == 1)
/* modo principiante */
resultados = fopen ("principiante.top","w");
12
if (modo == 2)
/* modo intermedio */
resultados = fopen ("intermedio.top","w");
if (modo ==3)
/* modo experto */
resultados = fopen ("experto.top","w");
for (i=0; i<10,usuario[i].tiempo; i++)
fwrite (&usuario[i], sizeof (struct datos), 1, resultados);
fclose (resultados);
}
/* lee los mejores resultados de un fichero y los imprime por pantalla */
void MostrarResultados (int modo)
{
int posicion = 1;
/* posicin en el ranking */
struct datos user;
/* datos del usuario */
FILE *resultados;
system ("cls");
if (modo == 1)
/* modo principiante */
{
resultados = fopen ("principiante.top","r");
printf ("\t**** Los mejores principiantes ****\n\n");
}
if (modo == 2)
/* modo intermedio */
{
resultados = fopen ("intermedio.top","r");
printf ("\t**** Los mejores intermedios ****\n\n");
}
if (modo ==3)
/* modo experto */
{
resultados = fopen ("experto.top","r");
printf ("\t**** Los mejores entre los mejores ****\n\n");
}
/* si no ha podido abrir el archivo es que todava no se ha creado (todava no
se han guardado resultados en ese modo) */
if (!resultados)
printf ("Todavia no hay ningun resultado introducido");
else
{
while (!feof (resultados))
{
fread (&user, sizeof (struct datos), 1, resultados);
/* si no se ha llegado al final del fichero */
if (user.tiempo)
printf ("%d -> %s : %d segundos\n\n",posicion++,user.nombre,user.tiempo);
user.tiempo = 0;
}
fclose (resultados);
}
printf ("\n\nPulse una tecla para volver al menu");
getch ();
menu ();
}
/* introduce un usuario ganador en el ranking si su tiempo est entre los 10 mejores */
void GuardarResultado (int tiempo, int modo)
{
int i;
struct datos user;
/* datos del usuario ganador */
/* se inicializa el tiempo de los mejores a 0 (eso querr decir que todava no hay
un usuario introducido en esa posicin del ranking */
for (i=0; i<10; i++)
usuario [i].tiempo = 0;
13
system ("cls");
fflush (stdin);
printf ("Introduce tu nombre: ");
gets (user.nombre);
user.tiempo = tiempo;
CargarResultados (modo);
AnadirEnOrden (user, modo);
GrabarResultados (modo);
MostrarResultados (modo);
}
/* permite al usuario introducir un campo de tipo contrasea (con asteriscos) */
void IntroducirContrasena (char **contrasena)
{
int i;
char c;
/* se introducen caracteres en la cadena mientras no se pulse Enter */
for (c=getch (),i=0; c!=13; c=getch (),i++)
{
/* si se pulsa el caracter 8 (borrar caracter) */
if (c == 8)
{
if (i != 0)
{
printf ("%c%c%c",8,' ',8);
i--;
}
i--;
continue;
}
/* reserva memoria segn van introducindose caracteres */
*contrasena = (char *)realloc(*contrasena, (i+1)*sizeof (char));
/* se guarda el caracter en la cadena */
(*contrasena)[i] = c;
/* se imprime un asterisco cada vez que se introduce un caracter */
printf ("*");
}
/* se guarda espacio para introducir el caracter fin de cadena */
*contrasena = (char *)realloc(*contrasena, (i+1)*sizeof (char)+1);
/* se introduce el caracter fin de cadena */
(*contrasena)[i] = 0;
}
/* guarda los datos de una partida para poder recuperarla en el futuro */
void GuardarPartida (int x,
/* nmero de columnas del tablero */
int y,
/* nmero de filas del tablero */
int minas, /* nmero de minas */
int destapadas,
/* nmero de casillas destapadas */
int banderas,
/* banderas (posibles minas) puestas */
int pos_x, /* componente x del cursor */
int pos_y, /* componente y del cursor */
int seg, /* tiempo acumulado en segundos */
int modo_juego,
/* 1.- principiante 2.- intermedio 3.- experto
0.- personalizado */
struct casilla **tablero)
{
int i,
j,
tam_contra;
/* tamao de la contrasea asociada al archivo */
char
nombre_archivo[50], /* nombre de la partida a guardar */
*contrasena;
/* contrasea asociada al archivo */
FILE *archivo;
system ("cls");
fflush (stdin);
printf ("Introduzca un nombre de usuario: ");
gets (nombre_archivo);
/* nombre del archivo donde se guardar la partida */
14
15
16
INSTRUCCIONES
El objetivo del juego es destapar todas las casillas que no contengan una mina en el
menor tiempo posible.
Una casilla no destapada se simboliza mediante un cuadrado negro.
Una casilla con una mina se simboliza mediante una mina.
Una casilla marcada como mina se simboliza mediante un rombo (bandera).
Una casilla marcada como dudosa se simboliza mediante un signo de interrogacin ?.
Una casilla destapada y que no tiene minas adyacentes se simboliza mediante un
cuadrado gris.
El nmero que aparece en una casilla cuando se destapa indica el nmero de minas que
hay en las casillas adyacentes.
Si se destapa una casilla con mina, se pierde el juego.
El carcter > es el cursor, que indica la casilla activa sobre la que se va a operar.
Controles:
ENTER
Destapar casilla
m
d
o
p
g
r
17
COMPILACIN
Se recomienda usar el compilador Microsoft Visual C++, ya que hay varias funciones
que no estn definidas en el ANSI C, como rand o system.
Incluir los archivos buscaminas.c (que contiene las funciones generales del juego),
archivos.c (que contiene las funciones relacionadas con el manejo de archivos), y
buscaminas.h (que contiene la declaracin de tipos) en un proyecto.
18
19