/** * Obtenemos la posición del nodo en función del numero de nodo */ private static int ObtenerPosicionNodo(Nodo[] mapa, Nodo nodo) { return nodo.numeroDeNodo -1; /*Console.WriteLine("Buscando nodo " + nodo.numeroDeNodo); for(int i = 0;i < mapa.Length; i++) { if(mapa[i] != null && mapa[i].numeroDeNodo == nodo.numeroDeNodo) return i; } Console.WriteLine("No existe"); return -1;*/ }
/** * Obtenemos la posición del nodo que dispone de la menor distancia. * La obtenemos entre los nodos no visitados y accesibles. * Devolvemos la posición del nodo con el peso mas bajo */ private static Nodo BuscarNodoDeMenorPeso(Nodo[] mapa) { Int32 pesoMinimo = Int32.MaxValue; Nodo nodoCorto = null; foreach(Nodo n in mapa) { if(n != null) { foreach(Conexion cnx in n.conexiones) { if(cnx != null) { /* Si el nodo de la tabla Dijkstra no es de los * ya visitados, se le ha asignado ya alguna distancia * y o todavía no hemos designado el nodo de peso mínimo * o ya habiéndolo designado el examinado es inferior * al ya propuesto */ if (!cnx.NodoConexion.Visitado && cnx.Peso < pesoMinimo) { pesoMinimo = cnx.Peso; nodoCorto = cnx.NodoConexion; } } } } } return nodoCorto; }
/* * Recorremos los distintos nodos que vamos visitando * El primer valor es posición del nodo origen (el nodo origen se va modificando * conforme vamos avanzando en la busqueda) * El segundo valor es posición del nodo destino final. * Distancia del nodo examinado. Este valor lo sumaremos al del valor modificable obteniendo * la distancia real entre el nodo origen y los nodos examinados */ private static void HacerDijkstra(Nodo[] mapa, Nodo origen, Nodo destino, int pesoAcumulado) { foreach(Nodo n in mapa) { if(n != null) { foreach(Conexion cnx in n.conexiones) { if(cnx != null) { /* Si el nodo origen tiene alguna conexión con * el nodo examinado Y El nodo examinado en la * tabla Dijkstra no tiene un valor todavía * o Si el nodo examinado en la tabla Dijkstra * tiene valor pero es superior al que obtendremos. */ if(cnx.NodoConexion.numeroDeNodo == origen.numeroDeNodo && (n.distancia == -1 || (pesoAcumulado + cnx.Peso) < n.distancia)) { n.distancia = pesoAcumulado + cnx.Peso; } } } } } Console.WriteLine("Origen " + origen.ToString()); origen.Visitado = true; Nodo nodo = BuscarNodoDeMenorPeso(mapa); if (nodo != null) { int pos = ObtenerPosicionNodo(mapa, nodo); Console.WriteLine(pos); HacerDijkstra(mapa, nodo, destino, mapa[ pos ].distancia); } }
private static Conexion BuscarConexionMenor( Nodo actual) { Conexion[] conexiones = actual.conexiones; Conexion menor = null; foreach(Conexion cnx in conexiones) { if(cnx != null && !cnx.NodoConexion.Visitado) { if(menor == null || cnx.NodoConexion.numeroDeNodo == 1) { menor = cnx; } else { if(menor.Peso > cnx.Peso) { menor = cnx; } } if(menor.NodoConexion.numeroDeNodo == 1) //es el destino break; } } if(menor == null) { //Se elimina la ultima adicion pues nos lleva a un camino cíclico. listaMovimientos.RemoveAt(listaMovimientos.Count - 1); menor = BuscarConexionMenor(anteriores.Pop()); } else { menor.NodoConexion.Visitado = true; } return menor; }
public static Queue<Direccion> PrimeroElMejor(Nodo origen, Nodo destino) { anteriores = new Stack<Nodo>(); listaMovimientos = new List<Direccion>(); Nodo actual = origen; do { Conexion tmp = BuscarConexionMenor( actual ); anteriores.Push(actual); // pila de anteriores actual = tmp.NodoConexion; listaMovimientos.Add(tmp.direccionUsada); }while(actual.numeroDeNodo != destino.numeroDeNodo); return new Queue<Direccion>(listaMovimientos); }
public static Queue<Direccion> Dijkstra(Nodo[] mapa, Nodo origen, Nodo destino) { movimientos = new Queue<Direccion>(); HacerDijkstra(mapa, origen, destino, 0); Console.WriteLine("Distancia a recorrer :" + destino.distancia); return movimientos; }
private void ConfeccionarCamino() { int intentos; int repeticiones = ITERACIONES; int castigo; Direccion direccion; Random random = new Random(System.DateTime.Now.Millisecond); int origen = kibus.OnToyY + kibus.OnToyX * 20; int destino = casa.OnToyY + casa.OnToyX * 20; //Setear los 2 nodos iniciales, origen y destino rectanguloOrigen = kibus.GetRectangulo(); while(repeticiones-->0) { Console.WriteLine("Iteracion #" + (ITERACIONES - repeticiones)); //Volver a iniciar los valores; nodosVisitados = new Nodo[20*20]; Nodo.CantidadNodosVisitados = 0; Conexion.conexionesUsadas = 0; nodosVisitados[destino] = new Nodo(); nodosVisitados[origen] = new Nodo(); kibus.Mover(rectanguloOrigen); while(kibus.OnToyX != casa.OnToyX || kibus.OnToyY != casa.OnToyY) { modoGrafico = Hardware.TeclaPulsada(Sdl.SDLK_g); if(modoGrafico) { DibujarTodo(); Hardware.EscribirTexto("Entrenando", 641, 10); Hardware.RefrescarPantalla(); } int anterior; int actual; intentos = 0; Sdl.SDL_Rect rectTemp = kibus.GetRectangulo(); do { kibus.Mover(rectTemp); do { direccion = (Direccion)random.Next(0, (int)Direccion.MISINGNO); intentos++; }while(!IntentarMover(kibus, direccion, false)); anterior = kibus.OnToyY + kibus.OnToyX * 20; kibus.Mover(direccion); actual = kibus.OnToyY + kibus.OnToyX * 20; if(nodosVisitados[actual] == null) { nodosVisitados[actual] = new Nodo(); break; } }while(intentos < 8); Conexion cnxDestino; if(nodosVisitados[anterior].conexiones[(int)direccion] == null) { cnxDestino = new Conexion(); cnxDestino.direccionUsada = direccion; } else { cnxDestino = nodosVisitados[anterior].conexiones[(int)direccion]; } cnxDestino.NodoConexion = nodosVisitados[actual]; nodosVisitados[anterior].conexiones[(int)direccion] = cnxDestino; if(modoGrafico) { Hardware.Pausar(10); } } //Console.WriteLine("CASA: {0},{1}", casa.OnToyX,casa.OnToyY); //Console.WriteLine("KIBU: {0},{1}", kibus.OnToyX,kibus.OnToyY); //Seteo de los valores minimos y máximos if(Conexion.conexionesUsadas > maximo) maximo = Conexion.conexionesUsadas; if(Conexion.conexionesUsadas < minimo) minimo = Conexion.conexionesUsadas; mediaHistorica = (maximo + minimo)/2; castigo = /*Math.Abs(*/Conexion.conexionesUsadas - mediaHistorica/*)*/; Console.WriteLine("Maximo :\t" + maximo); Console.WriteLine("Minimo :\t" + minimo); Console.WriteLine("Media :\t" + mediaHistorica); Console.WriteLine("Conexiones:\t" + Conexion.conexionesUsadas); Console.WriteLine("Castigo:\t" + castigo); Console.WriteLine(".------------------."); actualizarMundoValorifico(nodosVisitados, castigo); } }
private void actualizarMundoValorifico(Nodo[] nodosVisitados, int castigo) { for(int i = 0; i < nodosVisitados.Length; i++) { if(nodosVisitados[i] != null) { if(arregloNodosTotal[i] == null) { arregloNodosTotal[i] = nodosVisitados[i]; } else { //Checar las 8 conexiones del nodo y ver que fueron usadas, para aplicarles el castigop puesun. for(int j = 0; j < nodosVisitados[i].conexiones.Length; j++) { if(nodosVisitados[i].conexiones[j] != null) //Si la conexion se generó se verá actualizado su valor en el mapa { if(arregloNodosTotal[i].conexiones[j] == null) //si esto ocurre, se asignal la conexion tal cual, pues es nueva { arregloNodosTotal[i].conexiones[j] = nodosVisitados[i].conexiones[j]; } else //se actualizara el valor dependiendo del castigo { arregloNodosTotal[i].conexiones[j].Peso += castigo; } } //else, si no se utilizo la conexion, no tenemos que actualizar su situacion en el mapa } } } } }