Pop

Curso programación C# - 74. Inteligencia Artificial con C# (3)- Visual Studio 2017

74. Inteligencia Artificial (3). Analizando el motor del juego de Ajedrez

 -  En este capítulo del curso de programación en c# con visual studio 2017 vamos a continuar con nuestra serie de entradas relacionadas con un tema de moda: la inteligencia artificial. En este capítulo del curso continuamos con el análisis del motor del juego. Desgranaremos el funcionamiento de algunas de las clases que controlan los movimientos de nuestro ajedrez.


- En concreto en esta entrada vemos el funcionamiento de las últimas clases del motor interno que nos quedaban por analizar :  MovimientoValidoPieza.cs , Tablero.cs y Engine.cs. También os muestro brevemente la clases que utilizamos para pintar en pantalla el tablero y como inicializamos la posición de las piezas en el tablero.En el vídeo lo podemos ver:



Os dejo el código de las clases mencionadas en el vídeo:

  • MovimientoValidoPieza.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AjedrezIA.Motor
{
    internal static class MovimientosValidosPiezas
    {
        internal static bool[]  tableroAtacanNegras;
        private static byte poscionReynegro;

        internal static bool[] tableroAtacanBlancas;
        private static byte posicionReyBlanco;

        private static void analizarMovimientoPeon(Tablero tablero, byte posicionDestino, Pieza piezaMovimiento)
        {
            //Como el peón sólo mata en diagonal.La captura al paso es un escenario especial
            if (tablero.anteriorPosicion > 0)
            {
                if (piezaMovimiento.colorPieza != tablero.capturaAlPasoColor)
                {
                    if (tablero.anteriorPosicion == posicionDestino)
                    {
                        //Posible captura al paso
                        piezaMovimiento.movimientosValidos.Push(posicionDestino);

                        if (piezaMovimiento.colorPieza == ColorPieza.Blanco)
                            tableroAtacanBlancas[posicionDestino] = true;
                        else
                            tableroAtacanNegras[posicionDestino] = true;
                        
                    }
                }
            }

            Pieza piezaAtacada = tablero.Escaques[posicionDestino].pieza;

            
            if (piezaAtacada == null)
                return;

            //Se ataca este cuadrado
            if (piezaMovimiento.colorPieza == ColorPieza.Blanco)
            {
                tableroAtacanBlancas[posicionDestino] = true;

                //Si la pieza es del mismo color
                if (piezaAtacada.colorPieza == piezaMovimiento.colorPieza)
                {
                    piezaAtacada.valorDefensa += piezaMovimiento.valorAccionPieza;
                    return;
                }

                piezaAtacada.valorAtaque += piezaMovimiento.valorAccionPieza;

                //Si es un rey se hace jaque                  
                if (piezaAtacada.tipoPieza == TipoPiezaAjedrez.Rey)
                      tablero.jaqueNegro = true;
                else
                    piezaMovimiento.movimientosValidos.Push(posicionDestino);
                
            }
            else
            {
                tableroAtacanNegras[posicionDestino] = true;

                //Si la pieza es del mismo color
                if (piezaAtacada.colorPieza == piezaMovimiento.colorPieza)
                {
                    piezaAtacada.valorDefensa += piezaMovimiento.valorAccionPieza;
                    return;
                }

                piezaAtacada.valorAtaque += piezaMovimiento.valorAccionPieza;

                //Si es un rey se hace jaque                      
                if (piezaAtacada.tipoPieza == TipoPiezaAjedrez.Rey)
                    tablero.jaqueBlanco = true;
                else
                    piezaMovimiento.movimientosValidos.Push(posicionDestino);
                
            }

            return;
        }

        private static bool analizarMovimiento(Tablero tablero, byte posicionDestino, Pieza piezaMovimiento)
        {
            //Si no soy un peón muevo y puedo atacar
            if (piezaMovimiento.colorPieza == ColorPieza.Blanco)
                 tableroAtacanBlancas[posicionDestino] = true;
            else
                tableroAtacanNegras[posicionDestino] = true;


            //Si no hay ninguna pieza allí, puedo matar potencialmente
            if (tablero.Escaques[posicionDestino].pieza == null)
            {
                piezaMovimiento.movimientosValidos.Push(posicionDestino);

                return true;
            }

            Pieza piezaAtacada = tablero.Escaques[posicionDestino].pieza;

            //Si la pieza es de diferente color
            if (piezaAtacada.colorPieza != piezaMovimiento.colorPieza)
            {
                piezaAtacada.valorAtaque += piezaMovimiento.valorAccionPieza;

                //Si hay un rey hacemos jaque                
                if (piezaAtacada.tipoPieza == TipoPiezaAjedrez.Rey)
                {
                    if (piezaAtacada.colorPieza == ColorPieza.Negro)
                    {
                        tablero.jaqueNegro = true;
                    }
                    else
                    {
                        tablero.jaqueBlanco = true;
                    }
                }
                else
                {
                    //añadir como movimiento válido
                    piezaMovimiento.movimientosValidos.Push(posicionDestino);
                }

                //No podemos seguir moviendonos
                return false;
            }
        
            piezaAtacada.valorDefensa += piezaMovimiento.valorAccionPieza;
            
            return false;
        }

        private static void chequearMovimientosValidosPeon(List<byte> movimientos, Pieza piezaMoviendose, byte posicionOrigen,Tablero tablero, byte cont)
        {
            for (byte i = 0; i < cont; i++)
            {
                byte posDestino = movimientos[i];

                if (posDestino % 8 != posicionOrigen % 8)
                {
                    //Si no hay ninguna pieza es una muerte potencial
                    analizarMovimientoPeon(tablero, posDestino, piezaMoviendose);

                    if (piezaMoviendose.colorPieza == ColorPieza.Blanco)
                    {
                        tableroAtacanBlancas[posDestino] = true;
                    }
                    else
                    {
                        tableroAtacanNegras[posDestino] = true;
                    }
                }
                // si tenemos algo enfrente peón no podemos mover 
                else if (tablero.Escaques[posDestino].pieza != null)
                  return;
                //si tenemos algo enfrente peón  podemos mover 
                else
                    piezaMoviendose.movimientosValidos.Push(posDestino);
                
            }
        }

        private static void generarMovimientosValidosRey(Pieza pieza, Tablero tablero, byte posicionOrigen)
        {
            if (pieza == null)
            {
                return;
            }

            for (byte i = 0; i < MovimientoArrays.ReytotalMovimientos[posicionOrigen]; i++)
            {
                byte posicionDestino = MovimientoArrays.ReyMovimientos[posicionOrigen].Movimientos[i];

                if (pieza.colorPieza == ColorPieza.Blanco)
                {
                    //No puedo moverme porque estoy siendo atacado
                    if (tableroAtacanNegras[posicionDestino])
                    {
                        tableroAtacanBlancas[posicionDestino] = true;
                        continue;
                    }
                }
                else
                {
                    if (tableroAtacanBlancas[posicionDestino])
                    {
                        tableroAtacanNegras[posicionDestino] = true;
                        continue;
                    }
                }

                analizarMovimiento(tablero, posicionDestino, pieza);
            }
        }

        private static void generarMovimientosValidosEnroque(Tablero tablero, Pieza rey)
        {
            if (rey == null)
                 return;
            if (rey.Movida)
               return;
            
            if (rey.colorPieza == ColorPieza.Blanco && tablero.enroqueBlanco)
               return;
            
            if (rey.colorPieza == ColorPieza.Negro && tablero.enroqueNegro)
                return;
            
            if (rey.colorPieza == ColorPieza.Negro && tablero.jaqueNegro)
                  return;
            
            if (rey.colorPieza == ColorPieza.Blanco && tablero.jaqueBlanco)
                return;
            

            //Chequeo los posibles enroques
            if (rey.colorPieza == ColorPieza.Blanco)
            {
                if (tablero.jaqueBlanco)
                    return;
                

                if (tablero.Escaques[63].pieza != null)
                {
                    //Comprobar que la torre sigue en poscion correcta
                    if (tablero.Escaques[63].pieza.tipoPieza == TipoPiezaAjedrez.Torre)
                    {
                        if (tablero.Escaques[63].pieza.colorPieza == rey.colorPieza)
                        {
                            if (tablero.Escaques[62].pieza == null)
                            {
                                if (tablero.Escaques[61].pieza == null)
                                {
                                    if (tableroAtacanNegras[61] == false &&
                                        tableroAtacanNegras[62] == false)
                                    {
                                      
                                        rey.movimientosValidos.Push(62);
                                        tableroAtacanBlancas[62] = true;
                                    }
                                }
                            }
                        }
                    }
                }

                if (tablero.Escaques[56].pieza != null)
                {
                    //Comprobar que la torre sigue en poscion correcta
                    if (tablero.Escaques[56].pieza.tipoPieza == TipoPiezaAjedrez.Torre)
                    {
                        if (tablero.Escaques[56].pieza.colorPieza == rey.colorPieza)
                        {
                          
                            if (tablero.Escaques[57].pieza == null)
                            {
                                if (tablero.Escaques[58].pieza == null)
                                {
                                    if (tablero.Escaques[59].pieza == null)
                                    {
                                        if (tableroAtacanNegras[58] == false &&
                                            tableroAtacanNegras[59] == false)
                                        {
                                           
                                            rey.movimientosValidos.Push(58);
                                            tableroAtacanBlancas[58] = true;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else if (rey.colorPieza == ColorPieza.Negro)
            {
                if (tablero.jaqueNegro)
                {
                    return;
                }

                //scenario 1:
                if (tablero.Escaques[7].pieza != null)
                {
                    //Comprobar que la torre sigue en poscion correcta
                    if (tablero.Escaques[7].pieza.tipoPieza == TipoPiezaAjedrez.Torre
                        && !tablero.Escaques[7].pieza.Movida)
                    {
                        if (tablero.Escaques[7].pieza.colorPieza == rey.colorPieza)
                        {
                            if (tablero.Escaques[6].pieza == null)
                            {
                                if (tablero.Escaques[5].pieza == null)
                                {
                                    if (tableroAtacanBlancas[5] == false && tableroAtacanBlancas[6] == false)
                                    {
                                       
                                        rey.movimientosValidos.Push(6);
                                        tableroAtacanNegras[6] = true;
                                    }
                                }
                            }
                        }
                    }
                }
                //scenario 2:
                if (tablero.Escaques[0].pieza != null)
                {   
                    //Comprobar que la torre sigue en poscion correcta
                    if (tablero.Escaques[0].pieza.tipoPieza == TipoPiezaAjedrez.Torre && !tablero.Escaques[0].pieza.Movida)
                    {
                        if (tablero.Escaques[0].pieza.colorPieza == rey.colorPieza)
                        {
                            
                            if (tablero.Escaques[1].pieza == null)
                            {
                                if (tablero.Escaques[2].pieza == null)
                                {
                                    if (tablero.Escaques[3].pieza == null)
                                    {
                                        if (tableroAtacanBlancas[2] == false &&
                                            tableroAtacanBlancas[3] == false)
                                        {
                                            //Ok looks like move is valid lets add it
                                            rey.movimientosValidos.Push(2);
                                            tableroAtacanNegras[2] = true;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        internal static void generarMovimientosValidos(Tablero tablero)
        {
            // Reset tablero
            tablero.jaqueNegro = false;
            tablero.jaqueBlanco = false;

            tableroAtacanBlancas = new bool[64];
            tableroAtacanNegras = new bool[64];

            //Generate Moves
            for (byte x = 0; x < 64; x++)
            {
                Cuadrado escaque = tablero.Escaques[x];

                if (escaque.pieza == null)
                    continue;

                escaque.pieza.movimientosValidos = new Stack<byte>(escaque.pieza.ultimoMovimiento);

                switch (escaque.pieza.tipoPieza)
                {
                    case TipoPiezaAjedrez.Peon:
                        {
                            if (escaque.pieza.colorPieza == ColorPieza.Blanco)
                            {
                                chequearMovimientosValidosPeon(MovimientoArrays.peonBlancoMovimientos[x].Movimientos, escaque.pieza, x,tablero,MovimientoArrays.peonBlancoTotalMovimientos[x]);
                                break;
                            }
                            if (escaque.pieza.colorPieza == ColorPieza.Negro)
                            {
                                chequearMovimientosValidosPeon(MovimientoArrays.peonNegroMovimientos[x].Movimientos, escaque.pieza, x,tablero,MovimientoArrays.peonNegroTotalMovimientos[x]);
                                break;
                            }

                            break;
                        }
                    case TipoPiezaAjedrez.Caballo:
                        {
                            for (byte i = 0; i < MovimientoArrays.caballoTotalMovimientos[x]; i++)
                            {
                                analizarMovimiento(tablero, MovimientoArrays.caballoMovimientos[x].Movimientos[i], escaque.pieza);
                            }

                            break;
                        }
                    case TipoPiezaAjedrez.Alfil:
                        {
                            for (byte i = 0; i < MovimientoArrays.AlfilTotalMovimientos1[x]; i++)
                            {
                                if (analizarMovimiento(tablero, MovimientoArrays.AlfilMovimientos1[x].Movimientos[i],escaque.pieza) ==false)
                                {
                                    break;
                                }
                            }
                            for (byte i = 0; i < MovimientoArrays.AlfilTotalMovimientos2[x]; i++)
                            {
                                if (analizarMovimiento(tablero, MovimientoArrays.AlfilMovimientos2[x].Movimientos[i],escaque.pieza) ==false)
                                {
                                    break;
                                }
                            }
                            for (byte i = 0; i < MovimientoArrays.AlfilTotalMovimientos3[x]; i++)
                            {
                                if (analizarMovimiento(tablero, MovimientoArrays.AlfilMovimientos3[x].Movimientos[i], escaque.pieza) ==false)
                                {
                                    break;
                                }
                            }
                            for (byte i = 0; i < MovimientoArrays.AlfilTotalMovimientos4[x]; i++)
                            {
                                if (analizarMovimiento(tablero, MovimientoArrays.AlfilMovimientos4[x].Movimientos[i],escaque.pieza) ==false)
                                {
                                    break;
                                }
                            }

                            break;
                        }
                    case TipoPiezaAjedrez.Torre:
                        {
                            for (byte i = 0; i < MovimientoArrays.TorreTotalMovimientos1[x]; i++)
                            {
                                if (analizarMovimiento(tablero, MovimientoArrays.TorreMovimientos1[x].Movimientos[i], escaque.pieza) ==false)
                                {
                                    break;
                                }
                            }
                            for (byte i = 0; i < MovimientoArrays.TorreTotalMovimientos2[x]; i++)
                            {
                                if (analizarMovimiento(tablero, MovimientoArrays.TorreMovimientos2[x].Movimientos[i], escaque.pieza) ==false)
                                {
                                    break;
                                }
                            }
                            for (byte i = 0; i < MovimientoArrays.TorreTotalMovimientos3[x]; i++)
                            {
                                if (analizarMovimiento(tablero, MovimientoArrays.TorreMovimientos3[x].Movimientos[i], escaque.pieza) ==false)
                                {
                                    break;
                                }
                            }
                            for (byte i = 0; i < MovimientoArrays.TorreTotalMovimientos4[x]; i++)
                            {
                                if (analizarMovimiento(tablero, MovimientoArrays.TorreMovimientos4[x].Movimientos[i], escaque.pieza) == false)
                                {
                                    break;
                                }
                            }

                            break;
                        }
                    case TipoPiezaAjedrez.Reina:
                        {
                            for (byte i = 0; i < MovimientoArrays.ReinaTotalMovimientos1[x]; i++)
                            {
                                if ( analizarMovimiento(tablero, MovimientoArrays.ReinaMovimientos1[x].Movimientos[i], escaque.pieza) == false)
                                {
                                    break;
                                }
                            }
                            for (byte i = 0; i < MovimientoArrays.ReinaTotalMovimientos2[x]; i++)
                            {
                                if (analizarMovimiento(tablero, MovimientoArrays.ReinaMovimientos2[x].Movimientos[i], escaque.pieza) == false)
                                {
                                    break;
                                }
                            }
                            for (byte i = 0; i < MovimientoArrays.ReinaTotalMovimientos3[x]; i++)
                            {
                                if (analizarMovimiento(tablero, MovimientoArrays.ReinaMovimientos3[x].Movimientos[i], escaque.pieza) == false)
                                {
                                    break;
                                }
                            }
                            for (byte i = 0; i < MovimientoArrays.ReinaTotalMovimientos4[x]; i++)
                            {
                                if (analizarMovimiento(tablero, MovimientoArrays.ReinaMovimientos4[x].Movimientos[i], escaque.pieza) == false)
                                {
                                    break;
                                }
                            }

                            for (byte i = 0; i < MovimientoArrays.ReinaTotalMovimientos5[x]; i++)
                            {
                                if (analizarMovimiento(tablero, MovimientoArrays.ReinaMovimientos5[x].Movimientos[i], escaque.pieza) == false)
                                {
                                    break;
                                }
                            }
                            for (byte i = 0; i < MovimientoArrays.ReinaTotalMovimientos6[x]; i++)
                            {
                                if ( analizarMovimiento(tablero, MovimientoArrays.ReinaMovimientos6[x].Movimientos[i], escaque.pieza) ==false)
                                {
                                    break;
                                }
                            }
                            for (byte i = 0; i < MovimientoArrays.ReinaTotalMovimientos7[x]; i++)
                            {
                                if ( analizarMovimiento(tablero, MovimientoArrays.ReinaMovimientos7[x].Movimientos[i], escaque.pieza) ==false)
                                {
                                    break;
                                }
                            }
                            for (byte i = 0; i < MovimientoArrays.ReinaTotalMovimientos8[x]; i++)
                            {
                                if (analizarMovimiento(tablero, MovimientoArrays.ReinaMovimientos8[x].Movimientos[i], escaque.pieza) == false)
                                {
                                    break;
                                }
                            }

                            break;
                        }
                    case TipoPiezaAjedrez.Rey:
                        {
                            if (escaque.pieza.colorPieza == ColorPieza.Blanco)
                            {
                                posicionReyBlanco = x;
                            }
                            else
                            {
                                poscionReynegro = x;
                            }

                            break;
                        }
                }
            }


            if (tablero.quienMovio == ColorPieza.Blanco)
            {
                generarMovimientosValidosRey(tablero.Escaques[poscionReynegro].pieza, tablero,poscionReynegro);
                generarMovimientosValidosRey(tablero.Escaques[posicionReyBlanco].pieza, tablero,posicionReyBlanco);
            }
            else
            {
                generarMovimientosValidosRey(tablero.Escaques[posicionReyBlanco].pieza, tablero,posicionReyBlanco);
                generarMovimientosValidosRey(tablero.Escaques[poscionReynegro].pieza, tablero,poscionReynegro);
            }


            //Chquemaos todos para ver si es posible el enroque
            generarMovimientosValidosEnroque(tablero, tablero.Escaques[posicionReyBlanco].pieza);
            generarMovimientosValidosEnroque(tablero, tablero.Escaques[poscionReynegro].pieza);
        }
    }
}

  • Tablero.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AjedrezIA.Motor
{
    class Tablero
    {
        internal Cuadrado[] Escaques;
        internal int Puntuacion;
        internal ulong ZobristHash;
        internal bool jaqueNegro;
        internal bool mateNegro;
        internal bool jaqueBlanco;
        internal bool mateBlanco;
        internal bool TAblas;
        internal byte cincuentaMovimientos;
        internal byte movimientoRepetido;
        internal bool enroqueNegro;
        internal bool enroqueBlanco;
        internal bool faseFinaljuego;
        internal Movimiento ultimoMovimiento;
        internal ColorPieza capturaAlPasoColor;
        internal byte anteriorPosicion;
        internal ColorPieza quienMovio;
        internal int contadorMovimientos;

        #region Constructores

        internal Tablero(string fen) : this()
        {
            byte posicion = 0;
            byte cont = 0;

            enroqueBlanco = true;
            enroqueNegro = true;
            byte espaciadores = 0;

            quienMovio = ColorPieza.Blanco;

            if (fen.Contains("a3"))
            {
                capturaAlPasoColor = ColorPieza.Blanco;
                anteriorPosicion = 40;
            }
            else if (fen.Contains("b3"))
            {
                capturaAlPasoColor = ColorPieza.Blanco;
                anteriorPosicion = 41;
            }
            else if (fen.Contains("c3"))
            {
                capturaAlPasoColor = ColorPieza.Blanco;
                anteriorPosicion = 42;
            }
            else if (fen.Contains("d3"))
            {
                capturaAlPasoColor = ColorPieza.Blanco;
                anteriorPosicion = 43;
            }
            else if (fen.Contains("e3"))
            {
                capturaAlPasoColor = ColorPieza.Blanco;
                anteriorPosicion = 44;
            }
            else if (fen.Contains("f3"))
            {
                capturaAlPasoColor = ColorPieza.Blanco;
                anteriorPosicion = 45;
            }
            else if (fen.Contains("g3"))
            {
                capturaAlPasoColor = ColorPieza.Blanco;
                anteriorPosicion = 46;
            }
            else if (fen.Contains("h3"))
            {
                capturaAlPasoColor = ColorPieza.Blanco;
                anteriorPosicion = 47;
            }


            if (fen.Contains("a6"))
            {
                capturaAlPasoColor = ColorPieza.Blanco;
                anteriorPosicion = 16;
            }
            else if (fen.Contains("b6"))
            {
                capturaAlPasoColor = ColorPieza.Blanco;
                anteriorPosicion = 17;
            }
            else if (fen.Contains("c6"))
            {
                capturaAlPasoColor = ColorPieza.Blanco;
                anteriorPosicion = 18;
            }
            else if (fen.Contains("d6"))
            {
                capturaAlPasoColor = ColorPieza.Blanco;
                anteriorPosicion = 19;
            }
            else if (fen.Contains("e6"))
            {
                capturaAlPasoColor = ColorPieza.Blanco;
                anteriorPosicion = 20;
            }
            else if (fen.Contains("f6"))
            {
                capturaAlPasoColor = ColorPieza.Blanco;
                anteriorPosicion = 21;
            }
            else if (fen.Contains("g6"))
            {
                capturaAlPasoColor = ColorPieza.Blanco;
                anteriorPosicion = 22;
            }
            else if (fen.Contains("h6"))
            {
                capturaAlPasoColor = ColorPieza.Blanco;
                anteriorPosicion = 23;
            }

            foreach (char c in fen)
            {

                if (posicion < 64 && cont == 0)
                {
                    if (c == '1' && posicion < 63)
                        posicion++;
                    else if (c == '2' && posicion < 62)
                        posicion += 2;
                    else if (c == '3' && posicion < 61)
                        posicion += 3;
                    else if (c == '4' && posicion < 60)
                         posicion += 4;
                    else if (c == '5' && posicion < 59)
                        posicion += 5;
                    else if (c == '6' && posicion < 58)
                        posicion += 6;
                    else if (c == '7' && posicion < 57)
                        posicion += 7;
                    else if (c == '8' && posicion < 56)
                        posicion += 8;
                    else if (c == 'P')
                    {
                        Escaques[posicion].pieza = new Pieza(TipoPiezaAjedrez.Peon, ColorPieza.Blanco);
                        Escaques[posicion].pieza.Movida = true;
                        posicion++;
                    }
                    else if (c == 'N')
                    {
                        Escaques[posicion].pieza = new Pieza(TipoPiezaAjedrez.Caballo, ColorPieza.Blanco);
                        Escaques[posicion].pieza.Movida = true;
                        posicion++;
                    }
                    else if (c == 'B')
                    {
                        Escaques[posicion].pieza = new Pieza(TipoPiezaAjedrez.Alfil, ColorPieza.Blanco);
                        Escaques[posicion].pieza.Movida = true;
                        posicion++;
                    }
                    else if (c == 'R')
                    {
                        Escaques[posicion].pieza = new Pieza(TipoPiezaAjedrez.Torre, ColorPieza.Blanco);
                        Escaques[posicion].pieza.Movida = true;
                        posicion++;
                    }
                    else if (c == 'Q')
                    {
                        Escaques[posicion].pieza = new Pieza(TipoPiezaAjedrez.Reina, ColorPieza.Blanco);
                        Escaques[posicion].pieza.Movida = true;
                        posicion++;
                    }
                    else if (c == 'K')
                    {
                        Escaques[posicion].pieza = new Pieza(TipoPiezaAjedrez.Rey, ColorPieza.Blanco);
                        Escaques[posicion].pieza.Movida = true;
                        posicion++;
                    }
                    else if (c == 'p')
                    {
                        Escaques[posicion].pieza = new Pieza(TipoPiezaAjedrez.Peon, ColorPieza.Negro);
                        Escaques[posicion].pieza.Movida = true;
                        posicion++;
                    }
                    else if (c == 'n')
                    {
                        Escaques[posicion].pieza = new Pieza(TipoPiezaAjedrez.Caballo, ColorPieza.Negro);
                        Escaques[posicion].pieza.Movida = true;
                        posicion++;
                    }
                    else if (c == 'b')
                    {
                        Escaques[posicion].pieza = new Pieza(TipoPiezaAjedrez.Alfil, ColorPieza.Negro);
                        Escaques[posicion].pieza.Movida = true;
                        posicion++;
                    }
                    else if (c == 'r')
                    {
                        Escaques[posicion].pieza = new Pieza(TipoPiezaAjedrez.Torre, ColorPieza.Negro);
                        Escaques[posicion].pieza.Movida = true;
                        posicion++;
                    }
                    else if (c == 'q')
                    {
                        Escaques[posicion].pieza = new Pieza(TipoPiezaAjedrez.Reina, ColorPieza.Negro);
                        Escaques[posicion].pieza.Movida = true;
                        posicion++;
                    }
                    else if (c == 'k')
                    {
                        Escaques[posicion].pieza = new Pieza(TipoPiezaAjedrez.Rey, ColorPieza.Negro);
                        Escaques[posicion].pieza.Movida = true;
                        posicion++;
                    }
                    else if (c == '/')
                        continue;
                    else if (c == ' ')
                    cont++;
                    
                }
                else
                {
                    if (c == 'w')
                    {
                        quienMovio = ColorPieza.Blanco;
                    }
                    else if (c == 'b')
                    {
                        quienMovio = ColorPieza.Negro;
                    }
                    else if (c == 'K')
                    {
                        if (Escaques[60].pieza != null)
                        {
                            if (Escaques[60].pieza.tipoPieza == TipoPiezaAjedrez.Rey)
                                 Escaques[60].pieza.Movida = false;
                            
                        }

                        if (Escaques[63].pieza != null)
                        {
                            if (Escaques[63].pieza.tipoPieza == TipoPiezaAjedrez.Torre)
                                Escaques[63].pieza.Movida = false;
                            
                        }

                        enroqueBlanco = false;
                    }
                    else if (c == 'Q')
                    {
                        if (Escaques[60].pieza != null)
                        {
                            if (Escaques[60].pieza.tipoPieza == TipoPiezaAjedrez.Rey)
                                Escaques[60].pieza.Movida = false;
                            
                        }

                        if (Escaques[56].pieza != null)
                        {
                            if (Escaques[56].pieza.tipoPieza == TipoPiezaAjedrez.Torre)
                                Escaques[56].pieza.Movida = false;
                            
                        }

                        enroqueBlanco = false;
                    }
                    else if (c == 'k')
                    {
                        if (Escaques[4].pieza != null)
                        {
                            if (Escaques[4].pieza.tipoPieza == TipoPiezaAjedrez.Rey)
                                Escaques[4].pieza.Movida = false;
                            
                        }

                        if (Escaques[7].pieza != null)
                        {
                            if (Escaques[7].pieza.tipoPieza == TipoPiezaAjedrez.Torre)
                                Escaques[7].pieza.Movida = false;
                            
                        }

                        enroqueNegro = false;
                    }
                    else if (c == 'q')
                    {
                        if (Escaques[4].pieza != null)
                        {
                            if (Escaques[4].pieza.tipoPieza == TipoPiezaAjedrez.Rey)
                                Escaques[4].pieza.Movida = false;
                            
                        }

                        if (Escaques[0].pieza != null)
                        {
                            if (Escaques[0].pieza.tipoPieza == TipoPiezaAjedrez.Torre)
                                Escaques[0].pieza.Movida = false;
                            
                        }

                        enroqueNegro = false;
                    }
                    else if (c == ' ')
                     espaciadores++;
                    else if (c == '1' && espaciadores == 4)
                        cincuentaMovimientos = (byte)((cincuentaMovimientos * 10) + 1);
                    else if (c == '2' && espaciadores == 4)
                        cincuentaMovimientos = (byte)((cincuentaMovimientos * 10) + 2);
                    else if (c == '3' && espaciadores == 4)
                        cincuentaMovimientos = (byte)((cincuentaMovimientos * 10) + 3);
                    else if (c == '4' && espaciadores == 4)
                        cincuentaMovimientos = (byte)((cincuentaMovimientos * 10) + 4);
                    else if (c == '5' && espaciadores == 4)
                        cincuentaMovimientos = (byte)((cincuentaMovimientos * 10) + 5);
                    else if (c == '6' && espaciadores == 4)
                        cincuentaMovimientos = (byte)((cincuentaMovimientos * 10) + 6);
                    else if (c == '7' && espaciadores == 4)
                        cincuentaMovimientos = (byte)((cincuentaMovimientos * 10) + 7);
                    else if (c == '8' && espaciadores == 4)
                         cincuentaMovimientos = (byte)((cincuentaMovimientos * 10) + 8);
                    else if (c == '9' && espaciadores == 4)
                        cincuentaMovimientos = (byte)((cincuentaMovimientos * 10) + 9);
                    else if (c == '0' && espaciadores == 4)
                        contadorMovimientos = (byte)((contadorMovimientos * 10) + 0);
                    else if (c == '1' && espaciadores == 5)
                        contadorMovimientos = (byte)((contadorMovimientos * 10) + 1);
                    else if (c == '2' && espaciadores == 5)
                        contadorMovimientos = (byte)((contadorMovimientos * 10) + 2);
                    else if (c == '3' && espaciadores == 5)
                        contadorMovimientos = (byte)((contadorMovimientos * 10) + 3);
                    else if (c == '4' && espaciadores == 5)
                        contadorMovimientos = (byte)((contadorMovimientos * 10) + 4);
                    else if (c == '5' && espaciadores == 5)
                        contadorMovimientos = (byte)((contadorMovimientos * 10) + 5);
                    else if (c == '6' && espaciadores == 5)
                        contadorMovimientos = (byte)((contadorMovimientos * 10) + 6);
                    else if (c == '7' && espaciadores == 5)
                        contadorMovimientos = (byte)((contadorMovimientos * 10) + 7);
                    else if (c == '8' && espaciadores == 5)
                       contadorMovimientos = (byte)((contadorMovimientos * 10) + 8);
                    else if (c == '9' && espaciadores == 5)
                        contadorMovimientos = (byte)((contadorMovimientos * 10) + 9);
                    else if (c == '0' && espaciadores == 5)
                        contadorMovimientos = (byte)((contadorMovimientos * 10) + 0);
                }
            }
        }

        internal Tablero()
        {
            Escaques = new Cuadrado[64];

            for (byte i = 0; i < 64; i++)
            {
                Escaques[i] = new Cuadrado();
            }

            ultimoMovimiento = new Movimiento();
        }

        private Tablero(Cuadrado[] escaques)
        {
            Escaques = new Cuadrado[64];

            for (byte x = 0; x < 64; x++)
               if (escaques[x].pieza != null)
                  Escaques[x].pieza = new Pieza(escaques[x].pieza);
        }
        
        internal Tablero(int punt) : this()
        {
            Puntuacion = punt;
        }

     
        internal Tablero(Tablero tablero)
        {
            Escaques = new Cuadrado[64];

            for (byte x = 0; x < 64; x++)
            {
                if (tablero.Escaques[x].pieza != null)
                {
                    Escaques[x] = new Cuadrado(tablero.Escaques[x].pieza);
                }
            }
            faseFinaljuego = tablero.faseFinaljuego;

            cincuentaMovimientos = tablero.cincuentaMovimientos;
            movimientoRepetido = tablero.movimientoRepetido;

            enroqueBlanco = tablero.enroqueBlanco;
            enroqueNegro = tablero.enroqueNegro;

            jaqueNegro = tablero.jaqueNegro;
            jaqueBlanco = tablero.jaqueBlanco;
            TAblas = tablero.TAblas;
            mateBlanco = tablero.mateBlanco;
            mateNegro = tablero.mateNegro;
            quienMovio = tablero.quienMovio;
            anteriorPosicion = tablero.anteriorPosicion;
            capturaAlPasoColor = tablero.capturaAlPasoColor;

            ZobristHash = tablero.ZobristHash;

            Puntuacion = tablero.Puntuacion;

            ultimoMovimiento = new Movimiento(tablero.ultimoMovimiento);

            contadorMovimientos = tablero.contadorMovimientos;
        }

        #endregion

        #region Metodos Privados

        private static bool PromocionarPeones(Tablero tablero, Pieza pieza, byte posDestino, TipoPiezaAjedrez promocionarAPieza)
        {
            if (pieza.tipoPieza == TipoPiezaAjedrez.Peon)
            {
                if (posDestino < 8)
                {
                    tablero.Escaques[posDestino].pieza.tipoPieza = promocionarAPieza;
                    return true;
                }
                if (posDestino > 55)
                {
                    tablero.Escaques[posDestino].pieza.tipoPieza = promocionarAPieza;
                    return true;
                }
            }

            return false;
        }

        private static void RegistrarCambioPaso(ColorPieza coloPieza, TipoPiezaAjedrez tipoPieza, Tablero tablero, byte posicionOrigen, byte posicionDestino)
        {
            //Gaurdar cambio de paso si el peon fue movido
            if (tipoPieza == TipoPiezaAjedrez.Peon)
            {
                //resetear cincuenta movimientos mueves el peon
                tablero.cincuentaMovimientos = 0;

                int diferencia = posicionOrigen - posicionDestino;

                if (diferencia == 16 || diferencia == -16)
                {
                    tablero.anteriorPosicion = (byte)(posicionDestino + (diferencia / 2));
                    tablero.capturaAlPasoColor = coloPieza;
                }
            }
        }

        private static bool asignarMovimientoCambioPaso(Tablero tablero, byte posicionDestino, ColorPieza colorPieza)
        {
       
            if (tablero.anteriorPosicion == posicionDestino)
            {
                //posibilidad cambio de paso
                if (colorPieza != tablero.capturaAlPasoColor)
                {
                    int pieceLocationOffset = 8;

                    if (tablero.capturaAlPasoColor == ColorPieza.Blanco)
                        pieceLocationOffset = -8;
                    

                    posicionDestino = (byte)(posicionDestino + pieceLocationOffset);

                    Cuadrado escaque = tablero.Escaques[posicionDestino];
                    tablero.ultimoMovimiento.piezaComida = new PiezaComida(escaque.pieza.colorPieza, escaque.pieza.tipoPieza, escaque.pieza.Movida, posicionDestino);
                    tablero.Escaques[posicionDestino].pieza = null;

                    //Resetear a 50 movimientos si capturamos
                    tablero.cincuentaMovimientos = 0;

                    return true;
                }
            }

            return false;
        }

        private static void Enroque(Tablero tablero, Pieza pieza, byte posicionOrigen, byte posicionDestino)
        {
            if (pieza.tipoPieza != TipoPiezaAjedrez.Rey)
                return;
            

            //Comprobamos si es enroque
            if (pieza.colorPieza == ColorPieza.Blanco && posicionOrigen == 60)
            {
              
                if (posicionDestino == 62)
                {
                  
                    if (tablero.Escaques[63].pieza != null)
                    {
                        tablero.Escaques[61].pieza = tablero.Escaques[63].pieza;
                        tablero.Escaques[63].pieza = null;
                        tablero.enroqueBlanco = true;
                        tablero.ultimoMovimiento.moviendoPiezaSecundaria = new MovimientoPieza(tablero.Escaques[61].pieza.colorPieza, tablero.Escaques[61].pieza.tipoPieza, tablero.Escaques[61].pieza.Movida, 63, 61);
                        tablero.Escaques[61].pieza.Movida = true;
                        return;
                    }
                }
                //enroque izquierda
                else if (posicionDestino == 58)
                {
                    //Movemos torre
                    if (tablero.Escaques[56].pieza != null)
                    {
                        tablero.Escaques[59].pieza = tablero.Escaques[56].pieza;
                        tablero.Escaques[56].pieza = null;
                        tablero.enroqueBlanco = true;
                        tablero.ultimoMovimiento.moviendoPiezaSecundaria = new MovimientoPieza(tablero.Escaques[59].pieza.colorPieza, tablero.Escaques[59].pieza.tipoPieza, tablero.Escaques[59].pieza.Movida, 56, 59);
                        tablero.Escaques[59].pieza.Movida = true;
                        return;
                    }
                }
            }
            else if (pieza.colorPieza == ColorPieza.Negro && posicionOrigen == 4)
            {
                if (posicionDestino == 6)
                {
                  
                    if (tablero.Escaques[7].pieza != null)
                    {
                        tablero.Escaques[5].pieza = tablero.Escaques[7].pieza;
                        tablero.Escaques[7].pieza = null;
                        tablero.enroqueNegro = true;
                        tablero.ultimoMovimiento.moviendoPiezaSecundaria = new MovimientoPieza(tablero.Escaques[5].pieza.colorPieza, tablero.Escaques[5].pieza.tipoPieza, tablero.Escaques[5].pieza.Movida, 7, 5);
                        tablero.Escaques[5].pieza.Movida = true;
                        return;
                    }
                }
                //enroqe izquierda 
                else if (posicionDestino == 2)
                {
                    
                    //Ok we are casteling we need to move the Rook
                    if (tablero.Escaques[0].pieza != null)
                    {
                        tablero.Escaques[3].pieza = tablero.Escaques[0].pieza;
                        tablero.Escaques[0].pieza = null;
                        tablero.enroqueNegro = true;
                        tablero.ultimoMovimiento.moviendoPiezaSecundaria = new MovimientoPieza(tablero.Escaques[3].pieza.colorPieza, tablero.Escaques[3].pieza.tipoPieza, tablero.Escaques[3].pieza.Movida, 0, 3);
                        tablero.Escaques[3].pieza.Movida = true;
                        return;
                    }
                }
            }

            return;
        }

        #endregion

        #region Metodos internos
              
        internal Tablero Clonar()
        {
            Tablero clonarTablero = new Tablero(Escaques);
            clonarTablero.faseFinaljuego = faseFinaljuego;
            clonarTablero.quienMovio = quienMovio;
            clonarTablero.contadorMovimientos = contadorMovimientos;
            clonarTablero.cincuentaMovimientos = cincuentaMovimientos;
            clonarTablero.ZobristHash = ZobristHash;
            clonarTablero.enroqueNegro = enroqueNegro;
            clonarTablero.enroqueBlanco = enroqueBlanco;
            return clonarTablero;
        }

        internal static Movimiento MoverPieza(Tablero tablero, byte posicionOrigen, byte posicionDestino, TipoPiezaAjedrez promocionarAPieza)
        {
            Pieza pieza = tablero.Escaques[posicionOrigen].pieza;
            //almacenamos ultimo movimiento
            tablero.ultimoMovimiento = new Movimiento();
            tablero.cincuentaMovimientos++;
            if (pieza.colorPieza == ColorPieza.Negro)
                tablero.contadorMovimientos++;
                 
            if (tablero.anteriorPosicion > 0)
            {
                tablero.ultimoMovimiento.capturaAlPasoOcurrio = asignarMovimientoCambioPaso(tablero, posicionDestino, pieza.colorPieza);
            }

            if (!tablero.ultimoMovimiento.capturaAlPasoOcurrio)
            {
                Cuadrado escaque = tablero.Escaques[posicionDestino];

                if (escaque.pieza != null)
                {
                    tablero.ultimoMovimiento.piezaComida = new PiezaComida(escaque.pieza.colorPieza, escaque.pieza.tipoPieza,escaque.pieza.Movida, posicionDestino);
                    tablero.cincuentaMovimientos = 0;
                }
                else
                    tablero.ultimoMovimiento.piezaComida = new PiezaComida(ColorPieza.Blanco, TipoPiezaAjedrez.Ninguna, false,posicionDestino);
            }

            tablero.ultimoMovimiento.moviendoPiezaPrincipal = new MovimientoPieza(pieza.colorPieza, pieza.tipoPieza, pieza.Movida, posicionOrigen, posicionDestino);

            //eliminamos posción origen
            tablero.Escaques[posicionOrigen].pieza = null;

            //movemos pieza a la nueva posición
            pieza.Movida = true;
            pieza.Seleccionada = false;
            tablero.Escaques[posicionDestino].pieza = pieza;
            tablero.anteriorPosicion = 0;

            if (pieza.tipoPieza == TipoPiezaAjedrez.Peon)
            {
                tablero.cincuentaMovimientos = 0;
                RegistrarCambioPaso(pieza.colorPieza, pieza.tipoPieza, tablero, posicionOrigen, posicionDestino);
            }

            tablero.quienMovio = tablero.quienMovio == ColorPieza.Blanco ? ColorPieza.Negro : ColorPieza.Blanco;

            Enroque(tablero, pieza, posicionOrigen, posicionDestino);

            if (PromocionarPeones(tablero, pieza, posicionDestino, promocionarAPieza))
                tablero.ultimoMovimiento.peonPromocionado = true;
            else
                tablero.ultimoMovimiento.peonPromocionado = false;
            
            if (tablero.cincuentaMovimientos >= 50)
                tablero.TAblas = true;

            return tablero.ultimoMovimiento;
        }

        private static string dameLetraColumna(byte columna)
        {
            switch (columna)
            {
                case 0:
                    return "a";
                case 1:
                    return "b";
                case 2:
                    return "c";
                case 3:
                    return "d";
                case 4:
                    return "e";
                case 5:
                    return "f";
                case 6:
                    return "g";
                case 7:
                    return "h";
                default:
                    return "a";
            }
        }

        internal static string Fen(bool tableroSolo, Tablero tablero)
        {
            string respuesta = String.Empty;
            byte escaquesBlancos = 0;

            for (byte x = 0; x < 64; x++)
            {
                byte posicion = x;

                if (tablero.Escaques[posicion].pieza != null)
                {
                    if (escaquesBlancos > 0)
                    {
                        respuesta += escaquesBlancos.ToString();
                        escaquesBlancos = 0;
                    }

                    if (tablero.Escaques[posicion].pieza.colorPieza == ColorPieza.Negro)
                    {
                        respuesta += Pieza.dameLetraPieza(tablero.Escaques[posicion].pieza.tipoPieza).ToLower();
                    }
                    else
                    {
                        respuesta += Pieza.dameLetraPieza(tablero.Escaques[posicion].pieza.tipoPieza);
                    }
                }
                else
                {
                    escaquesBlancos++;
                }

                if (x % 8 == 7)
                {
                    if (escaquesBlancos > 0)
                    {
                        respuesta += escaquesBlancos.ToString();
                        respuesta += "/";
                        escaquesBlancos = 0;
                    }
                    else
                    {
                        if (x > 0 && x != 63)
                        {
                            respuesta += "/";
                        }
                    }
                }
            }

            if (tablero.quienMovio == ColorPieza.Blanco)
            {
                respuesta += " w ";
            }
            else
            {
                respuesta += " b ";
            }

            string espacios = "";

            if (tablero.enroqueBlanco == false)
            {
                if (tablero.Escaques[60].pieza != null)
                {
                    if (tablero.Escaques[60].pieza.Movida == false)
                    {
                        if (tablero.Escaques[63].pieza != null)
                        {
                            if (tablero.Escaques[63].pieza.Movida == false)
                            {
                                respuesta += "K";
                                espacios = " ";
                            }
                        }
                        if (tablero.Escaques[56].pieza != null)
                        {
                            if (tablero.Escaques[56].pieza.Movida == false)
                            {
                                respuesta += "Q";
                                espacios = " ";
                            }
                        }
                    }
                }
            }

            if (tablero.enroqueNegro == false)
            {
                if (tablero.Escaques[4].pieza != null)
                {
                    if (tablero.Escaques[4].pieza.Movida == false)
                    {
                        if (tablero.Escaques[7].pieza != null)
                        {
                            if (tablero.Escaques[7].pieza.Movida == false)
                            {
                                respuesta += "k";
                                espacios = " ";
                            }
                        }
                        if (tablero.Escaques[0].pieza != null)
                        {
                            if (tablero.Escaques[0].pieza.Movida == false)
                            {
                                respuesta += "q";
                                espacios = " ";
                            }
                        }
                    }
                }


            }

            if (respuesta.EndsWith("/"))
            {
                respuesta.TrimEnd('/');
            }


            if (tablero.anteriorPosicion != 0)
            {
                respuesta += espacios + dameLetraColumna((byte)(tablero.anteriorPosicion % 8)) + "" + (byte)(8 - (byte)(tablero.anteriorPosicion / 8)) + " ";
            }
            else
            {
                respuesta += espacios + "- ";
            }

            if (!tableroSolo)
            {
                respuesta += tablero.cincuentaMovimientos + " ";
                respuesta += tablero.contadorMovimientos + 1;
            }
            return respuesta.Trim();
        }

        #endregion
    }
}

  • Engine.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AjedrezIA.Motor
{
    class Engine
    {
        internal Tablero tablero;
        internal Tablero anteriorTablero;
        public ColorPieza Humano;

        public ColorPieza quienMovio
        {
            get { return tablero.quienMovio; }
            set { tablero.quienMovio = value; }
        }

        public Engine()
        {
            InicializaTablero("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
        }

        public Engine(string fen)
        {
            InicializaTablero(fen);
        }

        private void InicializaTablero(string fen)
        {
            Humano = ColorPieza.Blanco;
            tablero = new Tablero(fen);
            tablero.quienMovio = ColorPieza.Blanco;
            MovimientoPiezas.IniciarMovimientoPieza();
            GenerarMovimientosValidos();
        }

        public byte[] ObtenerMovimientosAnteriores()
        {
            if (tablero == null)
                return null;
            byte[] arrayRespuesta = new byte[2];

            arrayRespuesta[0] = (byte)(tablero.anteriorPosicion % 8);
            arrayRespuesta[1] = (byte)(tablero.anteriorPosicion / 8);

            return arrayRespuesta;
        }

        public bool EsMovimientoValido(byte columnaInicial, byte filaInicial, byte columnaDestino, byte filaDestino)
        {
            if (tablero == null)
                 return false;
           
            if (tablero.Escaques == null)
                return false;
            
            byte indice = DamePosicionTablero(columnaInicial, filaInicial);

            if (tablero.Escaques[indice].pieza == null)
                 return false;
           
            foreach (byte bs in tablero.Escaques[indice].pieza.movimientosValidos)
                if (bs % 8 == columnaDestino)
                   if ((byte)(bs / 8) == filaDestino)
                       return true;
                  
            indice = DamePosicionTablero(columnaDestino, filaDestino);

            if (indice == tablero.anteriorPosicion)
               return true;
            

            return false;
        }

        public TipoPiezaAjedrez dameTipoPieza(byte columnaTablero, byte filaTablero)
        {
            byte indice = DamePosicionTablero(columnaTablero, filaTablero);

            if (tablero.Escaques[indice].pieza == null)
               return TipoPiezaAjedrez.Ninguna;
           
            return tablero.Escaques[indice].pieza.tipoPieza;
        }

        public TipoPiezaAjedrez dameTipoPieza(byte indice)
        {
            if (tablero.Escaques[indice].pieza == null)
                  return TipoPiezaAjedrez.Ninguna;

            return tablero.Escaques[indice].pieza.tipoPieza;
        }

        public ColorPieza dameColorPieza(byte columnaTablero, byte filaTablero)
        {
            byte indice = DamePosicionTablero(columnaTablero, filaTablero);

            if (tablero.Escaques[indice].pieza == null)
               return ColorPieza.Blanco;
            
            return tablero.Escaques[indice].pieza.colorPieza;
        }

        public ColorPieza dameColorPieza(byte indice)
        {
            if (tablero.Escaques[indice].pieza == null)
                 return ColorPieza.Blanco;
            
            return tablero.Escaques[indice].pieza.colorPieza;
        }

        public bool damePiezaSeleccionada(byte columnaTablero, byte filaTablero)
        {
            byte indice = DamePosicionTablero(columnaTablero, filaTablero);

            if (tablero.Escaques[indice].pieza == null)
               return false;

            return tablero.Escaques[indice].pieza.Seleccionada;
        }

        public byte[][] dameMovimientosValidos(byte columnaTablero, byte filaTablero)
        {
            byte indice = DamePosicionTablero(columnaTablero, filaTablero);
            if (tablero.Escaques[indice].pieza ==null)
                        return null;
            

            byte[][] arrayRespuesta = new byte[tablero.Escaques[indice].pieza.movimientosValidos.Count][];
            int cont = 0;

            foreach (byte escaque in tablero.Escaques[indice].pieza.movimientosValidos)
            {
                arrayRespuesta[cont] = new byte[2];
                arrayRespuesta[cont][0] = (byte)(escaque % 8);
                arrayRespuesta[cont][1] = (byte)(escaque / 8);
                cont++;
            }

            return arrayRespuesta;
        }

        public void asignarPosicionAPieza (byte columnaTablero, byte filaTablero, bool seleccion)
        {
            byte posicion = DamePosicionTablero(columnaTablero, filaTablero);

            if (tablero.Escaques[posicion].pieza == null)
                return;
            
            if (tablero.Escaques[posicion].pieza.colorPieza != quienMovio)
                 return;
            
            tablero.Escaques[posicion].pieza.Seleccionada = seleccion;
        }

        public bool moverPieza(byte columnaOrigen, byte filaOrigen, byte columnaDestino, byte filaDestino)
        {
            byte posicionOrigen = (byte)(columnaOrigen + (filaOrigen * 8));
            byte posicionDestino = (byte)(columnaDestino + (filaDestino * 8));
            Pieza pieza = tablero.Escaques[posicionOrigen].pieza;
            anteriorTablero = new Tablero(tablero);
            Tablero.MoverPieza(tablero, posicionOrigen, posicionDestino, TipoPiezaAjedrez.Reina);
            MovimientosValidosPiezas.generarMovimientosValidos(tablero);

            if (pieza.colorPieza == ColorPieza.Blanco)
            {
                if (tablero.jaqueBlanco)
                {
                    //Movimiento no válido
                    tablero = new Tablero(anteriorTablero);
                    MovimientosValidosPiezas.generarMovimientosValidos(tablero);
                    return false;
                }
            }
            else if (pieza.colorPieza == ColorPieza.Negro)
            {
                if (tablero.jaqueNegro)
                {
                    //Movimiento no válido
                    tablero = new Tablero(anteriorTablero);
                    MovimientosValidosPiezas.generarMovimientosValidos(tablero);
                    return false;
                }
            }

            return true;

        }

        private void GenerarMovimientosValidos()
        {
            MovimientosValidosPiezas.generarMovimientosValidos(tablero);
        }

        private static byte DamePosicionTablero(byte columnaTablero, byte filaTablero)
        {
            return (byte)(columnaTablero + (filaTablero * 8));
        }
    }
}

  • GraphicsBuffer.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AjedrezIA
{
    public sealed class GraphicsBuffer
    {
        private Graphics graphics;
        private int height;
        private Bitmap memoryBitmap;
        private int width;

        public Graphics Graphics
        {
            get { return graphics; }
        }

        public void CreateGraphicsBuffer(Graphics g, int W, int H)
        {
            if (memoryBitmap != null)
            {
                memoryBitmap.Dispose();
                memoryBitmap = null;
            }

            if (graphics != null)
            {
                graphics.Dispose();
                graphics = null;
            }

            if (W == 0 || H == 0)
                return;


            if ((W != width) || (H != height))
            {
                width = W;
                height = H;

                memoryBitmap = new Bitmap(width, height);
                graphics = Graphics.FromImage(memoryBitmap);
            }
        }

        public void Render(Graphics g)
        {
            if (memoryBitmap != null)
            {
                g.DrawImage(memoryBitmap, new Rectangle(0, 0, width, height), 0, 0, width, height, GraphicsUnit.Pixel);
            }
        }
    }
}

  • FormAjedrez
using AjedrezIA.Motor;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AjedrezIA
{
    public partial class FormAjedrez : Form
    {
        public ColorPieza WhosMove;


        public FormAjedrez()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
       

            Opacity = 1;
        }

        private void MainForm_ResizeEnd(object sender, EventArgs e)
        {
          tableroAjedrez.Refresh();
        }

      

        private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
            {
                WindowState = FormWindowState.Normal;
            }
            else if (WindowState == FormWindowState.Normal)
            {
                WindowState = FormWindowState.Minimized;
            }
        }

  
    }
}

Curso .NET Core en C# - 34.Creamos nuestro propio log

34.Creamos nuestro propio log Hola a todos. En este curso, analizaremos todos los conceptos básicos, intermedios y avanzados de  ASP.NET...