/**
   * El nodo hijo pasado es el ultimo movimiento del jugador pasado en parametro, los hijos de este
   * nodo son los posibles movimientos del OTRO jugador, donde NO puede ganar este que estamos
   * probando.
   *
   * @param nodo
   * @param jugador
   * @param profundidad
   * @return
   */
  public int getCantidadVictoriasAPartirDe(Arbol.Nodo<Jugada> nodo, int jugador, int profundidad) {
    if (nodo.getHijos().estaVacia()) {
      if (nodo.getValor().haGanado(jugador)) return (10 - profundidad);
      int otroJugador = (jugador == COMPUTADORA ? JUGADOR : COMPUTADORA);
      if (nodo.getValor().haGanado(otroJugador)) return (profundidad - 10);
      return 0;
    }

    int total = 0;
    Iterator<Arbol.Nodo<Jugada>> iter = nodo.getHijos().iterator();
    while (iter.hasNext()) {
      Arbol.Nodo<Jugada> nodoHijo = iter.next();
      total += getCantidadVictoriasAPartirDe(nodoHijo, jugador, profundidad + 1);
    }

    return total;
  }
  /**
   * Crea un arbol de TODOS los posibles movimientos a partir de una jugada. Este metodo puede ser
   * bastantee pesado ya que puede crear un arbol de varios miles de nodos al menos para la primera
   * jugada. Alternativamente luego de cada jugada cambia de jugador para simular TODAS las posibles
   * jugadas.
   *
   * @param movida
   * @param jugador
   * @return
   */
  public Arbol<Jugada> crearArbol(Jugada movida, int jugador) {
    Arbol<Jugada> result = new Arbol<Jugada>();

    Arbol.Nodo<Jugada> nodoRaiz = result.insertarHijo(null, movida);

    Cadena<Jugada> posiblesJugadas = movida.getPosiblesJugadas(jugador);
    int otroJugador = (jugador == JUGADOR ? COMPUTADORA : JUGADOR);

    Iterator<Jugada> iter = posiblesJugadas.iterator();
    while (iter.hasNext()) {
      Jugada hijo = iter.next();
      Arbol.Nodo<Jugada> nodoHijo = result.insertarHijo(nodoRaiz, hijo);
      Arbol<Jugada> arbolHijo = crearArbol(hijo, otroJugador);

      nodoHijo.colocarHijosDeRaizDeArbol(arbolHijo);
    }

    return result;
  }
  /**
   * Elige una jugada a partir del arbol de decision obtenido para el jugador pasado en parametro.
   * Para esto lo que hace es contar la cantidad de victorias que le da cada uno de los hijos de la
   * raiz (las posibles jugadas). Luego, lo unico que se hace es elegir el hijo que da la mayor
   * cantidad de victorias.
   *
   * @param arbolDecision
   * @param jugador
   * @return
   */
  private Jugada elegirJugada(Arbol<Jugada> arbolDecision, int jugador) {
    int maxCantidadVictorias = Integer.MIN_VALUE;
    Jugada elegida = null;

    Cadena<Arbol.Nodo<Jugada>> posibles = arbolDecision.getRaiz().getHijos();

    Iterator<Arbol.Nodo<Jugada>> iter = posibles.iterator();
    while (iter.hasNext()) {
      Arbol.Nodo<Jugada> nodo = iter.next();
      logger.debug("Jugada: \n" + nodo.getValor());
      int cantidadVictorias = getCantidadVictoriasAPartirDe(nodo, jugador, 1);
      logger.debug("Tiene " + cantidadVictorias + " victorias posibles");
      if (cantidadVictorias >= maxCantidadVictorias) {
        elegida = nodo.getValor();
        maxCantidadVictorias = cantidadVictorias;
      }
    }

    return elegida;
  }