Pop

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

78. Inteligencia Artificial (7).Lógica para evitar un jaque(2)

 -  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 la entrada anterior enseñamos a nuestro agente dos mecanismos para evitar el jaque de nuestro adversario.

- En esta entrada aprenderemos a evitar el jaque del rival interponiendo una pieza en el camino  entre el rey y la pieza que nos ataca .Existen varias casuísticas que son las que implementamos en el vídeo. Se ven mejor con unas imágenes. Recordad que nuestro tablero al fin y al cabo es una matriz de de 8x8.


  • Jaque con una pieza que hace ataque en dirección vertical a nuestro rey

  • Jaque con un pieza que ataca en dirección horizontal a nuestro rey

  • Jaque con una pieza que ataca en dirección diagonal a nuestro rey

  • En el vídeo os muestro el código aplicado para evitar el jaque cuando se produzca alguna de las situaciones mostradas en las imágenes: 



- Una vez comprendido el objetivo de este capítulo os dejo el código de las dos funciones que hemos modificado para mejorar la lógica de nuestro agente en situaciones de jaque. 

        //Obtener todos los posibles movimientos de todas las piezas negras y de momento genero un movimiento aleatorio
        #region Nuevo
        public void generarMovimientoAleatorio()
        {

            int posinicial = 0;
            int columnaJaque = 0;
            ArrayList arrayPiezas = new ArrayList();
            ArrayList arrayPosInicialPiezas = new ArrayList();
            ArrayList arrayValorMovimiento = new ArrayList();

            ArrayList arraypiezasTaponanJaque = new ArrayList();
            ArrayList arraypiezasPosInicialTaponanJaque = new ArrayList();
            ArrayList arrayPosicionpiezasTaponanJaque = new ArrayList();


            int posicionJaque = 0;
            int posicionReyJaque = 0;
            Boolean SiJaque = false;
            Pieza piezaAux = new Pieza();
            Pieza reyAux = null;

            


            //Si nos dan jaque buscamos que pieza nos lo esta dando y en que posicion por si al calcular los movimientos de las piezas negras pudieramos comernos la pieza.También seleccionamos la pieza rey.
            if (motor.tablero.jaqueNegro)
            {

                foreach (Cuadrado c in motor.tablero.Escaques)
                {

                    //Guardamos en variable auxiliar la pieza rey negro
                    if (c.pieza != null && c.pieza.colorPieza == ColorPieza.Negro && c.pieza.tipoPieza == TipoPiezaAjedrez.Rey )
                                    reyAux = c.pieza;
                  

                    //Buscamos que pieza nos esta dando jaque
                    if (c.pieza != null && c.pieza.colorPieza == ColorPieza.Blanco && c.pieza.DandoJaque == true)
                    {
                        SiJaque = true;
                        piezaAux = c.pieza;
                    }
                    if(!SiJaque)
                    posicionJaque++;

                    if(reyAux==null)
                    posicionReyJaque++;
                }

                if (!SiJaque)
                    posicionJaque = -1;
            }


            //Recorremos el tablero y guardamos la posicion de las piezas negras con algun movimiento valido 
            foreach (Cuadrado c in motor.tablero.Escaques)
            {

                if (c.pieza != null && c.pieza.colorPieza == ColorPieza.Negro && c.pieza.movimientosValidos.Count > 0)
                {

                    arrayPiezas.Add(c.pieza);
                    arrayPosInicialPiezas.Add(posinicial);
                    arrayValorMovimiento.Add(valorMovimiento(c.pieza, motor.tablero, posicionJaque,posinicial));

                    //Vemos el tipo de pieza que nos esta dando jaque.Hemos obtenido anteriormente su posición y la del rey.
                    //Necesitamos obtener todos los movimientos de las piezas negras.Las que coincidan en trayectoria mover la de menor peso
                    if (SiJaque)
                    {

                        for (int i = 0; i < c.pieza.movimientosValidos.Count; i++)
                        {
                            //Jaque cuando la posicion del rey en la matriz sea menor que la de la pieza que ataca
                            if (posicionJaque > posicionReyJaque)
                            {
                                columnaJaque = Convert.ToByte(posicionReyJaque % 8);
                             
                               //Jaque en vertical
                                for (int j = posicionJaque; j >= posicionReyJaque && Convert.ToByte(posicionJaque % 8)== columnaJaque; j = j - 8)
                                {
                                    if (c.pieza.movimientosValidos.ElementAt(i) == j)
                                    {
                                        arraypiezasTaponanJaque.Add(c.pieza);
                                        arraypiezasPosInicialTaponanJaque.Add(posinicial);
                                        arrayPosicionpiezasTaponanJaque.Add(j);
                                       
                                    }
                                }

                                //jaque en horizontal.Deben estar en la misma fila de la matriz por lo tanto al diferencia no puede ser mayor a 7
                                if ((posicionJaque - posicionReyJaque <= 7) && (posicionJaque - posicionReyJaque >= 0))
                                {

                                    for (int j = posicionReyJaque; j <= posicionJaque; j++)
                                    {
                                        if (c.pieza.movimientosValidos.ElementAt(i) == j)
                                        {
                                            arraypiezasTaponanJaque.Add(c.pieza);
                                            arraypiezasPosInicialTaponanJaque.Add(posinicial);
                                            arrayPosicionpiezasTaponanJaque.Add(j);
                                        }
                                    }

                                }
                                //jaque en diagonal.Cuando la resta entre la posicion de la pieza que da jaque y el rey da 9 o multiplo de 9 o da 7 o múltiplo de 7
                                if ((posicionJaque - posicionReyJaque) % 9 ==0 )
                                {
                                    for (int j = posicionJaque; j >= posicionReyJaque; j = j - 9)
                                    {
                                        if (c.pieza.movimientosValidos.ElementAt(i) == j)
                                        {
                                            arraypiezasTaponanJaque.Add(c.pieza);
                                            arraypiezasPosInicialTaponanJaque.Add(posinicial);
                                            arrayPosicionpiezasTaponanJaque.Add(j);
                                        }
                                    }
                                }

                                if ((posicionJaque - posicionReyJaque) % 7 == 0)
                                {
                                    for (int j = posicionJaque; j >= posicionReyJaque; j = j - 7)
                                    {
                                        if (c.pieza.movimientosValidos.ElementAt(i) == j)
                                        {
                                            arraypiezasTaponanJaque.Add(c.pieza);
                                            arraypiezasPosInicialTaponanJaque.Add(posinicial);
                                            arrayPosicionpiezasTaponanJaque.Add(j);
                                        }
                                    }
                                }


                            } //Jaque cuando la posicion del rey en la matriz sea mayor que la de la pieza que ataca
                            else
                            {
                                columnaJaque = Convert.ToByte(posicionReyJaque % 8);
                                
                                //Jaque en vertical
                                for (int j = posicionReyJaque; j <= posicionJaque  && Convert.ToByte(posicionReyJaque % 8) == columnaJaque;  j = j + 8)
                                {
                                    if (c.pieza.movimientosValidos.ElementAt(i) == j)
                                    {
                                        arraypiezasTaponanJaque.Add(c.pieza);
                                        arraypiezasPosInicialTaponanJaque.Add(posinicial);
                                        arrayPosicionpiezasTaponanJaque.Add(j);
                                    }
                                }

                                //jaque en horizontal.Deben estar en la misma fila de la matriz por lo tanto al diferencia no puede ser mayor a 7
                                if ((posicionReyJaque - posicionJaque <= 7) && (posicionReyJaque - posicionJaque >=0))
                                {

                                    for (int j = posicionJaque; j <= posicionReyJaque; j++)
                                    {
                                        if (c.pieza.movimientosValidos.ElementAt(i) == j)
                                        {
                                            arraypiezasTaponanJaque.Add(c.pieza);
                                            arraypiezasPosInicialTaponanJaque.Add(posinicial);
                                            arrayPosicionpiezasTaponanJaque.Add(j);
                                        }
                                    }

                                }

                                //jaque en diagonal.Cuando la resta entre la posicion del rey y la pieza que da jaque da 9 o multiplo de 9 o da 7 o múltiplo de 7
                                if (( posicionReyJaque- posicionJaque) % 9 == 0)
                                {
                                    for (int j = posicionReyJaque; j >= posicionJaque; j = j - 9)
                                    {
                                        if (c.pieza.movimientosValidos.ElementAt(i) == j)
                                        {
                                            arraypiezasTaponanJaque.Add(c.pieza);
                                            arraypiezasPosInicialTaponanJaque.Add(posinicial);
                                            arrayPosicionpiezasTaponanJaque.Add(j);
                                        }
                                    }
                                }

                                if ((posicionReyJaque - posicionJaque) % 7 == 0)
                                {
                                    for (int j = posicionReyJaque; j >= posicionJaque; j = j - 7)
                                    {
                                        if (c.pieza.movimientosValidos.ElementAt(i) == j)
                                        {
                                            arraypiezasTaponanJaque.Add(c.pieza);
                                            arraypiezasPosInicialTaponanJaque.Add(posinicial);
                                            arrayPosicionpiezasTaponanJaque.Add(j);
                                        }
                                    }
                                }

                            }
                       }
                     }
                }

                posinicial++;
            }

            //Recorremos el array con los valores de los movimientos y elegimos el que mayor valor tenga si no elegimos un movimiento aleatorio
            int maxValor = 0;
            int posicionArray = 0;
            for (int i = 0; i < arrayValorMovimiento.Count; i++)
            {

                if (((MovimientoSeleccionado)arrayValorMovimiento[i]).ValorMovimiento > maxValor)
                {
                    maxValor = ((MovimientoSeleccionado)arrayValorMovimiento[i]).ValorMovimiento;
                    posicionArray = i;

                }
            }


            byte columnainicio = 0;
            byte filaInicio = 0;
            byte columnaDestino = 0;
            byte filaDestino = 0;
            int posicionInicial = 0;
            int posPiezaTapona = 0;
            int menorValor = 1000000;

            //Si nos estan dando jaque y no nos podemos comer la pieza que nos lo esta dando movemos el rey o ponemos una delante si vale menos  que la que da jaque
            if (SiJaque && maxValor != 100000)
            {
                if (arraypiezasTaponanJaque.Count > 0)
                {
                    for (int i = 0; i < arraypiezasTaponanJaque.Count; i++)
                    {
                        if ( ((Pieza) arraypiezasTaponanJaque[i]).valorPieza< menorValor)
                        {
                            menorValor = ((Pieza)arraypiezasTaponanJaque[i]).valorPieza;
                            posPiezaTapona = i;

                        }
                    }
                    
                    posicionInicial = Convert.ToInt32(arraypiezasPosInicialTaponanJaque[posPiezaTapona]);
                    columnainicio = Convert.ToByte(posicionInicial % 8);
                    filaInicio = Convert.ToByte(posicionInicial / 8);
                    columnaDestino = Convert.ToByte(Convert.ToInt32(arrayPosicionpiezasTaponanJaque[posPiezaTapona]) % 8);
                    filaDestino = Convert.ToByte(Convert.ToInt32(arrayPosicionpiezasTaponanJaque[posPiezaTapona]) / 8);

                }
                else
                {
                    if(reyAux.movimientosValidos.Count>0)
                    { 
                        Random random = new Random();
                        columnainicio = Convert.ToByte(posicionReyJaque % 8);
                        filaInicio = Convert.ToByte(posicionReyJaque / 8);
                        int posicionAleatoriaRey = random.Next(0, reyAux.movimientosValidos.Count);
                        columnaDestino = Convert.ToByte((reyAux.movimientosValidos.ElementAt(posicionAleatoriaRey) % 8));
                        filaDestino = Convert.ToByte((reyAux.movimientosValidos.ElementAt(posicionAleatoriaRey) / 8));
                    }

                }


            }
            else
            {

                //Si no nos aporta valor movemos cualquier ficha aleatoriamente
                if (maxValor > 0)
                {
                    posicionInicial = Convert.ToInt32(arrayPosInicialPiezas[posicionArray]);
                    columnainicio = Convert.ToByte(posicionInicial % 8);
                    filaInicio = Convert.ToByte(posicionInicial / 8);
                    columnaDestino = Convert.ToByte(((MovimientoSeleccionado)arrayValorMovimiento[posicionArray]).PosicionDestino % 8);
                    filaDestino = Convert.ToByte(((MovimientoSeleccionado)arrayValorMovimiento[posicionArray]).PosicionDestino / 8);
                }
                else
                {
                    //Seleccionamos aleatoriamente la pieza a mover y obtenemos columna y fila inicial
                    Random random = new Random();
                    int piezaAletoria = random.Next(0, arrayPiezas.Count);
                    posicionInicial = Convert.ToInt32(arrayPosInicialPiezas[piezaAletoria]);
                    columnainicio = Convert.ToByte(posicionInicial % 8);
                    filaInicio = Convert.ToByte(posicionInicial / 8);

                    ////Dentro de los movimientos validos selecionamos aleatoriamente alguno de ellos.Primero hacemos un random de los posible movimientos y 
                    ////luego seleccionamos uno de ellos
                    int posicionAleatoria = random.Next(0, ((Pieza)arrayPiezas[piezaAletoria]).movimientosValidos.Count);
                    columnaDestino = Convert.ToByte(((Pieza)arrayPiezas[piezaAletoria]).movimientosValidos.ElementAt(posicionAleatoria) % 8);
                    filaDestino = Convert.ToByte(((Pieza)arrayPiezas[piezaAletoria]).movimientosValidos.ElementAt(posicionAleatoria) / 8);
                }
            }
             motor.moverPieza(columnainicio, filaInicio, columnaDestino, filaDestino);


        }

        //Funcion para calcular el valor de un movimiento y la posicion detino que la almacenamos en el nuevo objeto MovimientoSeleccionado
        private MovimientoSeleccionado valorMovimiento(Pieza piezaMover, Tablero tablero , int PosicionJaque, int posicionInicialPiezaMovemos )
        {
            MovimientoSeleccionado mov = new MovimientoSeleccionado();
            mov.ValorMovimiento = 0;
            int posicionpiezaBlanca = 0;
            int valorMovimientoAux = 0;
            //si en alguno de los posibles movimientos hay una pieza que se pueda comer guardamos su peso y posicion
            for (int i = 0; i < piezaMover.movimientosValidos.Count; i++)
            {
                posicionpiezaBlanca = 0;
                foreach (Cuadrado c in motor.tablero.Escaques)
                {
                    if (c.pieza != null && c.pieza.colorPieza == ColorPieza.Blanco && piezaMover.movimientosValidos.ElementAt(i)==posicionpiezaBlanca)
                    {
                        //Si nos podemos comer una pieza que nos esta haciendo jaque le damos el máximo valor
                        if (posicionpiezaBlanca == PosicionJaque)
                            valorMovimientoAux = 100000;
                        else
                        {
                            if(c.pieza.valorPieza >= tablero.Escaques[posicionInicialPiezaMovemos].pieza.valorPieza)
                                valorMovimientoAux = c.pieza.valorPieza;
                        }
                        if (valorMovimientoAux > mov.ValorMovimiento)
                            mov.ValorMovimiento = valorMovimientoAux;

                        mov.PosicionDestino = posicionpiezaBlanca;
                    }
                    posicionpiezaBlanca++;
                }
            }
            return mov;
        }



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

