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;
}
- 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;
}
No hay comentarios:
Publicar un comentario