Acceder

Desafío Excel VBA para programadores - El valor estratégico de las celdas en ajedrez

Hola fans de programar en Excel VBA, hoy he querido poneros un desafío que no requiere demasiado código.  Se trata de analizar la capacidad de ataque de tus piezas dentro del tablero de ajedrez.  Primero hablaré de las reglas para construir el código, y luego el razonamiento acerca de por qué será de gran interés para tí y tus amigos, y sobre todo, será de interés para la comunidad del ajedrez.

En unas cuantas horas podreis completarlo.

Cómo debe funcionar la macro


En el tablero de la izquierda tienes las piezas, y en el de la derecha la cantidad de piezas que amenazan una determinada casilla.


En este ejemplo puedes ver a una reina y las celdas que puede atacar.  Como puedes ver hay dos piezas que evitan que su zona de influencia pueda extenderse.  La idea es calcular estas zonas para todas las piezas de un bando.  Al final vas a sumar todas las zonas de influencia (o región donde hay capacidad de ataque) de una pieza dada.  Puedes usar estos ejemplos para validar tus resultados.

La suma de todos los valores de las casillas y la cantidad de casillas con números también debe estar allí.  Mientras más casillas o mientras mayor sea la suma, mayor será la capacidad ofensiva de una disposición dada de piezas.

Además, en el tablero de la derecha, a como los valores sean mayores, tendrían que colorearse con un color más oscuro.  Obviamente tendrás que limpiar los colores de las celdas al tener nuevas configuraciones de piezas.

Las razones para crear esta macro

El ajedrez es un juego que abstrae mucho, y a muchos jugadores les gusta ganar y no te dicen cómo.  Encima el ajedrez no tiene comparación directa con un campo de batalla real en términos de movimientos y estrategias de ataque.  Esto hace que para el novato, diseñar estrategias y ver vulnerabilidades, se complique mucho.

Te dicen que hay que "controlar el centro" y ese es uno de los más grandes engaños de los maestros que enseñan ajedrez a sus alumnos.   En realidad lo que hay que hacer es expandir tu zona de influencia.  Si eres maestro de ajedrez puede que quieras sentirte ofendido, pero no deberías, porque al final te daré la razón pero de una manera distinta.  Es decir, el consejo es correcto, pero no como objetivo, sino como medio para lograr algo más.

Es que al final el ajedrez es igual que cualquier otro juego de estrategia y conquista.  Lo que necesitas es conquistar territorio.  Y la zona de influencia expande ese territorio. Y para muestra un botón, veamos algunas situaciones que justifican este razonamiento.

Entonces ¿qué implica controlar el centro?  El centro es la zona desde la cual puedes extender tu influencia con más facilidad, pues las orillas te restringen.  Entonces la lógica del centro no es del todo errada, pero no necesariamente es el mejor consejo.  El mejor consejo es buscar la mejor manera de expandir la zona de influencia propia o mover o reducir la zona de influencia enemiga.

Hay situaciones donde un jugador se encuentra encerrado por sus propias piezas.  En realidad no está encerrado, pues si puede moverse, pero no sin entrar en la zona de influencia enemiga y ser atacado.  Tiene su zona de influencia restringida.

Cuando analizas los gambitos, se trata de "sacrificio" para conseguir una "posición" o "ganar tiempo".  ¿Cómo sabes que una posición es o no valiosa?  Es valiosa en la medida en que te ayuda a expandir tu zona de influencia o acercar esa zona al enemigo. ¿Cómo se gana tiempo?  Le pones una carnada al enemigo para despejar una zona de influencia, y posiblemente reducir la zona de influencia enemiga, para realizar una movida.

Este modelo te permite representar visualmente las zonas de influencia.

Veamos este gambito donde un jugador regala el peón.


Visto desde la óptica del segundo jugador



Ahora el segundo jugador toma el regalo que le han dado.


Y para el segundo jugador, que toma el regalo, se mira así.


Y el primer jugador saca el caballo para cubrir la celda donde la reina enemiga podría atacar al rey..

Observa cómo es que a pesar de perder una pieza (y bajar su conteo de celdas), el jugador ha ganado en la suma.  Y la zona de influencia del oponente no cambia ni en la suma ni en el conteo, peró si en su distribución, y ha perdido la capacidad de controlar el centro.

Entonces la conquista en ajedrez no es un tema de conquistar el centro, sino de mover o reducir zonas de influencia del enemigo.  Reducirlas sirve para limitar la capacidad ofensiva enemiga, y moverlas sirve para despejar áreas y organizar ataques contra el rey. 

¿Te parece interesante este desafío?  ¿Te parece interesante las jugadas que puedes analizar con esta herramienta?  Bienvenidos sean tus comentarios y los análisis que hagas de jugadas que hayas encontrado.

----------------------------------------------------------------------------------------------
Solución:

Este es el código usado.  Necesitas un botón que eche a andar la subrutina ChessValue

Sub ChessValue()
    MiBando = CStr(Cells(11, 4))
    ClearBoardColors
    For i = 2 To 9
        For j = 2 To 9
            Cells(i, j + 10) = ""
        Next j
    Next i
    For i = 2 To 9
        For j = 2 To 9
            c = Cells(i, j)
            Pieza = Left(c, 1)
            Bando = Right(c, 1)
            EvaluarPieza Pieza, Bando, i, j, MiBando
        Next j
    Next i
    ColorCells