77. Inteligencia Artificial (6).Lógica para evitar un jaque(1)

 -  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 la entrada anterior enseñamos a nuestro agente  a comer piezas.En este capítulo trataremos de evitar el jaque que nos hagan las piezas blancas.

- En esta entrada aprenderemos a evitar el jaque del rival mediante dos mecanismos: comiendo la pieza del rival  que no está atacando o moviendo el rey a alguna casilla libre.En la siguiente entrada del blog trataremos de evitar el jaque de nuestro adversario bloqueando la trayectoria de la pieza que nos este atacando. De momento os dejo el vídeo con el código de los dos mecanismos anteriormente mencionados:



- Os pongo el código de los métodos modificado en este vídeo:

  //Obtener todos los posibles movimientos de todas las piezas negras y de momento generao un movimiento aleatorio
        #region Nuevo
        public void generarMovimientoAleatorio()
        {

            int posinicial = 0;
            ArrayList arrayPiezas = new ArrayList();
            ArrayList arrayPosInicialPiezas = new ArrayList();
            ArrayList arrayValorMovimiento = new ArrayList();


            int posicionJaque = 0;
            int posicionReyJaque = 0;
            Boolean SiJaque = false;
            Pieza piezaAux = new Pieza();
            Pieza reyAux = null;


            //Si nos dan jaque buscamos que pieza nos lo esta dando y en que posicion por si al calcular los movimientos de las piezas negras pudieramos comernos la pieza.También seleccionamos la pieza rey.
            if (motor.tablero.jaqueNegro)
            {

                foreach (Cuadrado c in motor.tablero.Escaques)
                {

                    //Guardamos en variable auxiliar la pieza rey negro
                    if (c.pieza != null && c.pieza.colorPieza == ColorPieza.Negro && c.pieza.tipoPieza == TipoPiezaAjedrez.Rey )
                                    reyAux = c.pieza;
               

                    //Buscamos que pieza nos esta dando jaque
                    if (c.pieza != null && c.pieza.colorPieza == ColorPieza.Blanco && c.pieza.DandoJaque == true)
                    {
                        SiJaque = true;
                        piezaAux = c.pieza;
                    }
                    if(!SiJaque)
                    posicionJaque++;

                    if(reyAux==null)
                    posicionReyJaque++;
                }

                if (!SiJaque)
                    posicionJaque = -1;
            }


            //Recorremos el tablero y guardamos la posicion de las piezas negras con algun movimiento valido
            foreach (Cuadrado c in motor.tablero.Escaques)
            {

                if (c.pieza != null && c.pieza.colorPieza == ColorPieza.Negro && c.pieza.movimientosValidos.Count > 0)
                {

                    arrayPiezas.Add(c.pieza);
                    arrayPosInicialPiezas.Add(posinicial);
                    arrayValorMovimiento.Add(valorMovimiento(c.pieza, motor.tablero, posicionJaque));

                }

                posinicial++;
            }



            //Recorremos el array con los valores de los movimientos y elegimos el que mayor valor tenga si no elegimos un movimiento aleatorio
            int maxValor = 0;
            int posicionArray = 0;
            for (int i = 0; i < arrayValorMovimiento.Count; i++)
            {

                if (((MovimientoSeleccionado)arrayValorMovimiento[i]).ValorMovimiento > maxValor)
                {
                    maxValor = ((MovimientoSeleccionado)arrayValorMovimiento[i]).ValorMovimiento;
                    posicionArray = i;

                }
            }


            byte columnainicio = 0;
            byte filaInicio = 0;
            byte columnaDestino = 0;
            byte filaDestino = 0;
            int posicionInicial = 0;

            //Si nos estan dando jaque y no nos podemos comer la pieza que nos lo esta dando movemos el rey
            if (SiJaque && maxValor != 100000)
            {
                Random random = new Random();
                columnainicio = Convert.ToByte(posicionReyJaque % 8);
                filaInicio = Convert.ToByte(posicionReyJaque / 8);
                int posicionAleatoriaRey = random.Next(0,reyAux.movimientosValidos.Count);
                columnaDestino = Convert.ToByte((reyAux.movimientosValidos.ElementAt(posicionAleatoriaRey) % 8));
                filaDestino = Convert.ToByte((reyAux.movimientosValidos.ElementAt(posicionAleatoriaRey) / 8));

                //Meter logica para bloquear la trayectoria de la pieza que nos esta atacando

            }
            else
            {

                //Si no nos aporta valor movemos cualquier ficha aleatoriamente
                if (maxValor > 0)
                {
                    posicionInicial = Convert.ToInt32(arrayPosInicialPiezas[posicionArray]);
                    columnainicio = Convert.ToByte(posicionInicial % 8);
                    filaInicio = Convert.ToByte(posicionInicial / 8);
                    columnaDestino = Convert.ToByte(((MovimientoSeleccionado)arrayValorMovimiento[posicionArray]).PosicionDestino % 8);
                    filaDestino = Convert.ToByte(((MovimientoSeleccionado)arrayValorMovimiento[posicionArray]).PosicionDestino / 8);
                }
                else
                {
                    //Seleccionamos aleatoriamente la pieza a mover y obtenemos columna y fila inicial
                    Random random = new Random();
                    int piezaAletoria = random.Next(0, arrayPiezas.Count);
                    posicionInicial = Convert.ToInt32(arrayPosInicialPiezas[piezaAletoria]);
                    columnainicio = Convert.ToByte(posicionInicial % 8);
                    filaInicio = Convert.ToByte(posicionInicial / 8);

                    ////Dentro de los movimientos validos selecionamos aleatoriamente alguno de ellos.Primero hacemos un random de los posible movimientos y
                    ////luego seleccionamos uno de ellos
                    int posicionAleatoria = random.Next(0, ((Pieza)arrayPiezas[piezaAletoria]).movimientosValidos.Count);
                    columnaDestino = Convert.ToByte(((Pieza)arrayPiezas[piezaAletoria]).movimientosValidos.ElementAt(posicionAleatoria) % 8);
                    filaDestino = Convert.ToByte(((Pieza)arrayPiezas[piezaAletoria]).movimientosValidos.ElementAt(posicionAleatoria) / 8);
                }
            }


            motor.moverPieza(columnainicio, filaInicio, columnaDestino, filaDestino);


        }

        //Funcion para calcular el valor de un movimiento y la posicion detino que la almacenamos en el nuevo objeto MovimientoSeleccionado
        private MovimientoSeleccionado valorMovimiento(Pieza piezaMover, Tablero tablero , int PosicionJaque )
        {
            MovimientoSeleccionado mov = new MovimientoSeleccionado();
            mov.ValorMovimiento = 0;
            int posicionpiezaBlanca = 0;
            int valorMovimientoAux = 0;
            //si en alguno de los posibles movimientos hay una pieza que se pueda comer guardamos su peso y posicion
            for (int i = 0; i < piezaMover.movimientosValidos.Count; i++)
            {
                posicionpiezaBlanca = 0;
                foreach (Cuadrado c in motor.tablero.Escaques)
                {
                    if (c.pieza != null && c.pieza.colorPieza == ColorPieza.Blanco && piezaMover.movimientosValidos.ElementAt(i)==posicionpiezaBlanca)
                    {
                        //Si nos podemos comer una pieza que nos esta haciendo jaque le damos el máximo valor
                        if (posicionpiezaBlanca == PosicionJaque)
                            valorMovimientoAux = 100000;
                        else
                        valorMovimientoAux = c.pieza.valorPieza;

                        if (valorMovimientoAux > mov.ValorMovimiento)
                            mov.ValorMovimiento = valorMovimientoAux;

                        mov.PosicionDestino = posicionpiezaBlanca;
                    }
                    posicionpiezaBlanca++;
                }
            }
            return mov;
        }





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

