Lógica del juego 5: Función IA - aigora/twIE_2021-chkr_s-l GitHub Wiki

void IA(int tablero[], bool dificil, int turno, int comidasPosibles[][3],int nComidasPosibles, SDL_Renderer *Render, const Cuadrante  dim_cas [32]);

Argumentos:

La función utiliza el tablero, con la información de que hay en cada casilla; el booleano dificil, asignado al seleccionar la dificultad; la matriz comidasPosibles, con las piezas que se pueden comer este turno; el nComidasPosibles, para poder recorrer la matriz comidasposibles y Render y dim_cas para pintar el movimiento que se realice.

Salida:

La función IA altera el array tablero en función de los movimientos del bot.

Funcionamiento:

Nota: En esta función se utiliza la función dondeCome, que tiene la misma utilidad que la función puedeMover pero para las comidas.
Lo primero que ocurre es la selección de dificultad.

if (dificil)
{
    //Bot difícil
}
else
{
    //Bot fácil
}

Modo fácil

En este modo el bot realiza un movimiento aleatorio evitando suicidar sus piezas si tiene otra opción, pero no realiza el movimiento más óptimo al comer.

Si puede comer:
El bot elige una pieza aleatoria de las que pueden comer y come con ella, mirando de forma recursiva si puede volver a comer, haciendo la comida en caso afirmativo y coronando si la pieza llegase al final del tablero.

pieza = rand() % (nComidasPosibles+1); //Se elige una comida aleatoria
tablero[comidasPosibles[pieza][2]] = tablero[comidasPosibles[pieza][0]];
tablero[comidasPosibles[pieza][0]] = 2;
tablero[comidasPosibles[pieza][1]] = 2;
coronar(tablero); //Se corona si se debe

for(j=0; j<=2; j++) //Se pinta el movimiento
{
     Pintar(tablero,comidasPosibles[pieza][j],false,Render,dim_cas); //Dibuja las piezas movidas
     SDL_Delay(time1/200);
}

nComidas = -1;

do
{
    nComidas = dondeCome(tablero, turno, comidasPosibles[pieza][2], comidasPosibles1);//Se ve si la pieza puede
//comer otra vez
    SDL_Delay(time1);
    if(nComidas != -1) //Si puede comer otra vez
    {
        pieza = rand()%(nComidas+1); //Elegir una comida aleatoria

        tablero[comidasPosibles1[pieza][1]] = tablero[comidasPosibles[pieza][2]];
        tablero[comidasPosibles[pieza][2]] = 2;
        tablero[comidasPosibles1[pieza][0]] = 2;
        coronar(tablero); //Coronar si se puede

        Pintar(tablero, comidasPosibles1[pieza][1], false, Render, dim_cas);
        Pintar(tablero, comidasPosibles[pieza][2], false, Render, dim_cas);
        Pintar(tablero, comidasPosibles1[pieza][0], false, Render, dim_cas);
    }
}while(nComidas != -1);

Si no puede comer:
Se elige un movimiento aleatorio de una pieza que pueda mover y que no sea comida al hacerlo (Función noEsComidaAlMover).

for (i=0; i<32; i++) //Para cada casilla
{
    if (tablero[i]%3 == turno%2) //Si la pieza de la casilla es del bot
    {
        nMovimientosPosibles = puedeMover(tablero, i, movimientosPosibles);
        if (nMovimientosPosibles != -1) //Si la pieza puede mover
        {
            puedenMover[l] = i; //Se almacenan las piezas que pueden mover de entre las que se va a sacar una
            if (l<=10) { l++; }
            for (j=0; j<=nMovimientosPosibles; j++)
            {
                if (noEsComidaAlMover(tablero, i, movimientosPosibles[j], turno)) //Si la pieza sobrevive al comer
                {
                    movidas[k][0] = i;
                    movidas[k][1] = movimientosPosibles[j];
                    if (k<=30) { k++; } else { break; }
                }
            }
            if (k>30) { break; }
        }
    }
}
pieza = rand()%k; //Se elige un movimiento aleatorio entre los que no llevan a que coman la pieza
tablero[movidas[pieza][1]] = tablero[movidas[pieza][0]];
tablero[movidas[pieza][0]] = 2;
coronar(tablero);


Pintar(tablero, movidas[pieza][0], false, Render, dim_cas);
Pintar(tablero, movidas[pieza][1], false, Render, dim_cas);

Modo difícil:

En este modo el bot come con la pieza con la que más veces puede comer, quita del peligro las piezas amenazadas si puede hacerlo de tal manera que no sean comidas y en última instancia hace un movimiento aleatorio.
Puede Comer:
Mira que piezas pueden comer y cuantas veces y almacena una aleatoria con el número más alto.

