Package prop.hex.domini.controladors.IA.auxiliars

Source Code of prop.hex.domini.controladors.IA.auxiliars.ResistenciaTauler

package prop.hex.domini.controladors.IA.auxiliars;

import prop.cluster.domini.models.estats.EstatCasella;
import prop.hex.domini.models.Casella;
import prop.hex.domini.models.TaulerHex;

import java.util.ArrayList;
import java.util.List;

/**
* Per evaluar un tauler concret imaginem el tauler com un circuit elèctric. On cada casella té una resistencia.
* <p/>
* Per a cada jugador resistencia de cada casella serà:
* 1 si la casella està buida.
* 0 si pertany al mateix jugador.
* Inf. si pertany al jugador contrari.
* <p/>
* Apliquem un voltatge a cada costat (A esquerra i dreta si és jugador A o a baix i a dalt si és jugador B),
* i n'evaluem la resistencia total.
* <p/>
* La resistencia d'un tauler calculada d'aquesta manera ve a ser un indicador de la facilitat de creuar d'un punt a
* un altre del tauler. Si la resistencia d'un tauler és 0 vol dir que el jugador ha guanyat. Si és Inf. vol dir que
* el jugador contrari ha guanyat.
* <p/>
* L'algoritme aplicat aqui per calcular la resistencia només fa una aproximació de la resistencia global on,
* per cada casella mira la les caselles evaluades anteriorment i en treu la resistencia en paral·lel.
* Calcular la resistencia global bé és massa costos i aquesta aproximació funciona prou bé.
*
* @author Marc Junyent Martín (Grup 7.3, Hex)
*/
public final class ResistenciaTauler
{

  /**
   * Tauler sobre el que s'evalua la resistencia.
   */
  private TaulerHex tauler;

  /**
   * Jugador per al que s'evalua la resistencia.
   */
  private EstatCasella jugador;

  /**
   * Resistencia del tauler.
   */
  private double resistencia;

  /**
   * Array de la mida del tauler on es guarden les resistencies parcials de cada casella,
   * necessari pel funcionament de l'algoritme.
   */
  private double[][] resistencies_parcials;

  /**
   * Instancia la classe amb el tauler i el jugador especificats.
   *
   * @param tauler  tauler a analitzar
   * @param jugador jugador per al qual volem trobar la resistencia del tauler.
   */
  public ResistenciaTauler( TaulerHex tauler, EstatCasella jugador )
  {
    this.tauler = tauler;
    this.jugador = jugador;
    this.resistencia = -1.0;
    this.resistencies_parcials = new double[tauler.getMida()][tauler.getMida()];
  }

  /**
   * Evalua la resistencia del tauler.
   *
   * @return double amb la resistencia total.
   */
  public double evalua()
  {
    if ( jugador == EstatCasella.JUGADOR_A )
    {
      evaluaA();
    }
    else if ( jugador == EstatCasella.JUGADOR_B )
    {
      evaluaB();
    }
    return resistencia;
  }

  /**
   * Evalua la resistencia per al jugador A.
   */
  private void evaluaA()
  {
    //Evaluem el tauler d'esquerra a dreta.

    // Omplim la primera columna del tauler amb les resistencies, (directe del seu estat).
    for ( int i = 0; i < tauler.getMida(); i++ )
    {
      resistencies_parcials[i][0] = resistenciaCasella( new Casella( i, 0 ) );
    }

    // Calculem les resistencies parcials cap a baix a partir de la primera fila.
    for ( int columna = 1; columna < tauler.getMida(); columna++ )
    {
      for ( int fila = 0; fila < tauler.getMida(); fila++ )
      {
        double r_entrada = calculaResistenciaColumna( fila, columna );

        if ( r_entrada >= 10000.0 )
        {
          resistencies_parcials[fila][columna] = 10000.0;
        }
        else
        {
          if ( resistenciaCasella( new Casella( fila, columna ) ) >= 10000.0 )
          {
            resistencies_parcials[fila][columna] = 10000.0;
          }
          else
          {
            resistencies_parcials[fila][columna] =
                r_entrada + resistenciaCasella( new Casella( fila, columna ) );
          }
        }
      }
    }

    resistencia = calculaResistenciaColumna( 0, tauler.getMida() );
  }

  /**
   * Evalua la resistencia per al jugador B.
   */
  private void evaluaB()
  {
    //Evaluem el tauler d'adalt a baix.

    // Omplim la primera fila del tauler amb les resistencies, (directe del seu estat).
    for ( int i = 0; i < tauler.getMida(); i++ )
    {
      resistencies_parcials[0][i] = resistenciaCasella( new Casella( 0, i ) );
    }

    // Calculem les resistencies parcials cap a baix a partir de la primera fila.
    for ( int fila = 1; fila < tauler.getMida(); fila++ )
    {
      for ( int columna = 0; columna < tauler.getMida(); columna++ )
      {
        double r_entrada = calculaResistenciaFila( fila, columna );

        if ( r_entrada >= 10000.0 )
        {
          resistencies_parcials[fila][columna] = 10000.0;
        }
        else
        {
          if ( resistenciaCasella( new Casella( fila, columna ) ) >= 10000.0 )
          {
            resistencies_parcials[fila][columna] = 10000.0;
          }
          else
          {
            resistencies_parcials[fila][columna] =
                r_entrada + resistenciaCasella( new Casella( fila, columna ) );
          }
        }
      }
    }

    resistencia = calculaResistenciaFila( tauler.getMida(), 0 );
  }

