Package prop.cluster.domini.controladors

Source Code of prop.cluster.domini.controladors.InteligenciaArtificial

package prop.cluster.domini.controladors;

import prop.cluster.domini.models.Partida;
import prop.cluster.domini.models.Tauler;
import prop.cluster.domini.models.estats.EstatCasella;
import prop.cluster.domini.models.estats.EstatPartida;

/**
* La classe <code>InteligenciaArtificial</code> proporciona una implementació estàndard de l'algorisme MiniMax amb
* l'optimització de poda alfa-beta. Per a més informació sobre el funcionament de l'algorisme poden consultar aquest <a
* href=http://www.lsi.upc.edu/~bejar/heuristica/docmin.html>enllaç</a>
*/
public abstract class InteligenciaArtificial
{

  /**
   * Intercanvia l'estat d'una casella ocupada del tauler
   *
   * @param estat Representa l'estat de la casella ocupada que es vol intercanviar
   * @return L'estat contrari a l'estat de la casella <em>estat</em>
   */
  private EstatCasella intercanviaEstatCasella( EstatCasella estat )
  {
    if ( estat == EstatCasella.JUGADOR_A )
    {
      return EstatCasella.JUGADOR_B;
    }
    return EstatCasella.JUGADOR_A;
  }

  /**
   * Avalua un objecte de la classe <code>Tauler</code> seguint l'heurísitca que s'implementi
   *
   * @param tauler         Objecte de la classe <code>Tauler</code> sobre el qual es disputa una partida.
   * @param estat_moviment Descriu en quin estat ha quedat <em>tauler</em> en funció de l'últim moviment efectuat
   *                       sobre aquest.
   * @param profunditat    És la profunditat a la que s'ha arribat durant l'exploració de les diferents possibilitats de
   *                       moviment. Cada unitat de <em>profunditat</em> representa un torn jugat de la partida.
   * @param fitxa_jugador  Indica el jugador de la partida a partir del qual avaluar <em>tauler</em>.
   * @return Un enter indicant l'avaulació de <em>tauler</em>.
   */
  public abstract int funcioAvaluacio( Tauler tauler, EstatPartida estat_moviment, int profunditat,
                                       EstatCasella fitxa_jugador );

  /**
   * Donada una partida amb una certa situació i la fitxa del jugador que ha de moure durant el torn actual, calcula
   * quina és la millor posició del tauler on realitzar el següent moviment, seguint l'algorisme MiniMax. Com que per
   * aconseguir aquest càlcul és necessari generar una estructura arbòria on cada nivell representa el pròxim torn i,
   * dins d'un mateix nivell, es generen tots els possibles moviments vàlids a realtzar, també cal donar un límit que
   * trunqui la cerca, per evitar que el cost temporal de l'algorisme MiniMax augmenti exponencialment.
   *
   * @param partida            Objecte de la classe <code>Partida</code> que representa la partida actual en joc.
   * @param estat_casella      Representa la fitxa del jugador que ha de disputar el torn actual de la partida.
   * @param profunditat_maxima Representa el nivell límit en la cerca arbòria del moviment òptim.
   * @return La posició òptima on el jugador amb fitxes <em>fitxa_jugador</em> ha de fer el seu moviment el seu torn a
   *         <em>partida</em>. La posició ve representada per les seves dues coordenades (número de fila i número
   *         col·lumna).
   */

  public int[] minimax( Partida partida, EstatCasella estat_casella, int profunditat_maxima )
  {
    int[] millor_moviment = {
        -1,
        -1
    };
    int maxim_actual;
    int maxim = Integer.MIN_VALUE;
    Tauler tauler = partida.getTauler();
    int mida = tauler.getMida();
    int profunditat = 0;
    EstatCasella fitxa_jugador = EstatCasella.JUGADOR_B;
    if ( estat_casella == EstatCasella.JUGADOR_A )
    {
      fitxa_jugador = EstatCasella.JUGADOR_A;
    }

    for ( int fila = 0; fila < mida; ++fila )
    {
      for ( int columna = 0; columna < mida; ++columna )
      {
        try
        {
          tauler.mouFitxa( estat_casella, fila, columna );
        }
        catch ( IllegalArgumentException excepcio )
        {
          continue;
        }
        EstatPartida estat_partida = partida.comprovaEstatPartida( fila, columna );
        estat_casella = this.intercanviaEstatCasella( estat_casella );
        maxim_actual =
            this.valorMax( partida, estat_partida, Integer.MIN_VALUE, Integer.MAX_VALUE, estat_casella,
                profunditat + 1, profunditat_maxima, fitxa_jugador );
        if ( maxim_actual > maxim )
        {
          maxim = maxim_actual;
          millor_moviment[0] = fila;
          millor_moviment[1] = columna;
        }
        tauler.treuFitxa( fila, columna );
        estat_casella = intercanviaEstatCasella( estat_casella );
      }
    }
    return millor_moviment;
  }

