martes, 6 de septiembre de 2016

VBA: Adivina el número buscado - juego en Excel

Desarrollaremos hoy un sencillo juego en Excel que consiste en adivinar un número entero entre 1 y 100.
Comenzaremos construyendo un par de funciones UDF que nos servirán para dar pistas al jugador...
Así, insertamos en un módulo estándar de nuestro proyecto VBA las siguientes funciones (una de ellas la vimos y explicamos en el post anterior):

Function FxEsPar(x As Integer) As Boolean
Dim n As Integer
'comenzamos indicando por defecto que el valor de la función es FALSO
FxEsPar = False
'solo si cumple la ocondición será PAR
'un número es par si el resto de su cocinete entre dos es cero
If (x Mod 2 = 0) Then
    FxEsPar = True
End If

'también podríamos haber aplicado la función
'FxEsPar = Application.WorksheetFunction.IsEven(x)
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function FxEsPrimo(x As Integer) As Boolean
Dim n As Integer
'En matemáticas,
'un número primo es un número natural mayor que 1 que tiene únicamente dos divisores distintos:
'él mismo y el 1.
n = 2
'damos valor VERDADERO por defecto a la función
FxEsPrimo = True
'si el número no es mayor que 1 no puede ser primo
If x <= 1 Then FxEsPrimo = False
'lanzamo un loop para ver si el número tiene algú otro divisor
Do While FxEsPrimo And n <= Sqr(x)
  'si encontramos uno
  'en cuyo caso el resto del cociente será cero
  If (x Mod n = 0) Then
    'en ese caso NO será primo
    FxEsPrimo = False
  End If
  n = n + 1
Loop

'en esta función trabajamos a la inversa,
'demostramos que no existe otro divisor para el número...
End Function

Estas funciones, como adelantaba al inicio de la entrada, la emplearemos en el procedimiento principal, para aportar pistas del número buscado... Añadimos entonces en módulo estándar de nuestro proyecto VBA el siguiente procedimiento:

Sub AdivinaNumero()
Randomize   'Inicializa el generador de números aleatorios.
Dim stPista As String, op As String
Dim msg1 As String, msg2 As String, msg3 As String
Dim x As Integer, numero As Integer
'el número a adivinar!!
'un aleatorio entre 1 y 100
numero = Int(Rnd * 100)

'daremos 10 oportunidades para descubrir el número
'para ello usamos un contador 'intento'
intento = 1

'recorremos los diez intentos...
Do While x <> numero And IsNumeric(numero) = True And intento <= 10
    opcion = (11 - intento)
    If opcion = 1 Then
        op = "Te queda " & opcion & " intento." & vbCrLf
    Else
        op = "Te quedan " & opcion & " intentos." & vbCrLf
    End If
      
    If x <> numero And IsNumeric(numero) = True And intento = 1 Then
        'generamos pista... entre las dos opciones definidas
        'con nuestras UDF: FxEsPAr y FxEsPrimo
        'generamos un aleatorio entre 1 y 2
        pista = Int((2 * Rnd) + 1)

       Select Case pista
         Case Is = 1
          If (FxEsPar(numero) = True) Then stPista = "Pista: Es un número PAR."
          If (FxEsPar(numero) = False) Then stPista = "Pista: Es un número IMPAR."
         Case Is = 2
          If (FxEsPrimo(numero) = True) Then stPista = "Pista: Es un número PRIMO."
          If (FxEsPrimo(numero) = False) Then stPista = "Pista: Es un número COMPUESTO - no primo."
       End Select
    End If
    
    'Comienza la rueda de preguntas al usuario
    x = Val(InputBox("Debes adivinar un número entero entre 1 y 100" & vbCrLf & op + stPista, "Excelforo"))
    '... y el feedback
    If x > 100 Or x < 1 Then m = MsgBox("Debes ingresar un número entre 1 y 100.", 0, "Adivinando un número entero entre 1 y 100"): End
    If x > numero Then m = MsgBox("Más pequeño que " & x, 0, "Adivinando un número entero entre 1 y 100")
    If x < numero Then m = MsgBox("Más grande que " & x, 0, "Adivinando un número entero entre 1 y 100")
    
    'incrementamos el contador
    intento = intento + 1
Loop
      
'Sacamos el mensaje final
msg1 = "Hey!, ¿hiciste trampa?.. Has acertado a la primera!!"
msg2 = "Correcto!!, el número buscado era: " & numero & "."
msg3 = "OOOOh, el número era: " & numero & "."

aux = intento - 1
If x = numero And aux = 1 Then m = MsgBox(msg1 & vbCrLf & msg2, 0, "Enhorabuena!!!")
If x = numero And aux > 1 Then m = MsgBox(msg2, 0, "Felicidades!")
If x <> numero Then m = MsgBox(msg3, 0, "Se siente!!")

End Sub

Asocia la macro 'AdivinaNumero' a un botón o similar, y ya estamos listos para jugar!!!

No hay comentarios:

Publicar un comentario en la entrada