76. Inteligencia Artificial (5).Comiendo piezas

 -  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 la entrada anterior aprendimos a generar movimientos aleatorios en nuestro tablero, que en realidad es una matriz.En esta ocasión nuestro agente tiene como objetivo comer fichas del rival en función del peso que tengan asignado.

- Para ello hemos asignado a cada pieza del rival  un valor:


  • Peón: 100 puntos
  • Caballo:320 puntos
  • Alfil:325 puntos
  • Torre:500 puntos
  • Reina: 975 puntos
  • Rey: 32767 puntos

- En función de los valores que tengan asignadas las piezas nuestro agente tratara de comer una pieza u otra en función del valor que tenga asignada.En el vídeo lo podemos ver más claro:


- En siguientes entradas iremos mejorando nuestro jugador para que además de intentar comer piezas del rival tenga en cuenta las posibles consecuencias de hacerlo.Por el momento os dejo el código de lo visto en el vídeo:


  • Nueva clase MovimientoSeleccionado.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AjedrezIA
{
    public class MovimientoSeleccionado
    {
        int valorMovimiento;
        int posicionDestino;

        public int ValorMovimiento { get => valorMovimiento; set => valorMovimiento = value; }
        public int PosicionDestino { get => posicionDestino; set => posicionDestino = value; }

        public MovimientoSeleccionado()
        {
            valorMovimiento = 0;
            posicionDestino = 0;
            }
    }
}

  • Métodos utilizados en este capítulo:
  //Obtener todos los posibles movimientos de todas las piezas negras y de momento generao un movimiento aleatorio
       
        public void generarMovimientoAleatorio()
        {

            int posinicial = 0;
            ArrayList arrayPiezas = new ArrayList();
            ArrayList arrayPosInicialPiezas = new ArrayList();
            ArrayList arrayValorMovimiento = new ArrayList();

            if (motor.tablero.jaqueNegro)
            {
                //Ver que hacemos en caso de jaque al rey

            }
            else
            {
                //Recorremos el tablero y guardamos la posicion de las piezas negras con algun movimiento valido en el caso que no sea jaque
                foreach (Cuadrado c in motor.tablero.Escaques)
                {

                    if (c.pieza != null && c.pieza.colorPieza == ColorPieza.Negro && c.pieza.movimientosValidos.Count > 0)
                    {
                        arrayPiezas.Add(c.pieza);
                        arrayPosInicialPiezas.Add(posinicial);
                        arrayValorMovimiento.Add(valorMovimiento(c.pieza, motor.tablero));
                    }
                    posinicial++;
                }
            }


            //Recorremos el array con los valores de los movimientos y elegimos el que mayor valor tenga si no elegimos un movimiento aleatorio
            int maxValor = 0;
            int posicionArray = 0;
            for (int i=0; i<arrayValorMovimiento.Count;i++)
            {
             
                if (((MovimientoSeleccionado)arrayValorMovimiento[i]).ValorMovimiento > maxValor)
                {
                    maxValor = ((MovimientoSeleccionado)arrayValorMovimiento[i]).ValorMovimiento;
                    posicionArray = i;
                  
                }
            }


            byte columnainicio = 0;
            byte filaInicio = 0;
            byte columnaDestino = 0;
            byte filaDestino = 0;
            int posicionInicial = 0;
            //Si no nos aporta valor movemos cualquier ficha aleatoriamente
            if (maxValor > 0)
            {
                posicionInicial =Convert.ToInt32(arrayPosInicialPiezas[posicionArray]);
                columnainicio = Convert.ToByte(posicionInicial % 8);
                filaInicio = Convert.ToByte(posicionInicial / 8);
                columnaDestino = Convert.ToByte(( (MovimientoSeleccionado)arrayValorMovimiento[posicionArray]).PosicionDestino % 8);
                filaDestino = Convert.ToByte(((MovimientoSeleccionado)arrayValorMovimiento[posicionArray]).PosicionDestino / 8);
            }
            else
            {
                //Seleccionamos aleatoriamente la pieza a mover y obtenemos columna y fila inicial
                Random random = new Random();
                int piezaAletoria = random.Next(0, arrayPiezas.Count);
                posicionInicial = Convert.ToInt32(arrayPosInicialPiezas[piezaAletoria]);
                columnainicio = Convert.ToByte(posicionInicial % 8);
                filaInicio = Convert.ToByte(posicionInicial / 8);

                ////Dentro de los movimientos validos selecionamos aleatoriamente alguno de ellos.Primero hacemos un random de los posible movimientos y 
                ////luego seleccionamos uno de ellos
                int posicionAleatoria = random.Next(0, ((Pieza)arrayPiezas[piezaAletoria]).movimientosValidos.Count);
                columnaDestino = Convert.ToByte(((Pieza)arrayPiezas[piezaAletoria]).movimientosValidos.ElementAt(posicionAleatoria) % 8);
                filaDestino = Convert.ToByte(((Pieza)arrayPiezas[piezaAletoria]).movimientosValidos.ElementAt(posicionAleatoria) / 8);
            }



            motor.moverPieza(columnainicio, filaInicio, columnaDestino, filaDestino);


        }

        //Funcion para calcular el valor de un movimiento y la posicion detino que la almacenamos en el nuevo objeto MovimientoSeleccionado
        private MovimientoSeleccionado valorMovimiento(Pieza piezaMover, Tablero tablero )
        {
            MovimientoSeleccionado mov = new MovimientoSeleccionado();
            mov.ValorMovimiento = 0;
            int posicionpiezaBlanca = 0;
            int valorMovimientoAux = 0;
            //si en alguno de los posibles movimientos hay una pieza que se pueda comer guardamos su peso y posicion
            for (int i = 0; i < piezaMover.movimientosValidos.Count; i++)
            {
                posicionpiezaBlanca = 0;
                foreach (Cuadrado c in motor.tablero.Escaques)
                {
                    if (c.pieza != null && c.pieza.colorPieza == ColorPieza.Blanco && piezaMover.movimientosValidos.ElementAt(i)==posicionpiezaBlanca)
                    {
                        valorMovimientoAux = c.pieza.valorPieza;
                        if (valorMovimientoAux > mov.ValorMovimiento)
                            mov.ValorMovimiento = valorMovimientoAux;

                        mov.PosicionDestino = posicionpiezaBlanca;
                    }
                    posicionpiezaBlanca++;
                }
            }
            return mov;
        }


        

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