  /**
   * Calcula la resistencia d'una casella en funció dels veins de la fila superior i de l'esquerra.
   *
   * @param fila    fila de la casella.
   * @param columna columna de la casella.
   * @return resistencia de la casella en qüestió.
   */
  private double calculaResistenciaFila( int fila, int columna )
  {
    //Iterem per tots els veins superiors i de l'esquerra, si un es 0 el resultat serà 0, si tots són inf,
    // el resultat serà inf, en altres casos, serà la inversa de la suma inversa de tots els 1.

    /*Obtenim els veins, si la fila és la mida del tauler entenem que estem a la cantonada i totes les caselles
     *de la última fila són les veines.
     */
    List<Casella> veins;
    if ( fila == tauler.getMida() )
    {
      veins = new ArrayList<Casella>();
      for ( int i = 0; i < tauler.getMida(); i++ )
      {
        veins.add( new Casella( tauler.getMida() - 1, i ) );
      }
    }
    else
    {
      veins = tauler.getVeins( fila, columna );
    }

    boolean calcula_paralel = false;
    double inversa_rt = 0.0;
    for ( int i = 0; i < veins.size(); i++ )
    {
      //Per tots els veins de la fila superior o de l'esquerra i mateixa fila...
      if ( veins.get( i ).getFila() < fila ||
           ( veins.get( i ).getFila() <= fila && veins.get( i ).getColumna() < columna ) )
      {
        //Si és 0, el resultat serà 0, no cal continuar.
        if ( resistencies_parcials[veins.get( i ).getFila()][veins.get( i ).getColumna()] == 0.0 )
        {
          return 0.0;
        }
        //Si no és Inf tampoc.
        else if ( resistencies_parcials[veins.get( i ).getFila()][veins.get( i ).getColumna()] < 10000 )
        {
          calcula_paralel = true;
          inversa_rt += 1.0 / resistencies_parcials[veins.get( i ).getFila()][veins.get( i ).getColumna()];
        }
      }
    }

    //Si calcula_paralel = false, ja ho tenim, sino li donem valor.
    if ( calcula_paralel )
    {
      return ( 1.0 / inversa_rt );
    }

    return 10000.0;
  }

  /**
   * Calcula la resistencia d'una casella en funció dels veins de l'esquerra i de dalt.
   *
   * @param fila    fila de la casella.
   * @param columna columna de la casella.
   * @return resistencia de la casella en qüestió.
   */
  private double calculaResistenciaColumna( int fila, int columna )
  {
    //Iterem per tots els veins de l'esquerra i els de dalt a l'esquerra, si un es 0 el resultat serà 0,
    // si tots són inf, el resultat serà inf, en altres casos, serà la inversa de la suma inversa de tots els 1.

    /*Obtenim els veins, si la columna és la mida del tauler entenem que estem a la cantonada i totes les caselles
     *de la última columna són les veines.
     */
    List<Casella> veins;
    if ( columna == tauler.getMida() )
    {
      veins = new ArrayList<Casella>();
      for ( int i = 0; i < tauler.getMida(); i++ )
      {
        veins.add( new Casella( i, tauler.getMida() - 1 ) );
      }
    }
    else
    {
      veins = tauler.getVeins( fila, columna );
    }

    boolean calcula_paralel = false;
    double inversa_rt = 0.0;
    for ( int i = 0; i < veins.size(); i++ )
    {
      //Per tots els veins de la columna esquerra o de la mateixa columna i superiors.
      if ( veins.get( i ).getColumna() < columna ||
           ( veins.get( i ).getFila() < fila && veins.get( i ).getColumna() <= columna ) )
      {
        //Si és 0, el resultat serà 0, no cal continuar.
        if ( resistencies_parcials[veins.get( i ).getFila()][veins.get( i ).getColumna()] == 0.0 )
        {
          return 0.0;
        }
        //Si no és Inf tampoc.
        else if ( resistencies_parcials[veins.get( i ).getFila()][veins.get( i ).getColumna()] < 10000.0 )
        {
          calcula_paralel = true;
          inversa_rt += 1.0 / resistencies_parcials[veins.get( i ).getFila()][veins.get( i ).getColumna()];
        }
      }
    }

    //Si calcula_paralel = false, ja ho tenim, sino li donem valor.
    if ( calcula_paralel )
    {
      return ( 1.0 / inversa_rt );
    }

    return 10000.0;
  }

  /**
   * retorna la resistencia d'una casella en funció del jugador.
   *
   * @param casella
   * @return la resistencia de la casella.
   */
  private double resistenciaCasella( Casella casella )
  {
    EstatCasella estat = tauler.getEstatCasella( casella );
    if ( estat == jugador )
    {
      return 0.0;
    }
    else if ( estat == EstatCasella.BUIDA )
    {
      return 1.0;
    }
    else
    {
      return 10000;
    }
  }
}
TOP

Related Classes of prop.hex.domini.controladors.IA.auxiliars.ResistenciaTauler

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.