示例#1
0
// PRE: coord_en_pixeles=false si se pasan posiciones en tiles. POST: camino posee pares de posiciones EN TILES que debe recorrer secuencialmente.
Camino Calculador::obtenerCaminoMin(Escenario *esc, Coordenada coord_orig, Coordenada coord_dest, Coordenada coord_ceros, bool coord_en_pixeles) {
	Camino camino;
	Coordenada pos_tile_inicial, pos_tile_destino;
	try {
		if (coord_en_pixeles) {
			pos_tile_inicial = tileParaPixel(coord_orig, coord_ceros);
			pos_tile_destino = tileParaPixel(coord_dest, coord_ceros);
		} else {
			pos_tile_inicial = coord_orig;
			pos_tile_destino = coord_dest;
		}

		//if ((!esc->tileEsOcupable(pos_tile_destino)) || (pos_tile_inicial == pos_tile_destino))
		if ((pos_tile_inicial == pos_tile_destino) || ((!esc->tileEsOcupable(pos_tile_destino)) && distEuclidiana(pos_tile_inicial, pos_tile_destino) < 2))
			return camino;
	} catch ( FueraDeEscenario &e ) {
		return camino;
	}

	std::vector<Nodo*> visitados, vecinos;
	Nodo *tile_inicial = new Nodo(pos_tile_inicial, NULL, pos_tile_destino);
	Nodo nodoFinal;
	vecinos.push_back(tile_inicial);
	std::vector<Nodo*>::iterator it, pActualIt;
	Nodo *pActual;

	try {
		while (!vecinos.empty()) {
			bool encontrado = false;
			Coordenada c;
			pActualIt = vecinos.begin();
			pActual = (*pActualIt);

			for (c.y = pActual->pos.y-1; c.y <= pActual->pos.y+1; c.y++) {
				for (c.x = pActual->pos.x-1; c.x <= pActual->pos.x+1; c.x++) {
					if ( (!pActual->padre || !pActual->padre->esTile(c)) && (!pActual->esTile(c)) ) {

						if (c == pos_tile_destino) {
							Nodo nodoAux(c, pActual, pos_tile_destino);
							if ((!encontrado) || nodoAux.f() < nodoFinal.f())
								nodoFinal = nodoAux;
							encontrado = true;

						} else if (esc->tileEsOcupable(c) && std::find_if(visitados.begin(), visitados.end(), Nodo::CmpPointerXY(c)) == visitados.end()) {
							it = std::find_if(vecinos.begin(), vecinos.end(), Nodo::CmpPointerXY(c));
							if (it == vecinos.end()) {
								std::vector<Nodo*>::iterator itV = std::lower_bound(vecinos.begin(), vecinos.end(), Nodo(c, pActual, pos_tile_destino), Nodo::CmpNodoVsPointerF());
								vecinos.insert(itV, new Nodo(c, pActual, pos_tile_destino));
							} else if ((*it)->guardarMenorG(pActual)) {
								Nodo *ppVecino = *it;
								vecinos.erase(it);
								it = std::lower_bound(vecinos.begin(), vecinos.end(), ppVecino, Nodo::CmpPointersF());
								vecinos.insert(it, ppVecino);
							}
						}

					}
				}
			}
			if (encontrado) {
				pActual = nodoFinal.padre;
				throw DestinoEncontrado();
			}
			visitados.push_back(pActual);
			pActualIt = std::find_if(vecinos.begin(), vecinos.end(), Nodo::CmpPointerXY(pActual->pos));
			vecinos.erase(pActualIt);
		}
	} catch ( DestinoEncontrado &e ) {	// pActual tiene ahora el último tile del camino, NO el destino.
		while (!pActual->esTile(tile_inicial)) {
				camino.agregar( pActual->pos );
				pActual = pActual->padre;
			}
			camino.invertir();
			if (esc->tileEsOcupable(pos_tile_destino))
				camino.agregar( pos_tile_destino );
			// Nuevo: En el caso de que se pueda hacer el camino entero hasta el lugar anterior porque el destino está ocupado, lo hará.
	}

	for (pActualIt = visitados.begin(); pActualIt < visitados.end(); ++pActualIt)
		delete *pActualIt;
	for (pActualIt =   vecinos.begin(); pActualIt <   vecinos.end(); ++pActualIt)
		delete *pActualIt;
	visitados.clear();
	vecinos.clear();

	return camino;
}
示例#2
0
		bool operator()(const Nodo* l, const Nodo r) {
			return (l->f() < r.f());
		}
示例#3
0
		bool operator()(const Nodo l, const Nodo* r) {
			return (l.f() < r->f());
		}
示例#4
0
	bool operator< (const Nodo & r) const {
		return (this->f() < r.f());
	}