75. Inteligencia Artificial (4). Generando movimientos

 -  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 empezamos a generar movimientos con las piezas negras que serán las que controle nuestro agente de inteligencia artificial.

- Por el momento nos conformaremos con generar un movimiento aleatorio de todos los posibles movimientos válidos, que se puedan realizar. En siguientes entradas empezaremos a calcular cual es el mejor movimiento dentro de los posibles movimientos válidos.Os dejo el vídeo con el código:


-Como hemos visto en el vídeo implementamos una función que nos genere los movimientos aleatorios utilizando las clases vistas en anteriores entradas.


  •  En primer lugar obtenemos los posibles movimientos válidos de las pieza negras con este código:


       int posinicial = 0;
            ArrayList arrayPiezas = new ArrayList();
            ArrayList arrayPosInicialPiezas = new ArrayList();

            if (motor.tablero.jaqueNegro)
            {
                //Ver que hacemos en caso de jaque al rey
           
            }
            else
            {
                //Recorremos el tablero y guardamos la posicion de las piezas negras con algun movimiento valido en el caso que no sea jaque
                foreach (Cuadrado c in motor.tablero.Escaques)
                {

                    if (c.pieza != null && c.pieza.colorPieza == ColorPieza.Negro && c.pieza.movimientosValidos.Count > 0)
                    {
                        arrayPiezas.Add(c.pieza);
                        arrayPosInicialPiezas.Add(posinicial);

                    }
                    posinicial++;
                }
            }


  • En segundo lugar en esta misma función hacemos un movimiento aleatorio:

          //Seleccionamos aleatoriamente la pieza a mover y obtenemos columna y fila inicial
            Random random = new Random();
            int piezaAletoria = random.Next(0, arrayPiezas.Count);
            int posicionInicial = Convert.ToInt32(arrayPosInicialPiezas[piezaAletoria]);
            byte columnainicio = Convert.ToByte(posicionInicial % 8);
            byte filaInicio = Convert.ToByte(posicionInicial / 8);

            //Dentro de los movimientos validos selecionamos aleatoriamente alguno de ellos.Primero hacemos un random de los posible movimientos y 
            //luego seleccionamos uno de ellos
            int posicionAleatoria = random.Next(0, ((Pieza)arrayPiezas[piezaAletoria]).movimientosValidos.Count);
            byte columnaDestino = Convert.ToByte(((Pieza)arrayPiezas[piezaAletoria]).movimientosValidos.ElementAt(posicionAleatoria) % 8);
            byte filaDestino = Convert.ToByte(((Pieza)arrayPiezas[piezaAletoria]).movimientosValidos.ElementAt(posicionAleatoria) / 8);

            motor.moverPieza(columnainicio, filaInicio, columnaDestino, filaDestino);


  • Os dejo el código completo de este clase. El resto del código esta en entradas anteriores del blog:

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