  /**
   * Mètode privat i recursiu que genera tots els possibles moviments d'un torn en una certa partida. De tots els
   * moviments, se selecciona el més favorable als interessos del jugador controlat per l'algorisme MiniMax, que a la
   * vegada és el més desfavorable als interessos del seu oponent.
   *
   * @param partida            Objecte de la classe <code>Partida</code> que representa la partida actual en joc.
   * @param estat_partida      Indica en quin estat es troba actualment <em>partida</em>
   * @param alfa               Valor de la millor opció (el més alt) que s'ha trobat fins al moment durant la cerca de l'arbre pel
   *                           jugador controlat per l'algorisme MiniMax.
   * @param beta               Valor de la millor opció (el més baix) que s'ha trobat fins al moment durant la cerca de l'arbre per
   *                           l'oponent del jugador controlat per l'algorisme MiniMax.
   * @param estat_casella      Representa la fitxa del jugador que ha de disputar el torn actual de la partida.
   * @param profunditat        Representa el nivell actual d'exploració en l'àrbre de moviments generat.
   * @param profunditat_maxima Representa el nivell límit en la cerca arbòria del moviment òptim.
   * @param fitxa_jugador      Indica el jugador de la partida controlat per l'algorisme MiniMax.
   * @return Valor de la millor opció (el més alt) un cop generat tots els possibles moviments pel torn on es troba
   *         <em>partida</em>.
   */
  private int valorMax( Partida partida, EstatPartida estat_partida, int alfa, int beta, EstatCasella estat_casella,
                        int profunditat, int profunditat_maxima, EstatCasella fitxa_jugador )
  {
    Tauler tauler = partida.getTauler();
    if ( profunditat == profunditat_maxima || estat_partida == EstatPartida.GUANYA_JUGADOR_A ||
         estat_partida == EstatPartida.GUANYA_JUGADOR_B || estat_partida == EstatPartida.EMPAT )
    {
      return funcioAvaluacio( tauler, estat_partida, profunditat, fitxa_jugador );
    }
    else
    {
      int mida = tauler.getMida();
      for ( int fila = 0; fila < mida; ++fila )
      {
        for ( int columna = 0; columna < mida; ++columna )
        {
          try
          {
            tauler.mouFitxa( estat_casella, fila, columna );
          }
          catch ( IllegalArgumentException excepcio )
          {
            continue;
          }
          EstatPartida estat_partida_aux = partida.comprovaEstatPartida( fila, columna );
          estat_casella = intercanviaEstatCasella( estat_casella );
          alfa = Math.max( alfa,
              this.valorMin( partida, estat_partida_aux, alfa, beta, estat_casella, ( profunditat + 1 ),
                  profunditat_maxima, fitxa_jugador ) );
          tauler.treuFitxa( fila, columna );
          if ( alfa >= beta )
          {
            return beta;
          }
          estat_casella = intercanviaEstatCasella( estat_casella );
        }
      }
      return alfa;
    }
  }

  /**
   * Mètode privat i recursiu que genera tots els possibles moviments d'un torn en una certa partida. De tots els
   * moviments, se selecciona el més favorable als interessos de l'oponent, que a la vegada és el més desfavorable pel
   * jugador controlat per l'algorisme MiniMax.
   *
   * @param partida            Objecte de la classe <code>Partida</code> que representa la partida actual en joc.
   * @param estat_partida      Indica en quin estat es troba actualment <em>partida</em>
   * @param alfa               Valor de la millor opció (el més alt) que s'ha trobat fins al moment durant la cerca de l'arbre pel
   *                           jugador controlat per l'algorisme MiniMax.
   * @param beta               Valor de la millor opció (el més baix) que s'ha trobat fins al moment durant la cerca de l'arbre per
   *                           l'oponent del jugador controlat per l'algorisme MiniMax.
   * @param estat_casella      Representa la fitxa del jugador que ha de disputar el torn actual de la partida.
   * @param profunditat        Representa el nivell actual d'exploració en l'àrbre de moviments generat.
   * @param profunditat_maxima Representa el nivell límit en la cerca arbòria del moviment òptim.
   * @param fitxa_jugador      Indica el jugador de la partida controlat per l'algorisme MiniMax.
   * @return Valor de la millor opció (el més baix) un cop generat tots els possibles moviments pel torn on es troba
   *         <em>partida</em>.
   */
  private int valorMin( Partida partida, EstatPartida estat_partida, int alfa, int beta, EstatCasella estat_casella,
                        int profunditat, int profunditat_maxima, EstatCasella fitxa_jugador )
  {
    Tauler tauler = partida.getTauler();
    if ( profunditat == profunditat_maxima || estat_partida == EstatPartida.GUANYA_JUGADOR_A ||
         estat_partida == EstatPartida.GUANYA_JUGADOR_B || estat_partida == EstatPartida.EMPAT )
    {
      return funcioAvaluacio( tauler, estat_partida, profunditat, fitxa_jugador );
    }
    else
    {
      int mida = tauler.getMida();
      for ( int fila = 0; fila < mida; ++fila )
      {
        for ( int columna = 0; columna < mida; ++columna )
        {
          try
          {
            tauler.mouFitxa( estat_casella, fila, columna );
          }
          catch ( IllegalArgumentException excepcio )
          {
            continue;
          }
          EstatPartida estat_partida_aux = partida.comprovaEstatPartida( fila, columna );
          estat_casella = this.intercanviaEstatCasella( estat_casella );
          beta = Math.min( beta,
              this.valorMax( partida, estat_partida_aux, alfa, beta, estat_casella, ( profunditat + 1 ),
                  profunditat_maxima, fitxa_jugador ) );
          tauler.treuFitxa( fila, columna );
          if ( alfa >= beta )
          {
            return alfa;
          }
          estat_casella = this.intercanviaEstatCasella( estat_casella );
        }
      }
      return beta;
    }
  }
}
TOP

Related Classes of prop.cluster.domini.controladors.InteligenciaArtificial

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.