End Sub

Sub EvaluarPieza(Pieza, Bando, fila, col, MiBando)
    If Bando = MiBando Then
        D1 = DrawNumber(fila, col, True)
        Select Case Pieza
            Case "J" 'Alfil
                D1 = True
                D2 = True
                D3 = True
                D4 = True
                For i = 1 To 8
                    D1 = DrawNumber(fila + i, col + i, D1)
                    D2 = DrawNumber(fila + i, col - i, D2)
                    D3 = DrawNumber(fila - i, col + i, D3)
                    D4 = DrawNumber(fila - i, col - i, D4)
                Next i
            Case "Q" 'Reina
                D1 = True
                D2 = True
                D3 = True
                D4 = True
                D5 = True
                D6 = True
                D7 = True
                D8 = True
                For i = 1 To 8
                    D1 = DrawNumber(fila + i, col + i, D1)
                    D2 = DrawNumber(fila + i, col - i, D2)
                    D3 = DrawNumber(fila - i, col + i, D3)
                    D4 = DrawNumber(fila - i, col - i, D4)
                    D5 = DrawNumber(fila, col + i, D5)
                    D6 = DrawNumber(fila, col - i, D6)
                    D7 = DrawNumber(fila - i, col, D7)
                    D8 = DrawNumber(fila + i, col, D8)
                Next i
            Case "K" 'Rey
                D1 = DrawNumber(fila + 1, col + 1, True)
                D2 = DrawNumber(fila + 1, col - 1, True)
                D3 = DrawNumber(fila - 1, col + 1, True)
                D4 = DrawNumber(fila - 1, col - 1, True)
                D5 = DrawNumber(fila, col + 1, True)
                D6 = DrawNumber(fila, col - 1, True)
                D7 = DrawNumber(fila - 1, col, True)
                D8 = DrawNumber(fila + 1, col, True)
            Case "H" 'Caballo
                D1 = DrawNumber(fila + 2, col + 1, True)
                D2 = DrawNumber(fila + 2, col - 1, True)
                D3 = DrawNumber(fila - 2, col + 1, True)
                D4 = DrawNumber(fila - 2, col - 1, True)
                D5 = DrawNumber(fila - 1, col + 2, True)
                D6 = DrawNumber(fila + 1, col + 2, True)
                D7 = DrawNumber(fila - 1, col - 2, True)
                D8 = DrawNumber(fila + 1, col - 2, True)
            Case "T" 'Torre
                D1 = True
                D2 = True
                D3 = True
                D4 = True
                For i = 1 To 8
                    D1 = DrawNumber(fila, col + i, D1)
                    D2 = DrawNumber(fila, col - i, D2)
                    D3 = DrawNumber(fila - i, col, D3)
                    D4 = DrawNumber(fila + i, col, D4)
                Next i
            Case "P" 'Peon
                If Bando = 2 Then
                    D1 = DrawNumber(fila + 1, col + 1, True)
                    D2 = DrawNumber(fila + 1, col - 1, True)
                ElseIf Bando = 1 Then
                    D3 = DrawNumber(fila - 1, col + 1, True)
                    D4 = DrawNumber(fila - 1, col - 1, True)
                    End If
        End Select
    End If
End Sub

Function DrawNumber(r, c, D) As Boolean
    DrawNumber = D
    If WithinBoard(r, c) Then
        If Cells(r, c) = "" And D Then
            Cells(r, c + 10) = Cells(r, c + 10) + 1
        Else
            If DrawNumber Then
                Cells(r, c + 10) = Cells(r, c + 10) + 1
            End If
            DrawNumber = False
        End If
    End If
End Function

Function WithinBoard(row, col) As Boolean
    WithinBoard = row > 1 And row < 10 And col > 1 And col < 10
End Function

Sub ClearBoardColors()
    For i = 2 To 9
        For j = 12 To 19
            Cells(i, j).Select
            NoFill
        Next j
    Next i
End Sub

Sub ColorCells()
    c = Array(0.799981688894314, 0.599993896298105, 0.399975585192419, -0.249977111117893, -0.499984740745262)
    Theme = xlThemeColorAccent4
    For i = 2 To 9
        For j = 12 To 19
            v = Cells(i, j)
            If v > 0 Then
                If v > 5 Then v = 5
                TintShade = c(v - 1)
                Cells(i, j).Select
                ThemeColor Theme, TintShade
            End If
        Next j
    Next i
End Sub

Sub NoFill()
    With Selection.Interior
        .Pattern = xlNone
        .TintAndShade = 0
        .PatternTintAndShade = 0
    End With
End Sub

Sub ThemeColor(Theme, TintShade)
    With Selection.Interior
        .Pattern = xlSolid
        .PatternColorIndex = xlAutomatic
        .ThemeColor = Theme
        .TintAndShade = TintShade
        .PatternTintAndShade = 0
    End With
End Sub

¿Te ha gustado el artículo?

Si quieres saber más y estar al día de mis reflexiones, suscríbete a mi blog y sé el primero en recibir las nuevas publicaciones en tu correo electrónico.

Accede a Rankia
¡Sé el primero en comentar!