namespace AjedrezIA.Controles
{
    public partial class TableroAjedrez : UserControl
    {
        #region Internal

      

        internal class Seleccion
        {
            public byte Columna;
            public byte Fila;
            public bool Seleccionado;
        }

       



        #endregion

        #region enumerados

        #region Column enum

        public enum Column
        {
            A,
            B,
            C,
            D,
            E,
            F,
            G,
            H,
            Desconocida
        }

        #endregion

        #region Mostrartipospiezas enum

        public enum Mostrartipospiezas
        {
            ClassicHiRes,
            Classic,
            EnchancedClassic
        }

        #endregion

        #endregion

        #region Delegados
        
        public delegate void CambioTurnoHandler(ColorPieza quienMueve);

        #endregion

        #region Private

        private Seleccion actualDestino;
        private Seleccion actualOrigen;

        private Engine motor;
        private int boxAltura;
        private int maxAltura;
        #endregion

        #region Public

        public event CambioTurnoHandler cambioTurno;


        #endregion

        #region Constructores

        public TableroAjedrez() 
        {
            InitializeComponent();

            NuevaPartida();
        }

        public void NuevaPartida()
        {
             
            motor = new Engine();

            actualOrigen = new Seleccion();
            actualDestino = new Seleccion();

            if (motor.Humano != motor.quienMovio)
            {
                MotorMovimiento();
            }

            Refresh();

        }

