Busca minas en forma de arañita
A continuación les presentare un busca minas en forma de arañita, este busca minas se monta sobre un panel, y se dibuja su estructura con Blush para definir sus colores DrawLine, FillRectangle y DrawString, gracias a un control de eventos PaintEventArgs el cual nos permite manipular un Objeto Panel, podemos obtener el tipo de clic que se usa sobre el panel con un método panel1_MouseClick que nos permite controlar el evento MouseEventArgs y así poder identificar dicho dato. la figura se crea restringiendo los espacios para que no se utilicen dichos campos como sitio de juego. a continuación les dejo el código para descargar.
Realmente quería hacer el logo del hombre araña de lado pero para que quedara bien tenia que hacer demaciado grande el espacio de juego y no es la gracia !!!!
Descargar Codigo Clic Aqui
ATENCION!
la clase mas importante la cual representa toda la lógica del programa es la clase MapaMinas.cs ahí esta como se cargan las minas como se grafica los botones dentro del panel, como se aplican colores al panel y los despejes, incluyendo tambien el metodo que identifica los campos que van a conformar la figura
MapaMinas.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
namespace BuscaMinas
{
class MapaMinas
{
Celda[,] mapa;
//9 >= mina. 1,2,3,4,5,6,7,8 = minas adyacentes. 0 = casilla vacía y sin minas adyacentes.
int nMinas;
int casillasVistas = 0;
int ancho;
int alto;
bool primerclick = true;
PointF posicion;
int anchoCelda = 20;
int altoCelda = 20;
internal MapaMinas() { }
internal MapaMinas(int ancho, int alto, int numeroMinas, PointF posicion)
{
mapa = new Celda[alto, ancho];
nMinas = numeroMinas;
if (nMinas >= mapa.Length)
throw new ArgumentOutOfRangeException("Debe haber al menos una casilla libre de minas");
this.posicion = posicion;
this.ancho = mapa.GetLength(1);
this.alto = mapa.GetLength(0);
}
internal void DibujarCuadricula(System.Drawing.Graphics g)
{
//definimos los colores y herramientas que nos van a dar la estructura del mapa
Pen lapizRojo = new Pen(Color.Red, 1.0f);
Pen lapizAzul = new Pen(Color.Blue, 1.0f);
Pen lapizNegro = new Pen(Color.Black, 1.0f);
Pen lapizlima = new Pen(Color.LimeGreen, 1.0f);
Pen lapiz = lapizNegro;
Brush brushMina = Brushes.Red;
Brush brush = Brushes.Black;
Brush brushLima = Brushes.LimeGreen;
Brush brushTexto = Brushes.Black;
List<object> fig = imgMap();
int[] ex = (int[])fig[0];
int[] ey = (int[])fig[1];
//desactivamos las areas donde no deben ir minas lo que nos va a dar la figura
for (int i = 0; i < ex.Length; i++)
{
int auxy = ex[i];
int auxx = ey[i];
mapa[auxy, auxx].Visible = false;
}
//Casillas
for (int i = 0; i < alto; i++)
{
for (int j = 0; j < ancho; j++)
{
if (mapa[i, j].Visible == true)
{
int valor = mapa[i, j].Valor;
lapiz = lapizAzul;
//definimos colores los cuales van a llenar y estructural el campo de juego
switch (valor)
{
case 0:
break;
case 9:
g.FillRectangle(brushMina, j * anchoCelda + posicion.X, i * altoCelda + posicion.Y, anchoCelda, altoCelda);
break;
default:
g.DrawString(valor.ToString(), new Font("Arial", 13), brushTexto, j * anchoCelda + posicion.X, i * altoCelda + posicion.Y);
break;
}
}
else
{
int reg = 0;
int auxy = 0, auxx = 0;
for (int id = 0; id < ex.Length; id++)
{
//aca coloreamos las areas donde no se va a jugar
auxy = ey[id];
auxx = ex[id];
if (auxy == j && auxx == i)
{
g.FillRectangle(brushLima, j * anchoCelda + posicion.X, i * altoCelda + posicion.Y, anchoCelda, altoCelda);
reg++;
}
}
if (reg == 0) {
g.FillRectangle(brush, j * anchoCelda + posicion.X, i * altoCelda + posicion.Y, anchoCelda, altoCelda);
}
}
}
}
//lineas horizontales
for (int i = 0; i <= alto; i++)
{
g.DrawLine(lapizNegro, posicion.X, altoCelda * i + posicion.Y, anchoCelda * ancho + posicion.X, altoCelda * i + posicion.Y);
}
//lineas verticales
for (int i = 0; i <= ancho; i++)
{
g.DrawLine(lapizNegro, anchoCelda * i + posicion.X, posicion.Y, anchoCelda * i + posicion.X, altoCelda * alto + posicion.Y);
}
}
private void ColocarMinas(int xInicial, int yInicial)
{
//Obtener aleatoriamente un conjunto de minas
Point[] puntosMinas = new Point[nMinas];
Random r = new Random();
Point puntoIn = new Point(xInicial, yInicial);
// se trae la lista de areas donde no van minas
List<object> fig = imgMap();
int[] ex = (int[])fig[1];
int[] ey = (int[])fig[0];
int ind = 0;
for (int i = 0; i < nMinas; i++)
{
Point p = new Point();
do
{
//se valida que los randomicos no den con espacios de la imagen
int aux1 = r.Next(0, mapa.GetLength(1));
int aux2 = r.Next(0, mapa.GetLength(0));
int control = 0;
for (ind = 0; ind < ex.Length; ind++) {
if (aux1 == ex[ind] && aux2 == ey[ind]) {
control++;
}
}
if (control == 0) {
p.X = aux1;
p.Y = aux2;
}
} while (Contiene(puntosMinas, p) ^ p == puntoIn);
puntosMinas[i] = p;
}
//Colocar los valores en el mapa con minas y numeros de referencia
for (int i = 0; i < puntosMinas.Length; i++)
{
mapa[puntosMinas[i].Y, puntosMinas[i].X].Valor = 9; //9 = ID mina
if (puntosMinas[i].Y + 1 < alto)//abajo
if (mapa[puntosMinas[i].Y + 1, puntosMinas[i].X].Valor < 9)
mapa[puntosMinas[i].Y + 1, puntosMinas[i].X].Valor++;
if (puntosMinas[i].X + 1 < ancho)//derecha
if (mapa[puntosMinas[i].Y, puntosMinas[i].X + 1].Valor < 9)
mapa[puntosMinas[i].Y, puntosMinas[i].X + 1].Valor++;
if (puntosMinas[i].Y - 1 >= 0)//arriba
if (mapa[puntosMinas[i].Y - 1, puntosMinas[i].X].Valor < 9)
mapa[puntosMinas[i].Y - 1, puntosMinas[i].X].Valor++;
if (puntosMinas[i].X - 1 >= 0)//izquierda
if (mapa[puntosMinas[i].Y, puntosMinas[i].X - 1].Valor < 9)
mapa[puntosMinas[i].Y, puntosMinas[i].X - 1].Valor++;
if (puntosMinas[i].Y + 1 < alto && puntosMinas[i].X + 1 < ancho)//abajo-derecha
if (mapa[puntosMinas[i].Y + 1, puntosMinas[i].X + 1].Valor < 9)
mapa[puntosMinas[i].Y + 1, puntosMinas[i].X + 1].Valor++;
if (puntosMinas[i].Y + 1 < alto && puntosMinas[i].X - 1 >= 0)//abajo-izquierda
if (mapa[puntosMinas[i].Y + 1, puntosMinas[i].X - 1].Valor < 9)
mapa[puntosMinas[i].Y + 1, puntosMinas[i].X - 1].Valor++;
if (puntosMinas[i].Y - 1 >= 0 && puntosMinas[i].X - 1 >= 0)//arriba-izquierda
if (mapa[puntosMinas[i].Y - 1, puntosMinas[i].X - 1].Valor < 9)
mapa[puntosMinas[i].Y - 1, puntosMinas[i].X - 1].Valor++;
if (puntosMinas[i].Y - 1 >= 0 && puntosMinas[i].X + 1 < ancho)//arriba-derecha
if (mapa[puntosMinas[i].Y - 1, puntosMinas[i].X + 1].Valor < 9)
mapa[puntosMinas[i].Y - 1, puntosMinas[i].X + 1].Valor++;
}
//aca ya debe estar cargado todo el tablero con minas
}
private bool Contiene(Point[] conjunto, Point elemento)
{
for (int i = 0; i < conjunto.Length; i++)
{
if (conjunto[i].X == elemento.X && conjunto[i].Y == elemento.Y)
return true;
}
return false;
}
internal bool DestaparCelda(int x, int y)
{
//Destapa las celdas cliqueadas, si es la primera vez que se carga el juego se ejecuta el metodo Colocar minas si no ignora el
//el condicional if (primerclick) y empieza a validar si hay mina y las pocisiones que hay a lado
if (primerclick)
{
ColocarMinas(x, y);
primerclick = false;
}
if (x < ancho && y < alto && x >= 0 && y >= 0 && mapa[y, x].Visible == false)
{
if (mapa[y, x].Valor >= 9)
{
casillasVistas++;
return true;
}
DescubrirArea(x, y);
casillasVistas=0;
for (int i = 0; i < alto; i++)
{
for (int j = 0; j < ancho; j++)
{
if (mapa[i, j].Visible == true)
{
casillasVistas++;
}
}
}
//mapa[y, x].Visible = true;
}
return false;
}
private void DescubrirArea(int x, int y)
{
//Si la casilla esta tapada
if (mapa[y, x].Visible == false)
{
//Descubre la casilla
mapa[y, x].Visible = true;
//casillasVistas++;
//Si no hay minas cercanas
if (mapa[y, x].Valor == 0)
{
//Recorre las casillas cercanas y tambien las ejecuta
for (int f2 = Math.Max(0, x - 1); f2 < Math.Min(ancho, x + 2); f2++)
{
for (int c2 = Math.Max(0, y - 1); c2 < Math.Min(alto, y + 2); c2++)
{
DescubrirArea(f2, c2);
}
}
}
}
}
internal void HacerTodoVisible()
{
for (int i = 0; i < alto; i++)
{
for (int j = 0; j < ancho; j++)
{
mapa[i, j].Visible = true;
}
}
}
internal Celda[,] Casillas
{
get { return mapa; }
}
internal PointF Posicion
{
get { return posicion; }
}
internal int AnchoCelda
{
get { return anchoCelda; }
}
internal int AltoCelda
{
get { return altoCelda; }
}
internal int Ancho
{
get { return ancho; }
}
internal int Alto
{
get { return alto; }
}
internal int CasillasVistas
{
get { return casillasVistas; }
}
public List<Object> imgMap() {
// esta lista contiene las coordenadas que no se van a usar y que dan la forma de arañita
List<object>ls= new List<object>();
int[]ejex={0,0,0,0,0,0,0, 0 ,0 ,0, 0, 0, 0, 1,1,1,1, 1, 1, 1 ,1 ,1 ,1 ,1 ,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3, 3, 3, 3, 3, 3,3, 4,4,4,4,4,4,4,4,4, 5,5,5,5,5,5,5,5, 6,6,6,6,6, 7 ,9,9,9,9,9,9,9,9, 10,10,10,10,10,10,10,10 ,12, 13,13,13,13,13, 14,14,14,14,14,14,14,14, 15,15,15,15,15,15,15,15,15, 16,16,16,16,16,16,16,16,16,16, 17,17,17,17,17,17,17,17,17,17,17, 18,18,18,18,18,18,18,18,18,18,18, 19,19,19,19,19,19,19,19,19,19,19,19,19};
int[]ejey={0,1,2,3,4,5,11,14,15,16,17,18,19, 0,1,2,3,4,10,15,16,17,18,19, 0,1,2,3,10,12,13,16,17,18,19, 0,1,2,5,10,12,14,17,18,19 ,0,1,4,6,10,12,15,18,19, 0,3,7,12,16,17,18,19, 0,1,2,7,12 ,12, 0,1,2,3,16,17,18,19, 0,1,2,3,16,17,18,19, 12 ,0,1,2,7,12, 0,3,7,12,16,17,18,19, 0,1,4,6,10,12,15,18,19, 0,1,2,5,10,12,14,17,18,19, 0,1,2,3,10,12,13,16,17,18,19, 0,1,2,3,4,10,15,16,17,18,19, 0,1,2,3,4,5,11,14,15,16,17,18,19};
ls.Add(ejex);
ls.Add(ejey);
return ls;
}
internal bool bandera(int x, int y, System.Drawing.Graphics g)
{
Brush brushLima = Brushes.DarkSlateBlue;
//g.FillRectangle(brushLima, y * anchoCelda + x, x * altoCelda + y, anchoCelda, altoCelda);
return false;
}
}
}
Windows Form
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Media;
using System.Text;
using System.Windows.Forms;
namespace BuscaMinas
{
public partial class Form1 : Form
{
MapaMinas mapa;
bool muerte = false;
bool ganado = false;
int MINAS = 20;
int TAMAÑOX = 20;
int TAMAÑOY = 20;
public Form1(int tamañoX, int tamañoY, int minas, string titulo)
{
TAMAÑOX = tamañoX;
TAMAÑOY = tamañoY;
MINAS = minas;
Text = titulo;
InitializeComponent();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
mapa.DibujarCuadricula(e.Graphics);
}
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
int celdaX, celdaY;
if (e.Button == MouseButtons.Right)
{
celdaX = (e.X - (int)mapa.Posicion.X) / mapa.AnchoCelda;
celdaY = (e.Y - (int)mapa.Posicion.Y) / mapa.AltoCelda;
Graphics g;
}
else {
try
{
celdaX = (e.X - (int)mapa.Posicion.X) / mapa.AnchoCelda;
celdaY = (e.Y - (int)mapa.Posicion.Y) / mapa.AltoCelda;
MapaMinas om = new MapaMinas();
List<object> fig = om.imgMap();
int[] ex = (int[])fig[1];
int[] ey = (int[])fig[0];
int reg = 0;
int auxy = 0, auxx = 0;
//verificamos que la zona este habilitada para jugar
for (int id = 0; id < ex.Length; id++)
{
auxy = ey[id];
auxx = ex[id];
if (auxy == celdaY && auxx == celdaX)
{
reg++;
}
}
//si la zona esta habilitada ingresamos a verificar si hay mina o no
if (reg == 0)
{
if (!mapa.Casillas[celdaY, celdaX].Visible)
{
muerte = mapa.DestaparCelda(celdaX, celdaY);
}
panel1.Invalidate();
if (muerte)
{
mapa.HacerTodoVisible();
Invalidate();
DialogResult result = MessageBox.Show("¡Has Pisado una mina! :C", "Buscaminas", MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
{
OnLoad(new EventArgs());
}
else if (result == DialogResult.No)
{
this.Close();
}
}
if (TAMAÑOX * TAMAÑOY - (MINAS+152) <= mapa.CasillasVistas)
{
Invalidate();
DialogResult result = MessageBox.Show("¡Has ganado! Felicitaciones :)", "Buscaminas", MessageBoxButtons.YesNo);
if(result == DialogResult.Yes)
{
OnLoad(new EventArgs());
}
else if(result == DialogResult.No)
{
this.Close();
}
}
}}
catch {
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
mapa = new MapaMinas(TAMAÑOX, TAMAÑOY, MINAS, new PointF(30, 30));
panel1.Invalidate();
}
private void label1_Click(object sender, EventArgs e)
{
}
private void label3_Click(object sender, EventArgs e)
{
}
}
}