for (i=0; i<32; i++) { tablero1[i]=tablero[i]; } //Se copia el tablero para no alterar el general
for (i=0; i<=nComidasPosibles; i++) //Para cada comida que se puede hacer
{
    n = 0;
    salir = false;
    posicion = comidasPosibles[i][0];
    comidasPosibles1[i][0] = comidasPosibles[i][1];
    comidasPosibles1[i][1] = comidasPosibles[i][2];
    comida1[0] = comidasPosibles[i][0];
    comida1[1] = comidasPosibles1[i][0];
    do
    {
        pieza = tablero1[posicion];
        for (j=0; j<32; j++) //Se actualiza el tablero con el movimiento
        {
            if (posicion == j){ tablero1[j] = 2; }
            else if (comidasPosibles1[i][0] == j){ tablero1[j] = 2; }
            else if (comidasPosibles1[i][1] == j){ tablero1[j] = pieza; }
            else { tablero1[j]=tablero1[j]; }
        }
        posicion = comidasPosibles1[i][1]; //Se comprueba si puede comer otra vez
        coronar(tablero1);
        n++;
        nComidas = dondeCome(tablero1, turno, posicion, comidasPosibles1);
        comida1[n + 1] = comidasPosibles1[i][0];
        if(n > comida[0]) //Si es el numero de comidas más grande se almacena
        {
            comida[0] = n;
            comida[1] = pieza;
            comida[2] = comidasPosibles1[i][1];
            for (j=0; j<=n; j++)
            {
                comida[j + 3] = comida1[j];
            }
        }
        if (nComidas == -1){ salir = true; }
    }while (!salir);
}
tablero[comida[2]] = comida[1];
for (i=0; i<comida[0]+1; i++) //Eliminan las piezas comidas y la inicial del tablero
{
    tablero[comida[i + 3]] = 2;
}
coronar(tablero); //Se corona si se puede
SDL_Delay(time1);
for (i=0; i<=comida[0]+2; i++) //de dibuja la jugada
{
    Pintar(tablero, comida[i + 2], false, Render, dim_cas);
}

Si hay una pieza amenazada:
Se comprueba si al mover esa pieza puede librarse de ser comida y se es así la mueve a una de las posiciones seguras aleatoriamente.

for (i=0; i<32; i++) //Para cada casilla
{
    if (tablero[i]%3 == turno%2) //Si es del bot
    {
        nMovimientosPosibles = puedeMover(tablero, i, movimientosPosibles);
        if (nMovimientosPosibles != -1) //Si puede mover
        {
            puedenMover[l] = i;
            if (l<=10) { l++; }

            sobrevive = true;
            for(j=0; j<=nComidas; j++) //Mira si la pieza es comida al turno siguiente si no se mueve
            {
                if (comidasPosibles2[j][1] == i) { sobrevive = false; break; }
            }
            if (!sobrevive) //Si la ficha es comida al turno siguiente
            {
                 for (j=0; j<=nMovimientosPosibles; j++) //Para cada movimiento que puede hacer la pieza
                {
                    if (noEsComidaAlMover(tablero, i, movimientosPosibles[j], turno)) //Si no es comida al turno
//siguiente haciendo ese movimiento este se añade a la lista
                    {
                        movidas[k][0] = i;
                        movidas[k][1] = movimientosPosibles[j];
                        k++;
                    }
                }
            }
        }
    }
}

Movimientos en el que la pieza no sea comida al turno siguiente:
Esto utiliza el mismo algoritmo que en la dificultad fácil.

for (i=0; i<32; i++) //Para cada casilla
                {
    if (tablero[i]%3 == turno%2) //Si la pieza es del bot
    {
        nMovimientosPosibles = puedeMover(tablero, i, movimientosPosibles);
        if (nMovimientosPosibles != -1) //Si la ficha puede hacer movimientos
        {
            puedenMover[l] = i;
            if (l<=10) { l++; }
            for (j=0; j<=nMovimientosPosibles; j++) //Por cada movimiento
            {
                if (noEsComidaAlMover(tablero, i, movimientosPosibles[j], turno))//sobrevive) //Si la pieza no es
//comida en la posición a la que llega en el turno siguiente
                {
                    movidas[k][0] = i;
                    movidas[k][1] = movimientosPosibles[j];
                    if (k<=30) { k++; } else { break; }
                }
            }
            if (k>30) { break; }
        }
    }
}

Pintar las fichas:
Si se pueden hacer movimientos ventajosos se realizan uno aleatorio de entre esos, y si no, se realiza uno aleatorio.

if (k > 0) //Si hay movimientos ventajosos
{
    rnd = rand() % k; //Elige uno aleatorio de entre estos

    tablero[movidas[rnd][1]] = tablero[movidas[rnd][0]];
    tablero[movidas[rnd][0]] = 2;
    coronar(tablero);

    SDL_Delay(time1);
    Pintar(tablero, movidas[rnd][0], false, Render, dim_cas);
    Pintar(tablero, movidas[rnd][1], false, Render, dim_cas);
}
else
{
    rnd = rand() % l; //Elige uno de entre las pieza que se pueden mover
    pieza = puedenMover[rnd];
    nMovimientosPosibles = puedeMover(tablero, pieza, movimientosPosibles);
    if (nMovimientosPosibles != -1) { rnd = rand() % (nMovimientosPosibles + 1); } else { rnd = 0; }
    posicion = movimientosPosibles[rnd];

    tablero[posicion] = tablero[pieza];
    tablero[pieza] = 2;
    coronar(tablero);

    SDL_Delay(time1);
    Pintar(tablero, pieza, false, Render, dim_cas);
    Pintar(tablero, posicion, false, Render, dim_cas);
}
⚠️ **GitHub.com Fallback** ⚠️