        #endregion

        #region Publica 

        private void MotorMovimiento()
        {

            if (motor.dameTipoPieza(actualOrigen.Columna, actualOrigen.Fila) == TipoPiezaAjedrez.Ninguna)
            {
                actualDestino.Seleccionado = false;
                actualOrigen.Seleccionado = false;
                return;
            }

    

            bool valid = motor.EsMovimientoValido(actualOrigen.Columna, actualOrigen.Fila, actualDestino.Columna, actualDestino.Fila);

            if (valid == false)
            {
                actualDestino.Seleccionado = false;
                actualOrigen.Seleccionado = false;
                return;
            }

            motor.moverPieza(actualOrigen.Columna, actualOrigen.Fila, actualDestino.Columna, actualDestino.Fila);

            if (cambioTurno != null)
            {
                cambioTurno(motor.quienMovio);
            }

            //Limpiar solucion         
            actualOrigen.Seleccionado = false;
            //Generar movimiento
            generarMovimientoAleatorio();
            Refresh();
        }

        public static Column dameNumeroColumna(int columna)
        {
            Column retColumna;

            switch (columna)
            {
                case 1:
                    retColumna = Column.A;
                    break;
                case 2:
                    retColumna = Column.B;
                    break;
                case 3:
                    retColumna = Column.C;
                    break;
                case 4:
                    retColumna = Column.D;
                    break;
                case 5:
                    retColumna = Column.E;
                    break;
                case 6:
                    retColumna = Column.F;
                    break;
                case 7:
                    retColumna = Column.G;
                    break;
                case 8:
                    retColumna = Column.H;
                    break;
                default:
                    retColumna = Column.Desconocida;
                    break;
            }

            return retColumna;
        }

        #endregion

        #region Eventos

