package algoritmos;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Stack;
import tablero.CasillaTablero.ColorLinea;
import tablero.CasillaTablero.TipoLinea;
import tablero.PuntoTablero.TipoPunto;
import traza.TrazaAlgoritmo;
public abstract class AlgoritmoResolucion implements Runnable {
public int velocidad;
public TrazaAlgoritmo traza;
HashMap <String,Nodo> cerrados;
HashMap <String,Nodo> abiertos;
VariablesProblema variables;
String cadenaVertical,cadenaHorizontal;
public void iniciarEstructurasDeDatos(){
this.abiertos=new HashMap<String,Nodo>();
this.cerrados=new HashMap<String,Nodo>();
}
protected void setVariablesProblema(VariablesProblema variables){
this.variables=variables;
}
public int getSizeAbiertos(){
return this.abiertos.size();
}
public int getSizeCerrados(){
return this.cerrados.size();
}
protected class Nodo{
int fila,columna;
int filaPadre,columnaPadre;
int gn=0;
int hn=0;
boolean visitado=false;
public void setFilaColumna(int fila,int columna){
this.fila=fila;
this.columna=columna;
}
public void setFilaColumnaPadre(int fila,int columna){
this.filaPadre=fila;
this.columnaPadre=columna;
}
public void setGn(int gn){
this.gn=gn;
}
public void setHn(int hn){
this.hn=hn;
}
public void setVisitado(boolean valor){
this.visitado=valor;
}
public boolean getVisitado(){
return this.visitado;
}
public int getFn(){
return this.gn+this.hn;
}
public int getGn(){
return this.gn;
}
@SuppressWarnings("unused")
public int getHn(){
return this.hn;
}
public int getFila(){
return this.fila;
}
public int getColumna(){
return this.columna;
}
@SuppressWarnings("unused")
public int getFilaPadre(){
return this.filaPadre;
}
@SuppressWarnings("unused")
public int getColumnaPadre(){
return this.columnaPadre;
}
public String getCoordenadas(){
return this.fila+"-"+this.columna;
}
public String getCoordenadasPadre(){
return this.filaPadre+"-"+this.columnaPadre;
}
public String toString(){
String resultado="-----------------\n";
resultado+="Fila: "+fila+"\n";
resultado+="Columna: "+columna+"\n";
resultado+="Gn: "+gn+"\n";
resultado+="Hn: "+hn+"\n";
resultado+="-----------------\n";
return resultado;
}
}
class FnComparator implements Comparator<Nodo> {
public int compare(Nodo o1, Nodo o2) {
Nodo u1 = o1;
Nodo u2 = o2;
return u1.getFn() - u2.getFn();
}
public boolean equals(Object o) {
return this == o;
}
}
public class VariablesProblema{
Nodo nodoInicio;
Nodo nodoObjetivo;
public VariablesProblema(Nodo nodoInicio,Nodo nodoObjetivo){
this.nodoInicio=nodoInicio;
this.nodoObjetivo=nodoObjetivo;
}
public int getFilasTotales(){
int numerofilas=nodoObjetivo.getFila()-nodoInicio.getFila();
return numerofilas+nodoInicio.getFila();
}
public int getColumnasTotales(){
int numerocolumnas=nodoObjetivo.getColumna()-nodoInicio.getColumna();
return numerocolumnas+nodoInicio.getColumna();
}
}
public void resolverAlgoritmo(){
int filaActual=1;
int columnaActual=1;
int filasTotales=this.variables.getFilasTotales();
int columnasTotales=this.variables.getColumnasTotales();
//System.out.println(filasTotales);
Nodo nodoActual=new Nodo();
nodoActual.setFilaColumna(this.variables.nodoInicio.getFila(), this.variables.nodoInicio.getColumna());
nodoActual.setFilaColumnaPadre(0, 0);
nodoActual.setGn(0);
nodoActual.setHn(0);
nodoActual.setVisitado(false);
String nodoObjetivo=this.variables.nodoObjetivo.getCoordenadas();
//System.out.println(nodoObjetivo);
boolean objetivoAlcanzado=false;
this.abiertos.put(nodoActual.getCoordenadas(),nodoActual);
this.traza.actualizarNodosEnMemoria();
while (!objetivoAlcanzado && !this.abiertos.isEmpty()){
nodoActual=siguienteNodo();
this.abiertos.remove(nodoActual.getCoordenadas());
this.cerrados.put(nodoActual.getCoordenadas(), nodoActual);
//this.traza.pintarLinea(nodoActual.getFilaPadre(),nodoActual.getColumnaPadre(),nodoActual.getFila(),nodoActual.getColumna(),TipoLinea.CONTINUA,ColorLinea.ACTUAL);
this.traza.pintarPunto(nodoActual.getFila(),nodoActual.getColumna(),TipoPunto.ACTUAL);
this.traza.actualizarNodosEnMemoria();
if(nodoObjetivo.equals(nodoActual.getCoordenadas())){
//Si el nodo es el objetivo lo marcamos y lo metemos en cerrados
objetivoAlcanzado=true;
}
filaActual=nodoActual.getFila();
columnaActual=nodoActual.getColumna();
//Vecino inferior
if( !objetivoAlcanzado && filaActual<filasTotales){
//A�adimos el nodo a abiertos
Nodo nodoInferior=new Nodo();
nodoInferior.setFilaColumna(filaActual+1, columnaActual);
nodoInferior.setFilaColumnaPadre(filaActual, columnaActual);
insertarEnAbiertos(nodoInferior,nodoActual);
this.traza.actualizarNodosEnMemoria();
}
//Vecino diagonal
if(!objetivoAlcanzado && filaActual<filasTotales && columnaActual<columnasTotales ){
//A�adimos el nodo a abiertos
Nodo nodoDiagonal=new Nodo();
nodoDiagonal.setFilaColumna(filaActual+1, columnaActual+1);
nodoDiagonal.setFilaColumnaPadre(filaActual, columnaActual);
insertarEnAbiertos(nodoDiagonal,nodoActual);
this.traza.actualizarNodosEnMemoria();
}
//Vecino derecha
if(!objetivoAlcanzado && columnaActual<columnasTotales){
//A�adimos el nodo a abiertos
Nodo nodoDerecha=new Nodo();
nodoDerecha.setFilaColumna(filaActual, columnaActual+1);
nodoDerecha.setFilaColumnaPadre(filaActual, columnaActual);
insertarEnAbiertos(nodoDerecha,nodoActual);
this.traza.actualizarNodosEnMemoria();
}
this.traza.introducirRetardo();
this.traza.pintarPunto(nodoActual.getFila(),nodoActual.getColumna(),TipoPunto.CERRADO);
}
}
public TipoLinea seleccionarTipoLinea(Nodo nodoActual, Nodo nuevoNodo){
TipoLinea tipoLinea=TipoLinea.CONTINUA;
if(nodoActual.getFila()+1==nuevoNodo.getFila() && nodoActual.getColumna()+1==nuevoNodo.getColumna() &&
!this.cadenaHorizontal.substring(nodoActual.getColumna()-1, nodoActual.getColumna()).equals(this.cadenaVertical.substring(nodoActual.getFila()-1, nodoActual.getFila())))
{
tipoLinea=TipoLinea.PUNTEADA;
}
return tipoLinea;
}
public void pintarSolucion(){
//System.out.println(this.traza.toString());
//this.traza.limpiarTablero();
//Creamos la pila soluci�n
Stack<Nodo> solucion=new Stack<Nodo>();
//Configuramos el nodo objetivo desde el que vamos a hacer
//el backtracking
String indiceNodoActual=this.variables.nodoObjetivo.getCoordenadas();
String indiceNodoInicial=this.variables.nodoInicio.getCoordenadas();
//System.out.println(this.cerrados.toString());
//Mientras no lleguemos al nodo de partida seguimos iterando
while(!indiceNodoActual.equals(indiceNodoInicial)){
Nodo nodoActual=this.cerrados.get(indiceNodoActual);
//String[] fila_columna=indiceNodoActual.split("-");
solucion.push(nodoActual);
indiceNodoActual=nodoActual.getCoordenadasPadre();
}
//solucion.toString();
this.traza.pintarPunto(1, 1, TipoPunto.SOLUCION);
while(!solucion.empty()){
Nodo temp=solucion.pop();
if(temp.getFilaPadre()!=0 || temp.getColumnaPadre()!=0){
if(temp.getFila()==(temp.getFilaPadre()+1) && temp.getColumna()==(temp.getColumnaPadre()+1)){
if(this.cadenaHorizontal.substring(temp.getColumnaPadre()-1, temp.getColumnaPadre()).equals(this.cadenaVertical.substring(temp.getFilaPadre()-1, temp.getFilaPadre()))){
this.traza.pintarLinea(temp.getFilaPadre(), temp.getColumnaPadre(), temp.getFila(), temp.getColumna(), TipoLinea.CONTINUA,ColorLinea.SOLUCION);
}
else{
this.traza.pintarLinea(temp.getFilaPadre(), temp.getColumnaPadre(), temp.getFila(), temp.getColumna(), TipoLinea.PUNTEADA,ColorLinea.SOLUCION);
}
}
else{
this.traza.pintarLinea(temp.getFilaPadre(), temp.getColumnaPadre(), temp.getFila(), temp.getColumna(), TipoLinea.CONTINUA,ColorLinea.SOLUCION);
}
}
}
}
public abstract Nodo siguienteNodo();
public abstract void insertarEnAbiertos(Nodo nuevoNodo,Nodo nodoActual);
}