Integrantes:
Sergio Sepúlveda
Sthefany Blanco
Juan Franco
BUSCAMINAS
sus funciones y características son:
Destapar minas
Verificar cuantas minas hay alrededor de una casilla
Colocar Banderas
Despejar las casillas vacías del tablero hasta encontrar una mina
El juego maneja un temporizador
El juego reproduce sonidos cuando se gana el juego, cuando se pierde, cuando
destapa una mina y cuando coloca una bandera
El juego cuenta con imágenes que indican el estado de la partida
Diseño de la interfaz
Esto es lo que ve el usuario al iniciar el programa:
Cuando el usuario da click al botón iniciar, se muestra el tablero de
juego y el tiempo empieza a correr:
Cuando el usuario da click en un boton del tablero (y este no es una mina) esta
se pondrá de color gris y muestra un número indicando cuantas minas hay
alrededor
o si la casilla es vacía el programa buscará
las casillas vacías a su alrededor hasta encontrar una mina
si es una mina el tablero se destapará por completo,
revelando donde estaban las minas, la nave explotará, el temporizador se
detendrá y el programa arroja un mensaje diciéndole al usuario que ha
perdido y preguntándole si quiere reiniciar el juego o salir
Si el usuario quiere colocar una bandera, deberá marcar
la opcion de "Colocar Banderas" en la parte inferior de la venata y
hacer click en el tablero, al hacer click la casilla se pintará de color azul y
el indicador de banderas aumentará en 1
El usuario ganará el juego cuando marque como banderas
todas las casillas que sean minas, pero si marca 50 banderas y estas no
corresponden con las minas, el programa mostrará un mensaje al usuario
diciendole que puso mal las banderas y que lo intente otra vez
Si el usuario intenta poner una bandera en una casilla
que ya destapó el programa enviará un mensaje diciendo que poner una bandera
ahi no es necesario
Y si el usuario intenta destapar una casilla en la que
hay una bandera, el programa enviará un mensaje diciendo que debe retirarla
Código:
Variables globales:
///La variable mapa es un arreglo en donde se
guardarán las minas que se asignen aleatoriamete
int[] mapa = new int[352];
///la variable espacio es
una matriz que representa el tablero de juego la cual consta de 22 columnas y
16 filas (352 botones en total)
int[,] espacio = new
int[22,16];
/// la variable
casilas_vacias es un arreglo que contiene números correspondientes a los id de
los botones nulos del juego
int[] casillas_vacias = new
int[]
{1,2,3,4,7,8,9,10,11,12,13,14,15,16,19,20,21,22,
23,24,25,26,29,30,31,32,33,34,35,36,37,38,41,42,43,44,
45,46,47,48,49,50,53,54,55,56,57,58,61,62,63,64,65,66,
67,68,69,70,71,72,75,76,77,78,79,80,83,84,85,86,87,88,
89,90,91,92,107,108,109,110,
111,112,113,114,129,130,131,132,
133,134,139,140,147,148,153,154,
155,156,161,162,169,170,175,176,
223,224,239,240,
245,246,261,262,
267,268,271,272,273,274,275,276,277,278,279,280,283,284,
289,290,293,294,295,296,297,298,299,300,301,302,305,306,
309,310,311,312,313,314,319,320,325,326,327,328,329,330,
331,332,333,334,335,336,341,342,347,348,349,350,351,352};
/// La variable
casillas_minas es un arreglo que albergará numeros correspondientes a los
botones que serán asignados como minas
int[] casillas_minas = new int[50];
/// La variable banderas es un arreglo que contiene
números correspondientes a los botones a los que se le han puesto una bandera
int[] banderas = new
int[50];
/// La variable
contador_banderas tiene el conteo de las banderas que se han puesto, este
aumentara hasta 50
int contador_banderas = 0;
/// Estas variables de
tipo entero se usan en el método del timer para contar minutos y segundos
int segundos = 0;
int minutos = 0;
Método manejador de eventos del botón iniciar, este
invoca el método cargar e iguala las variables contador_banderas, minutos y
segundos a 0
private void BotonIniciar_Click(object sender, EventArgs e)
{
/// Instancia del metodo cargar
cargar();
/// Linea de codigo que esconde el
boton iniciar y muestra el tablero de juego
BotonIniciar.Hide();
/// Linea de codigo que inicia el
temporizador
timer1.Enabled = true;
/// Al dar click en el boton
iniciar el temporizador se inicia en 0 asi como el contador de banderas
segundos = 0;
minutos = 0;
contador_banderas = 0;
Tiempomin.Text = "Tiempo:
00";
Tiemposeg.Text = ":00";
cantbanderas.Text = "Banderas
utilizadas: 0/50";
}
Método que inicia el juego cargando las minas dejando un valor de 9 en las
casillas que sean minas y en las casillas que no lo sean busca cuantas minas
tiene alrededor estableciendo un valor de 0 a 8
public void cargar()
{
/// La variable r se usa para
instanciar aleatorios
Random r = new Random();
/// Ciclo for que recorre la matriz
espacio e iguala todos sus valores a 0
for (int i = 1; i <
espacio.GetLength(0); i++)
{
for (int j = 1; j
< espacio.GetLength(1); j++)
{
espacio[i, j] = 0;
}
}
/// Ciclo for que recorre el
arreglo mapa y la matriz espacio dejando todos sus valores en 0 y reestablece
las características predeterminadas de los botones
for (int i = 1; i <
mapa.Length; i++)
{
/// La variable
lista se usa para guardar las coordenadas que retorne el metodo recuperar
coordenadas
List<int>
lista =null;
/// Instancia del
metodo recuperar coordenadas el cual devuelve 2 valores correspondientes a las
coordenadas en la matriz espacio
lista=
recuperarCoordenadas(i);
espacio[lista[1],
lista[0]] = 0;
mapa[i] = 0;
/// Linea de codigo
que busca un boton segun su id y lo guarda en la variable boton
Button boton =
(Button)this.Controls.Find("button" + i, false)[0];
boton.Text =
"" + i;
/// If en donde se
distinguen los botones nulos de los jugables y se "pintan" con su color
correspondiente
if
(casillas_vacias.Contains(i) == true)
{
boton.ForeColor = Color.Black;
boton.BackColor = Color.Black;
}
else
{
boton.ForeColor = Color.Lime;
boton.BackColor = Color.Lime;
}
}
/// Indice que representa la cantidad
de iteraciones del ciclo while el cual aumentará hasta 50 que es la cantidad de
minas en el juego
int indice = 0;
/// Ciclo while que genera un
aleatorio el cual corresponde a unas coordenadas de la matriz espacio donde se
asignará el numero 9 que es igual a una mina
while (indice < 50)
{
/// Variable que
contiene la cantidad de minas que se han puesto
int contador_minas =
0;
/// Variable
aleatoria entre 1 y 352, este numero corresponde a la casilla donde se asignará
la mina
int mina = r.Next(1,
352);
/// Booleano con el
cual se verifica que la variable mina no sea una casilla vacia
bool es_vacia =
casillas_vacias.Contains(mina);
if (es_vacia ==
false)
{
///
Booleano con el que se verifica que la mina no haya sido asignada
bool
es_mina = casillas_minas.Contains(mina);
if
(es_mina == false)
{
/// Lista donde se almacenan las coordenadas donde se aloja la mina
List<int> lista = recuperarCoordenadas(mina);
/// Variables donde se guardan las coordenadas en x y en y de la mina
int y = lista[0];
int x = lista[1];
/// Se asigna el valor 9 (el cual es equivalente a una mina) en las
coordenadas dentro de la matriz espacio y el arreglo mapa
espacio[x,y]=9;
mapa[mina] = 9;
casillas_minas[indice] = mina;
/// Ciclo que recorre la matriz espacio buscando minas, por cada mina
suma 1 al contador
for (int j = 0; j < espacio.GetLength(1); j++)
{
for (int i = 0; i < espacio.GetLength(0); i++)
{
if (espacio[i, j] == 9)
{
contador_minas++;
}
}
}
/// Serie de if´s que suman 1 al valor de las casillas contiguas a la
casilla donde se ubicó la mina
/// Casilla de abajo
if (x + 1 < 22)
if (espacio[x + 1, y] < 9)
espacio[x + 1, y] = espacio[x + 1, y] + 1;
///Casilla de la derecha
if (y + 1 < 16)
if (espacio[x, y + 1] < 9)
espacio[x, y + 1] = espacio[x, y + 1]+1;
/// Casilla de arriba
if (x - 1 >= 0)
if (espacio[x - 1, y] < 9)
espacio[x - 1, y]++;
/// Casilla de la izquierda
if (y - 1 >= 0)
if (espacio[x, y - 1] < 9)
espacio[x, y - 1]++;
/// Casilla diagonal abajo derecha
if (x + 1 < 22 && y + 1 < 16)
if (espacio[x + 1, y + 1] < 9)
espacio[x + 1, y + 1]++;
/// Casilla diagonal abajo-izquierda
if (x + 1 < 22 && y - 1 >= 0)
if (espacio[x + 1, y - 1] < 9)
espacio[x + 1, y - 1]++;
/// Casilla diagonal arriba-izquierda
if (x - 1 >= 0 && y - 1 >= 0)
if (espacio[x - 1, y - 1] < 9)
espacio[x - 1, y - 1]++;
/// Casilla diagonal arriba-derecha
if (x - 1 >= 0 && y + 1 < 16)
if (espacio[x - 1, y + 1] < 9)
espacio[x - 1, y + 1]++;
/// Iguala el contador de minas al indice para que cuando este sea 50 se
salga del ciclo
indice = contador_minas;
}
}
}
}
Método que destapa un botón y averigua si es o no una mina, si es una mina
mostrará el estado de derrota en el juego, si no lo es llamará al método de
descubrir área
public void destaparmina(object sender)
{
/// Linea de codigo que instancia
el metodo SonidoLaser que reproduce el sonido de un laser
SonidoLaser();
try
{
/// Variable que
atrapa el nombre del boton con el cual fue invocado el método
Button b =
(Button)sender;
/// Variable
auxiliar que busca el valor del espacio correspondiente al numero del boton en
el arreglo mapa
int aux =
mapa[Int32.Parse(b.Text)];
/// Lista en donde
se guardan las coordenadas del boton presionado
List<int>
lista = recuperarCoordenadas(int.Parse(b.Text));
/// Variables que
tienen las coordenadas en x y en y del boton
int y = lista[0];
int x = lista[1];
/// If que pregunta
si el boton a destapar es una bandera, si es asi muestra un mensaje diciendole
al usuario que debe quitar la bandera para destapar la mina
if (b.ForeColor ==
Color.Blue)
{
DialogResult dialogResult = MessageBox.Show("Retira la bandera antes de
destapar la casilla", "Destapar casilla", MessageBoxButtons.OK);
}
else
{
///
Booleano que verifica si el boton presionado es una mina
bool
es_mina = false;
if
(aux == 9)
{
es_mina = true;
}
/// Si
el boton presionado es una mina, se destapará todo el tablero indicando las
casillas que eran minas
if
(es_mina == true)
{
/// Variable indice para recorrer la matriz espacio
int indice = 1;
/// Ciclo que recorre la matriz espacio asignando sus valores a cada
boton
for (int j = 0; j < espacio.GetLength(1); j++)
{
for (int i = 0; i < espacio.GetLength(0); i++)
{
/// Linea de codigo que busca un boton segun
su id y lo guarda en la variable boton
Button casilla =
(Button)this.Controls.Find("button" + indice, false)[0];
/// Linea de codigo que asigna al boton un
texto con el valor de la matriz espacio segun sus coordenadas
casilla.Text = "" + espacio[i, j];
indice++;
}
}
/// Ciclo for que recorre el arreglo mapa buscando aquellas casillas que
son minas
for (int i = 1; i < mapa.Length; i++)
{
/// Si el valor del espacio es igual a 9 pintará el botón
de rojo indicando que es una mina
if (mapa[i] == 9)
{
Button bomba = (Button)this.Controls.Find("button"
+ i, false)[0];
bomba.BackColor = Color.Red;
bomba.ForeColor = Color.Red;
}
/// En caso contrario pintará la casilla de color gris
indicando que no es una mina
else
{
Button bomba =
(Button)this.Controls.Find("button" + i, false)[0];
bomba.BackColor = Color.DarkGray;
bomba.ForeColor = Color.Black;
}
}
/// Linea de codigo que detiene el temporizador
timer1.Stop();
/// Lineas de codigo que cambian la imagen de la nave por la de una
explosion
Nave.Hide();
nexpl.Show();
/// Linea de codigo que reproduce el sonido de una explosion
SonidoExplosion();
/// Linea de código que muestra un mensaje diciendo que el juego ha
terminado
DialogResult dialogResult = MessageBox.Show("Perdiste\n ¿Quieres
comenzar de nuevo?", "GameOver", MessageBoxButtons.YesNo);
/// Si el usuario responde que si el juego se reiniciará
if (dialogResult == DialogResult.Yes)
{
/// Linea de codigo que vuelve a mostrar el boton de
inicio
BotonIniciar.Show();
/// Lineas de codigo que reestablecen la imagen de la
nave
nexpl.Hide();
Nave.Show();
}
/// Si el usuario responde que no el juego se cerrará
else if (dialogResult == DialogResult.No)
{
this.Close();
}
}
/// Si
el boton presionado no es una mina, se invocará el método descubrirArea
enviando el id del botón y sus coordenadas
else
{
DescubrirArea(x, y, int.Parse(b.Text));
}
}
}
catch { }
}
Método que descubre todas las casillas vacías cercanas a un botón
presionado en caso de que este sea vacio, si este tiene minas cercanas
escribirá la cantidad correspondiente en el botón
public void DescubrirArea(int x, int y, int i)
{
/// Linea
que busca el botón segun su id y lo guarda en la variable boton
Button boton
= (Button)this.Controls.Find("button" + i, false)[0];
/// Si la
casilla esta tapada
if
(boton.ForeColor == Color.Lime)
{
/// Descubre la casilla
boton.BackColor = Color.DarkGray;
boton.ForeColor = Color.Black;
boton.Text = "" + espacio[x, y];
/// Si no hay minas cercanas
if (espacio[x, y] == 0)
{
/// Ciclo que recorre las casillas cercanas
for (int f2 = Math.Max(0, x - 1); f2 < Math.Min(22, x + 2); f2++)
{
for (int c2 = Math.Max(0, y - 1); c2 < Math.Min(16, y + 2); c2++)
{
/// Invoca el metodo
recuperarNboton que obtiene el número de los botones cercanos al que se
presionó y lo guarda en la variable nboton
int nboton =
recuperarNboton(f2, c2);
/// Incoca recursivamente el
metodo descubrir area para las casillas cercanas
DescubrirArea(f2, c2, nboton);
}
}
}
}
}
Método que coloca la bandera en el botón que se presionó,
luego de colocar la bandera comparará si corresponde con las minas (en caso de
poner todas las banderas correctamente el juego mostrará el estado de victoria,
en caso contrario informará que las banderas fueron colocadas erróneamente) y
si el botón presionado es una bandera, el programa retira la bandera
public
void colocarBandera(object sender)
{
/// Linea de
codigo que reproduce el sonido de un escudo de energia
SonidoEscudo();
try
{
/// Lineas de codigo que recuperan el id del boton sobre el que se puso
la bandera
Button b
= (Button)sender;
int boton =
Int32.Parse(b.Text);
/// Variable que cuenta
la cantidad de banderas que se pusieron correctamente
int aciertos = 0;
/// Booleano que pregunta si el boton presionado ya es una bandera
bool es_bandera = banderas.Contains(boton);
/// If que pregunta si el boton ya ha sido destapado por medio de la
característica ForeColor, si es así mostrará un mensaje diciendo que la bandera
no se puede poner ahi
Button
bandera = (Button)this.Controls.Find("button" + boton, false)[0];
if (bandera.ForeColor ==
Color.Black)
{
DialogResult dialogResult = MessageBox.Show("Ya sabes
que esta casilla no tiene minas\n por lo que una bandera es innecesaria",
"Bandera Innecesaria", MessageBoxButtons.OK);
}
else
/// En caso contrario preguntará si el boton presionado no es una
banderá, si no es bandera colocará la bandera en el boton y si es una bandera
la retirará
{
if (es_bandera == false)
{
/// Pregunta si el usuario ya ha usado todas
las banderas
if (contador_banderas < 50)
{
/// Lineas de codigo que
pintan el boton de azul
bandera.BackColor = Color.Blue;
bandera.ForeColor = Color.Blue;
/// Linea de código que introduce una bandera en el
arreglo de las banderas
banderas[contador_banderas] =
boton;
/// Se suma 1 al contador de
banderas indicando que se colocó una bandera y se muestra al usuario el cambio
en el contador
contador_banderas =
contador_banderas + 1;
this.cantbanderas.Text =
"Banderas utilizadas:" + contador_banderas + "/50";
/// Ciclo for que recorre el
arreglo de banderas preguntando si sus valores corresponden a los de las minas,
si es así le sumará uno a al contador de aciertos
for (int i = 0; i <
banderas.Length; i++)
{
if (casillas_minas.Contains(banderas[i]))
{
aciertos++;
}
}
/// Si la variable aciertos es
igual a 50 quiere decir que el usuario puso todas las banderas correctamente y
que ganó el juego
if (aciertos == 50)
{
/// Lineas de
código que muestran el estado de victoria del juego, se reproduce un sonido de
un marciano muriendo y las imagenes de los marcianos se reemplazan por
explosiones
SonidoMarciano();
timer1.Stop();
Marciano1.Hide();
Marciano2.Hide();
Marciano3.Hide();
mexpl1.Show();
mexpl2.Show();
mexpl3.Show();
///Linea de
código que muestra un mensaje diciendo que el juego ha terminado
DialogResult
dialogResult = MessageBox.Show("Has descubierto todas las minas\n ¿Quieres
comenzar de nuevo?", "GameOver", MessageBoxButtons.YesNo);
///Si el usuario
responde que si el juego se reiniciará
if (dialogResult
== DialogResult.Yes)
{
BotonIniciar.Show();
Marciano1.Show();
Marciano2.Show();
Marciano3.Show();
mexpl1.Hide();
mexpl2.Hide();
mexpl3.Hide();
}
///Si el usuario
responde que no el juego se cerrará
else if (dialogResult ==
DialogResult.No)
{
this.Close();
}
}
}
/// Si los aciertos no son 50 y el usuario
puso todas las banderas, el programa enviará un mensaje informandole que puso
las banderas incorrectamente
else
{
DialogResult dialogResult =
MessageBox.Show("Has puesto todas las banderas, pero estas no coinciden
con las minas\n inténtalo de nuevo", "Intenta otra vez",
MessageBoxButtons.OK);
}
}
/// Si el usuario presionó un botón que ya es una bandera,
el programa procederá a quitar la bandera del boton
else
{
/// Lineas de código que devuelven el botón
a su estado original
bandera.BackColor = Color.Lime;
bandera.ForeColor = Color.Lime;
/// El contador de banderas se reduce en 1,
indicando que la bandera fue retirada
contador_banderas = contador_banderas - 1;
/// Variable de tipo int que indica la
pocisión en el arreglo de banderas
int pocision = 0;
/// Ciclo for que busca la pocisión en el
arreglo de las banderas
for (int i = 0; i < banderas.Length;
i++)
{
if(banderas[i]==boton)
{
pocision = i;
}
}
/// Se deja el valor de la pocisión
encontrada en 0
banderas[pocision] = 0;
/// Se muestra al usuario que retiró una
bandera
this.cantbanderas.Text = "Banderas
utilizadas:" + contador_banderas + "/50";
}
}
}
catch { }
}
Método que recupera las coordenadas de un botón según su
id (este método fue necesario para poder manejar el botón dentro de una matriz)
private List<int> recuperarCoordenadas(int
num)
{
/// Variable
que actua de contador para limitar hasta donde se sumarán los indices i y j de
la matriz espacio
int pos = 0;
/// Lista
donde se guardará el resultado de la búsqueda
List<int> resultado = new
List<int>();
/// Ciclo que recorre la matriz
verificando que la variable pos sea igual al numero -1, cuando sea asi le
asignará a resultado los valores de las coordenadas i y j de la matriz espacio
for (int i = 0; i <
espacio.GetLength(1); i++)
{
for (int j = 0; j <
espacio.GetLength(0); j++)
{
if(pos==num-1)
{
resultado.Add(i);
resultado.Add(j);
}
else
{
pos++;
}
}
}
return
resultado;
}
Método que recupera el id de un botón según sus
coordenadas (este método fue necesario para que el programa modificara los
botones que encontrara alrededor de una casilla vacia presionada)
private int recuperarNboton(int x,int y)
{
/// Variable
de tipo int en la que se guardará la pocisión del boton que se quiere guardar
int pos = 0;
/// Matriz
auxiliar con la cual se buscarán las coordenadas del boton
int[,] eaux
= new int[22, 16];
/// Ciclo
for que deja todos los valores de la matriz eaux en 0
for (int i =
0; i < eaux.GetLength(0); i++)
{
for (int j = 0; j < eaux.GetLength(1); j++)
{
eaux[i, j] = 0;
}
}
/// Linea
que deja el valor de la matriz en 1 según las coordenadas del boton al que se
le quiere encontrar su id
eaux[x, y] =
1;
/// For que
recorre la matriz eaux buscando las coordenadas en donde su valor sea igual a 1
for (int j =
0; j < eaux.GetLength(1); j++)
{
for
(int i = 0; i < eaux.GetLength(0); i++)
{
/// Si el valor en la matriz es igual a 1 deja los valores de i y
j en 100 y se sale del ciclo for
if (eaux[i, j] == 1)
{
j = 100;
i = 100;
}
/// De no ser así le suma 1 a la pocisión
else
{
pos=pos+1;
}
/// Si i es igual a 22 le suma 1 para que continúe con la
siguiente fila
if (i == 22)
{
i++;
}
}
/// Si j es igual a 16 le suma 1 para que continúe con la siguiente
columna
if (j == 16)
{
j++;
}
}
return pos;
}
Método que maneja los eventos de los botones que
representan las casillas de los eventos, si el checkBox ColocarBandera está
seleccionado se ejecuta el método de colocar bandera, en caso contrario se
ejecuta el metodo de destaparmina (Este es solo uno de los métodos ya que
tuvimos que hacer uno por cada boton)
private void button346_Click_1(object sender,
EventArgs e)
{
if
(ColocarBanderas.Checked) {colocarBandera(sender);} else
{destaparmina(sender);}
}
Manejador de eventos del botón salir
private void
BotonSalir_Click(object sender, EventArgs e) { this.Close(); }
Método para controlar el temporizador del juego, este se
ejecutará 1 vez cada segundo
private void
timer1_Tick(object sender, EventArgs e)
{
/// Le suma
1 a los segundos
segundos++;
/// Pregunta
si los segundos están entre 0 y 9, si es así añade un 0 al texto que muestra
los segundos (esto es mera estética)
if (segundos
>= 0 && segundos <= 9)
{
Tiemposeg.Text = ":0" + segundos.ToString();
}
/// Si no es
así pone en el texto los segundos tal y como están
else
{
Tiemposeg.Text = ":"+segundos.ToString();
}
/// Si los
segundos son iguales a 60, le sumará uno a los minutos y dejará los segundos en
0
if (segundos
== 60)
{
segundos = 0;
Tiemposeg.Text = ":00";
minutos++;
/// Pregunta si los minutos están entre 0 y 9, si es así añade un 0 al
texto que muestra los minutos (esto es mera estética)
if (minutos >= 0 && minutos <= 9)
{
Tiempomin.Text = "Tiempo: 0" +
minutos.ToString();
}
/// Si no es así, pone los minutos tal y como están
else
{
Tiempomin.Text = "Tiempo: "+minutos.ToString();
}
}
}
Método para cargar y reproducir sonidos, en la variable
player que es de tipo SoundPlayer, carga el sonido que está dentro de los
recursos del proyecto y luego reproduce el sonido cargado (aqui ponemos uno de
ellos ya que los otros son iguales y solo cambian en el recurso que se carga)
private void SonidoLaser()
{
SoundPlayer
player = new SoundPlayer(global::Buscaminas.Properties.Resources.Laser);
player.Play();
}
Para añadir recursos necesarios para reproducir sonidos y poner imagenes nos
vamos a proyecto y propiedades de buscaminas
Y en la categoría de recursos agregamos los archivos como
recursos
descargue aquí el programa completo