        private void tablero_Pintar(object sender, PaintEventArgs e)
        {
            GraphicsBuffer gBuffer = new GraphicsBuffer();
            gBuffer.CreateGraphicsBuffer(e.Graphics, Width, Height);

            Graphics g = gBuffer.Graphics;

            SolidBrush solidWhiteBrush = new SolidBrush(Color.White);
            SolidBrush solidBlackBrush = new SolidBrush(Color.Black);

            Pen penBlack = new Pen(Color.Black, 1);

            Pen penHightlight = new Pen(Color.Black, 2);
            Pen penDestination = new Pen(Color.Yellow, 2);
            Pen penValidMove = new Pen(Color.Black, 2);
            Pen penEnPassant = new Pen(Color.DeepPink, 1);

            const int buffer = 10;

            if (Width < Height)
            {
                maxAltura = Width - 5 - buffer;
                boxAltura = maxAltura / 8;
            }
            else
            {
                maxAltura = Height - 5 - buffer;
                boxAltura = maxAltura / 8;
            }

            g.Clear(BackColor);

            try
            {
                int seleccionX;
                int seleccionY;

                //Draw Chess Board
                for (byte y = 0; y < 8; y++)
                {
                    for (byte x = 0; x < 8; x++)
                    {
                        if ((x + y) % 2 == 0)
                        {
                            g.FillRectangle(solidWhiteBrush, (x * boxAltura) + buffer, (y * boxAltura), boxAltura, boxAltura);
                        }
                        else
                        {
                            Rectangle dibujarArea1 = new Rectangle((x * boxAltura) + buffer, (y * boxAltura), boxAltura, boxAltura);
                            LinearGradientBrush linearBrush = new LinearGradientBrush(dibujarArea1, Color.Gainsboro, Color.Silver, LinearGradientMode.ForwardDiagonal);
                            g.FillRectangle(linearBrush, (x * boxAltura) + buffer, (y * boxAltura), boxAltura, boxAltura);
                        }

                        g.DrawRectangle(penBlack, (x * boxAltura) + buffer, (y * boxAltura), boxAltura, boxAltura);
                    }

                }
                for (byte i = 0; i < 8; i++)
                {
                    g.DrawString((8 - i).ToString(), new Font("Verdana", 8), solidBlackBrush, 0, (i * boxAltura) + buffer);
                    g.DrawString(dameNumeroColumna(i + 1).ToString(), new Font("Verdana", 8), solidBlackBrush, (i * boxAltura) + (boxAltura / 2) + 3, maxAltura - 1);
                }
               
                //dibujar piezas
                for (byte columna = 0; columna < 8; columna++)
                {
                    for (byte fila = 0; fila < 8; fila++)
                    {
                        TipoPiezaAjedrez tipoPiezaAjedrez = motor.dameTipoPieza(columna, fila);

                        if (tipoPiezaAjedrez != TipoPiezaAjedrez.Ninguna)
                        {
                            ColorPieza colorPieza = motor.dameColorPieza(columna, fila);
                            bool seleccionado = motor.damePiezaSeleccionada(columna, fila);


                            int x = (columna) * boxAltura;
                            int y = (fila) * boxAltura;

                            if (colorPieza == ColorPieza.Blanco)
                            {
                                if (tipoPiezaAjedrez == TipoPiezaAjedrez.Peon)
                                {
                                    g.DrawImage(Resources.WPawn, x + buffer, y, boxAltura, boxAltura);
                                }
                                else if (tipoPiezaAjedrez == TipoPiezaAjedrez.Torre)
                                {
                                    g.DrawImage(Resources.WRook, x + buffer, y, boxAltura, boxAltura);
                                }
                                else if (tipoPiezaAjedrez == TipoPiezaAjedrez.Caballo)
                                {
                                    g.DrawImage(Resources.WKnight, x + buffer, y, boxAltura, boxAltura);
                                }
                                else if (tipoPiezaAjedrez == TipoPiezaAjedrez.Alfil)
                                {
                                    g.DrawImage(Resources.WBishop, x + buffer, y, boxAltura, boxAltura);
                                }
                                else if (tipoPiezaAjedrez == TipoPiezaAjedrez.Reina)
                                {
                                    g.DrawImage(Resources.WQueen, x + buffer, y, boxAltura, boxAltura);
                                }
                                else if (tipoPiezaAjedrez == TipoPiezaAjedrez.Rey)
                                {
                                    g.DrawImage(Resources.WKing, x + buffer, y, boxAltura, boxAltura);
                                }
                            }
                            else
                            {
                                if (tipoPiezaAjedrez == TipoPiezaAjedrez.Peon)
                                {
                                    g.DrawImage(Resources.BPawn, x + buffer, y, boxAltura, boxAltura);
                                }
                                else if (tipoPiezaAjedrez == TipoPiezaAjedrez.Torre)
                                {
                                    g.DrawImage(Resources.BRook, x + buffer, y, boxAltura, boxAltura);
                                }
                                else if (tipoPiezaAjedrez == TipoPiezaAjedrez.Caballo)
                                {
                                    g.DrawImage(Resources.BKnight, x + buffer, y, boxAltura, boxAltura);
                                }
                                else if (tipoPiezaAjedrez == TipoPiezaAjedrez.Alfil)
                                {
                                    g.DrawImage(Resources.BBishop, x + buffer, y, boxAltura, boxAltura);
                                }
                                else if (tipoPiezaAjedrez == TipoPiezaAjedrez.Reina)
                                {
                                    g.DrawImage(Resources.BQueen, x + buffer, y, boxAltura, boxAltura);
                                }
                                else if (tipoPiezaAjedrez == TipoPiezaAjedrez.Rey)
                                {
                                    g.DrawImage(Resources.BKing, x + buffer, y, boxAltura, boxAltura);
                                }
                            }

                            if (seleccionado)
                            {
                                seleccionX = ((columna) * boxAltura) + buffer;
                                seleccionY = (fila) * boxAltura;
                                g.DrawRectangle(penHightlight, seleccionX, seleccionY, boxAltura - 1, boxAltura - 1);


                                //Pintar movimientos validos
                                if (motor.dameMovimientosValidos(columna, fila) != null)
                                {
                                    foreach (byte[] sqr in motor.dameMovimientosValidos(columna, fila))
                                    {
                                        int moverY = (sqr[1]) * boxAltura;


                                        int moverX = (sqr[0] * boxAltura) + buffer;

                                        g.DrawRectangle(penValidMove, moverX, moverY, boxAltura - 1, boxAltura - 1);
                                    }
                                }
                            }
                            if (motor.ObtenerMovimientosAnteriores()[0] > 0)
                            {
                                int moverY = (motor.ObtenerMovimientosAnteriores()[1]) * boxAltura;

                                int moverX = (motor.ObtenerMovimientosAnteriores()[0] * boxAltura) + buffer;

                                g.DrawRectangle(penEnPassant, moverX, moverY, boxAltura - 1, boxAltura - 1);
                            }

                        }
                    }
                }

                if (actualDestino.Seleccionado)
                {
                    seleccionY = (actualDestino.Fila) * boxAltura;
                    seleccionX = ((actualDestino.Columna) * boxAltura) + buffer;

                    g.DrawRectangle(penDestination, seleccionX, seleccionY, boxAltura - 1, boxAltura - 1);
                }


                gBuffer.Render(CreateGraphics());

                g.Dispose();

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error al dibujar tablero", MessageBoxButtons.OK);
            }

        }

