En este ejercicio vamos a desarrollar el famoso juego de BuscaMinas que tanto nos ha entretenido. Además, queremos explicarte cómo hacer un buscaminas en Excel para que puedas hacerlo tú mismo. Pero, sobre todo, vamos a demostrar cómo se pueden realizar aplicaciones de forma fácil en Excel aprovechando las bondades de las hojas de cálculo y de VBA. El objetivo es utilizar las opciones de programación en VBA cuando no se pueda resolver mediante fórmulas de Excel. Esto facilita el tiempo de desarrollo y las depuraciones. Este ejercicio se ha realizado en poco más de una hora, una vez decidido el esquema y organización. En este ejercicio se utilizan el evento Click sobre Botón de Comandos y los eventos SelectionChange y BeforeRightClick sobre Hoja de Cálculo.
La organización de los datos para resolver el juego BUSCAMINAS
Para poder realizar el juego del buscaminas en Excel hemos creado un esquema que nos ayudará a entender los diferentes pasos que debemos dar en la construcción del Excel donde estará el juego. Los datos se estructuran en distintas matrices con una organización como la mostrada en la figura:
- Tablero de Juego, es la matriz que interactúa con el usuario. Toma los datos de la Matriz Mapa Minas Copiados, Matriz Minas Próximas y Matriz Celdas Usadas.
- Matriz Mapa Minas Original es donde, en función del nivel de dificultad seleccionado, se calculan el número de minas y su posición. Los valores de esta matriz cambian cada vez que se realiza un cálculo del libro.
- Matriz Mapa Minas. Donde se anotan las minas que formarán parte del juego. Es copia en valores de la Matriz Mapa Minas Original.
- Matriz Minas Próximas, sobre la Matriz Mapa de Minas calcula el número de minas que hay alrededor de cada celda.
- Matriz Celdas Usadas, toma la posición de la celda del Tablero de Juego y las anota como usada.
- Matriz Finalización, anota cada vez que se usa una celda para contar cuando se han usado todas.
- Matriz Minas Detectadas, anota todas las minas que se han descubierto para saber cuántas quedan por descubrir.
- Matriz Minas Erroneas que anota cuando ha explotado una mina para anotar el número de errores.
Generando minas de forma aleatoria para el BuscaMinas
El primer paso es generar de forma aleatoria las minas sobre la Matriz Mapa Minas Original. Hemos utilizado un tablero de 10×10, pero el lector verá que puede ser cualquier otra dimensión, cambiando los datos necesarios.
Vamos a utilizar la función ALEATORIO.ENTRE. Nos generará un número aleatorio entero comprendido entre a y b, ambos incluidos.
Para decidir si ponemos una mina fijaremos un límite de tal modo que si el valor de la función aleatorio es menor decidiremos poner una mina y si es mayor, no ponemos mina. Por tanto el límite funciona como un grado de dificultad del juego y tomaremos el criterio de representar una mina con un 1 y ausencia de mina con un 0. Para tener más grados de dificultad fijaremos los valores de la variable aleatoria entre 1 y 100. Con esto la ecuación queda:
=SI(ALEATORIO.ENTRE(1;100)<Dificultad*10;1;0) Para una dificultad con valores entre 1 y 10.
El ser ALEATORIO una función estadística uniforme nos dice que de media hay el mismo número de valores desde 1 a 100. Esto quiere decir que para una Dificultad= 5 el 50% son minas y hemos comprobado que por encima de esta densidad de minas es imposible resolver un tablero. Por tanto, y para mantener los grados de dificultad de 1 a 10 hemos modificado la función de esta forma:
=SI(ALEATORIO.ENTRE(1;100)<Dificultad/2*10;1;0) Para una Dificultad entre 1 y 10.
Esto quiere decir que para una Dificultad=5 tendremos alrededor de 25 minas y con 10 alrededor de 50 minas. El siguiente gráfico es la Matriz Mapa Minas Original para dificultad 4, con 23 minas.
Como la función ALEATORIO se va ejecutando cada vez que hay un cambio en la hoja, no podría ser estable para ejecutar el juego con lo que el contenido de la Matriz Mapa Minas Original se copia en valores sobre la Matriz Mapa Minas y desde aquí será donde se ejecute el juego.
Cómo calcular el número de minas que rodean una celda
Para calcular el número de minas que rodean una celda tomamos una cuadricula de 3×3, donde la celda que nos interesa esté en el centro, y contamos las minas que hay. Para que esta cuadrícula exista incluso en las celdas de los bordes, rodearemos la matriz con ceros. Por tanto la Matriz Mapa Minas quedará:
Sobre esta Matriz realizaríamos la suma de una cuadrícula de 3×3, como las minas son un 1 la suma nos dará el número de minas, que anotaremos en la Matriz Minas Próximas.
Para las cuadrículas utilizaremos la función DESREF (Referencia; Nfila; Ncolumna;3;3) que selecciona una cuadrícula de 3×3 cuyo vértice superior izquierda está a Nfila y Ncolumna de la celda Referencia. Para referenciar correctamente cada cuadrícula, los valores de Nfila y Ncolumna se pondrán en los bordes de la Matriz Minas Próximas.
La ecuación utilizada en cada celda de Matriz Minas Próximas sería:
=SUMA(DESREF(Referencia; Nfila; Ncolumna;3;3))
Donde:
- Referencia es la esquina exterior superior izquierda de la Matriz Mapa Minas Copiado;
- Nfila son los valores en el borde izquierdo de la Matriz Minas Próximas;
- Ncolumnas son los valores en el borde superior de la Matriz Minas Próximas;
Secuencia de juego
El juego se realiza sobre la hoja BuscaMinas donde están todos los elementos para interactuar con el juego:
- Tablero de Juego: En el rango A1:J10, es una matriz de 10×10 celdas donde vamos descubriendo las minas ocultas.
- Botón Reiniciar: Para iniciar una partida.
- Selección de la Dificultad: Un desplegable para seleccionar la Dificultad del juego
- Información Minas Detectadas: Un mensaje que nos informa del número de minas detectadas frente al total en el juego.
- Mensaje final de Juego: El detectar todas las minas nos informa del número de errores del juego.
Tablero de Juego
Al pulsar con el botón izquierdo del ratón sobre cualquiera de las celdas aparece el número de minas que hay alrededor de esa celda, o si justo en esa celda hay una mina aparece una X con el fondo rojo. En cambio, si en esa celda pulsamos con el botón derecho si hay una mina se marca una X en fondo verde, pero si no había una mina, aparece la celda con fondo en negro, un mensaje “Error, vuelve a comenzar”, se pinta la solución completa del BuscaMinas y Termina el juego.
Al pulsar el botón izquierdo del ratón se activa el evento Selection Change y al pulsar el botón derecho, se activa el evento Bofore Right Click
Cada celda del tablero de juego comprueba si la posición equivalente de la Matriz Celdas Usadas es un 1, lo que significa que esa posición ya se ha abierto y si no, pone vacío (“”). Si la posición ya se ha abierto, se comprueba si la posición equivalente de la Matriz Mapa Minas Copiadas es un 1, lo que significa que en esa posición hay una mina con lo que pone un X y si no pone el valor de la posición equivalente de la Matriz Minas Próximas, que dice el número de minas que hay alrededor de la celda.
La ecuación en cada celda del tablero de juego sería:
= SI ( MatrizCeldasUsadas = 1; si (MatrizMapaMinasCopiadas = 1; “X”; MatrizMinasProximas))
El juego consiste en identificar la posición de todas las minas con el mínimo número de errores, minas en rojo.
Evento Selection Change
Al pulsar el botón izquierdo del ratón se dispara el evento Selection Change que ejecuta el procedimiento Worksheet_SelectionChange.
El evento Selection Change se dispara cuando se hace una nueva selección en una hoja de cálculo. No hay que confundirlo con el evento Change que se dispara cuando se cambia el contenido de una celda.
El procedimiento Worksheet_SelectionChange tiene la siguiente sintaxis:
Private Sub Worksheet_SelectionChange (ByVal Target As Range)
La variable Target contiene la posición de la celda seleccionada en modo Range.
El procedimiento primero comprueba que se ha pulsado una celda dentro del tablero de juego y si es así pone un 1 en la Matriz Celdas Usadas, para indicar que esa celda ya se ha abierto. Además, comprueba si en esa posición hay una mina y si es así, pinta el fondo de rojo, marca que se ha detectado una mina, en la Matriz Minas Detectadas, y marca que hay un error en la detección de minas, en la Matriz Minas Erroneas.
Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim FilaX, ColumnaX As Integer FilaX = ActiveCell.Row ColumnaX = ActiveCell.Column If FilaX < 11 Then If ColumnaX < 11 Then Sheets("Control").Range("N16").Offset(FilaX, ColumnaX) = 1 If Sheets("Control").Range("N2").Offset(FilaX, ColumnaX) = 1 Then Selection.Interior.Color = vbRed Sheets("control").Range("AA2").Offset(FilaX, ColumnaX) = 1 Sheets("control").Range("AL2").Offset(FilaX, ColumnaX) = 1 End If End If End If End Sub
Evento Before Righ Click
Al seleccionar una celda con el botón derecho del ratón se producen los eventos Selection Change, por haber seleccionado una nueva celda y a continuación el evento Before Right Click, por haber pulsado con el botón derecho sobre la celda.
Con el evento Selection Change ejecuta El procedimiento Worksheet_SelectionChange, que ya hemos visto, y el evento Before Right Click ejecuta el procedimiento Worksheet_BeforeRightClick.
El procedimiento Worksheet_BeforeRightClick, tiene la siguiente sintaxis:
Private Sub Worksheet_BeforeRightClick (ByVal Target As Range, Cancel As Boolean)
- La variable Target contiene la posición de la celda seleccionada en modo Range
- La variable Cancel es False cuando se dispara el evento y se puede poner a True para cancelar los eventos posteriores derivados de la misma acción.
El procedimiento primero comprueba que se ha pulsado una celda del tablero de juego y si es así comprueba que esa celda contiene una mina. Si contiene una mina pinta el fondo de verde y corrige la marca de mina errónea.
Si en esa posición del tablero de juego no hay una mina si entiende que se ha cometido un error grave y no deja continuar el juego. Marca la celda en negro genera un mensaje de error. Una vez aceptado el mensaje de error pinta las posiciones donde estaban todas las minas.
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean) FilaX = ActiveCell.Row ColumnaX = ActiveCell.Column If ColumnaX < 11 Then If FilaX < 11 Then If Sheets("control").Range("N2").Offset(FilaX, ColumnaX) = 1 Then Selection.Interior.Color = vbGreen Sheets("control").Range("AL2").Offset(FilaX, ColumnaX) = 0 Else Selection.Interior.Color = vbBlack Selection.Font.Color = vbWhite MsgBox "Error, vuelve a comenzar.", vbCritical, "Error" Application.ScreenUpdating = False For i = 1 To 11 For j = 1 To 11 Cells(i, j).Select Next Next End If End If End If Cancel = True End Sub
Evento Click en el Botón de Comandos REINICIAR
Al pulsar el botón “Reiniciar” (hacer click) se dispara el evento Click del Botón de Comandos. Este evento ejecuta el procedimiento Private Sub CommandButton1_Click().
Este procedimiento llama a la rutina Sub Iniciar(), que ejecuta:
- Desactiva la actualización de pantalla (Application.ScreenUpdating = False)
- Desactiva la generación de eventos (Application.EnableEvants = False)
- Quita el relleno de todas las celdas del tablero.
- Fija la fuente de color en negro.
- Copia la Matriz Mapa Minas Original sobre la Matriz Mapa Minas en modo valores.
- Limpia la Matriz Celdas Usadas.
- Limpia la Matriz Minas Detectadas
- Limpia la Matriz Minas Erroneas
- Vuelve a activar la actualización de pantalla (Application.ScreenUpdating = False)
- Vuelve a activar la generación de eventos (Application.EnableEvants = False)
La sintaxis de este evento es:
Sub Iniciar() Application.ScreenUpdating = False Application.EnableEvents = False ' Borra el relleno de la matriz de entrada Sheets("BuscaMinas").Select Range("A1:J10").Select With Selection.Interior .Pattern = xlNone .TintAndShade = 0 .PatternTintAndShade = 0 End With With Selection.Font .ThemeColor = xlThemeColorLight1 .TintAndShade = 0 End With Range("M2").Select ' Copia un nuevo mapa de Minas y borra matriz puntos usados, matriz minas detectadas y matriz minas erroneas Sheets("Control").Activate Range("B3:K12").Select Selection.Copy Range("O3").Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False Range("O17:X26").Select Selection.ClearContents Range("AB3:AK12").Select Selection.ClearContents Range("AM3:AV12").Select Selection.ClearContents Application.EnableEvents = True Application.ScreenUpdating = True End Sub
Descargar Buscaminas Excel
Para descargar el Buscaminas en Excel solo tendrás que hacer “Me gusta” en nuestra página de Facebook y así no perderte ni una de nuestras actualizaciones.
[sociallocker]
Juegos ExcelyVBA.com – BUSCAMINAS v2
[/sociallocker]