Pop

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);


        }
}

No hay comentarios:

Publicar un comentario

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