        private void tablero_MouseClick(object sender, MouseEventArgs e)
        {
            byte columna = 0;
            byte fila = 0;

            try
            {
                //dame Columna
                for (int i = 0; i < 8; i++)
                {
                    if (((i * boxAltura) + 10) < e.Location.X)
                    {
                        columna++;
                    }
                    else
                    {
                        break;
                    }
                }

                //dame fila
                for (int i = 0; i < 8; i++)
                {
                    if (i * boxAltura < e.Location.Y)
                    {
                        fila++;
                    }
                    else
                    {
                        break;
                    }
                }
                columna--;

                fila--;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error calculando fila y columna seleccionada", MessageBoxButtons.OK);
            }

            //Comprobar si filas y columna están en los limites  
            if (columna > 7 || columna < 0)
            {
                return;
            }
            if (fila > 7 || fila < 0)
            {
                return;
            }

            try
            {
                if (actualOrigen.Columna == columna && actualOrigen.Fila == fila && actualOrigen.Seleccionado)
                {
                
                    actualOrigen.Seleccionado = false;
                    actualDestino.Seleccionado = false;

                    if (motor.dameTipoPieza(columna, fila) != TipoPiezaAjedrez.Ninguna)
                    {
                        motor.asignarPosicionAPieza(columna, fila, false);
                    }
                }
                else if ((actualOrigen.Columna != columna || actualOrigen.Fila != fila) && actualOrigen.Seleccionado)
                {
                   
                    actualDestino.Seleccionado = true;
                    actualDestino.Columna = columna;
                    actualDestino.Fila = fila;

                    MotorMovimiento();
                }
                else
                {
                    if (motor.dameTipoPieza(columna, fila) != TipoPiezaAjedrez.Ninguna)
                    {
                        if (motor.dameColorPieza(columna, fila) != motor.quienMovio)
                        {
                            motor.asignarPosicionAPieza(actualDestino.Columna, actualDestino.Fila, false);

                            actualOrigen.Seleccionado = false;
                            actualDestino.Seleccionado = false;
                            return;
                        }
                        motor.asignarPosicionAPieza(columna, fila, true);
                    }
                    else
                    {
                        motor.asignarPosicionAPieza(actualDestino.Columna, actualDestino.Fila, false);

                        actualOrigen.Seleccionado = false;
                        actualDestino.Seleccionado = false;
                        return;
                    }

                    //Seleccionar origen
                    actualDestino.Seleccionado = false;

                    actualOrigen.Columna = columna;
                    actualOrigen.Fila = fila;
                    actualOrigen.Seleccionado = true;


                }



                Refresh();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error seleccionando pieza", MessageBoxButtons.OK);
            }
        }

        private void ChessBoard_Load(object sender, EventArgs e)
        {
            if (cambioTurno != null)
            {
                cambioTurno(motor.quienMovio);
            }
        }

        private void ChessBoard_Resize(object sender, EventArgs e)
        {
            Refresh();
        }

        #endregion


        //Obtener todos los posibles movimientos de todas las piezas negras y de momento generao un movimiento aleatorio
        #region Nuevo
        public void generarMovimientoAleatorio()
        {

            int posinicial = 0;
            ArrayList arrayPiezas = new ArrayList();
            ArrayList arrayPosInicialPiezas = new ArrayList();

            if (motor.tablero.jaqueNegro)
            {
                //Ver que hacemos en caso de jaque al rey
             
            }
            else
            {
                //Recorremos el tablero y guardamos la posicion de las piezas negras con algun movimiento valido en el caso que no sea jaque
                foreach (Cuadrado c in motor.tablero.Escaques)
                {

                    if (c.pieza != null && c.pieza.colorPieza == ColorPieza.Negro && c.pieza.movimientosValidos.Count > 0)
                    {
                        arrayPiezas.Add(c.pieza);
                        arrayPosInicialPiezas.Add(posinicial);
                        valorMovimiento(c.pieza,motor.tablero);
                    }
                    posinicial++;
                }
            }


            //Seleccionamos aleatoriamente la pieza a mover y obtenemos columna y fila inicial
            Random random = new Random();
            int piezaAletoria = random.Next(0, arrayPiezas.Count);
            int posicionInicial = Convert.ToInt32(arrayPosInicialPiezas[piezaAletoria]);
            byte columnainicio = Convert.ToByte(posicionInicial % 8);
            byte filaInicio = Convert.ToByte(posicionInicial / 8);

            //Dentro de los movimientos validos selecionamos aleatoriamente alguno de ellos.Primero hacemos un random de los posible movimientos y 
            //luego seleccionamos uno de ellos
            int posicionAleatoria = random.Next(0, ((Pieza)arrayPiezas[piezaAletoria]).movimientosValidos.Count);
            byte columnaDestino = Convert.ToByte(((Pieza)arrayPiezas[piezaAletoria]).movimientosValidos.ElementAt(posicionAleatoria) % 8);
            byte filaDestino = Convert.ToByte(((Pieza)arrayPiezas[piezaAletoria]).movimientosValidos.ElementAt(posicionAleatoria) / 8);

            motor.moverPieza(columnainicio, filaInicio, columnaDestino, filaDestino);


        }
}

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...