/// <summary> /// Find the coords that are above, below, left, and right of the current cell, assuming they are valid /// </summary> /// <param name="current"></param> /// <returns>The valid coords around the current cell</returns> protected virtual IEnumerable <Coord> GetNeighbours(Node current) { var neighbours = new List <Cell> { Cuadrilla.GetCell(current.Coord.X - 1, current.Coord.Y), Cuadrilla.GetCell(current.Coord.X + 1, current.Coord.Y), Cuadrilla.GetCell(current.Coord.X, current.Coord.Y - 1), Cuadrilla.GetCell(current.Coord.X, current.Coord.Y + 1) }; return(neighbours.Where(x => x.Tipo != Enums.CellType.Invalido && x.Tipo != Enums.CellType.Solido).Select(x => x.Coord).ToArray()); }
/// <summary> /// Get the cost of the path between A and B /// </summary> /// <returns>Cost of the path or 0 if no path has been found</returns> protected int GetPathCost() { if (Ruta == null) { return(0); } var cost = 0; foreach (var step in Ruta) { cost += Cuadrilla.GetCell(step.X, step.Y).Weight; } return(cost); }
public void Dibujar() { _cellWidth = _pb.Width / Horizontales; _cellHeight = _pb.Height / Verticales; var image = new Bitmap(_pb.Width, _pb.Height); using (var g = Graphics.FromImage(image)) { var background = new Rectangle(0, 0, image.Width, image.Height); g.FillRectangle(new SolidBrush(Color.White), background); for (var x = 0; x < Horizontales; x++) { for (var y = 0; y < Verticales; y++) { var cell = Cuadrilla.GetCell(x, y); switch (cell.Tipo) { case CellType.Vacio: switch (cell.Valor) { case 2: g.FillRectangle(Brushes.White, GetRectangle(x, y)); break; case 3: g.FillRectangle(Brushes.White, GetRectangle(x, y)); break; } break; case CellType.Solido: g.FillRectangle(Brushes.Black, GetRectangle(x, y)); break; case CellType.Camino: g.FillRectangle(Brushes.Red, GetRectangle(x, y)); break; case CellType.Abierto: g.FillRectangle(Brushes.LightSkyBlue, GetRectangle(x, y)); break; case CellType.Cerrado: g.FillRectangle(Brushes.LightSeaGreen, GetRectangle(x, y)); break; case CellType.Actual: g.FillRectangle(Brushes.Red, GetRectangle(x, y)); break; case CellType.A: g.DrawString("->", GetFont(), Brushes.Red, GetPoint(x, y)); break; case CellType.B: g.DrawString("->", GetFont(), Brushes.Red, GetPoint(x, y)); break; default: throw new ArgumentOutOfRangeException("Unknown cell type: " + cell); } g.DrawRectangle(Pens.Black, GetRectangle(x, y)); } } _pb.Image = image; } }
public override DetallesBusqueda MarcarRuta() { if (NodoActual == null) { if (!_ListaAbierta.Any()) { return(detallesBusqueda()); } // utilizar el nodo actual de la lista abierta para examinarlo NodoActual = _ListaAbierta.OrderBy(x => x.F).ThenBy(x => x.H).First(); // mover a la lista cerrada para no ser examinado de nuevo _ListaAbierta.Remove(NodoActual); Cerrada.Add(NodoActual); Cuadrilla.SetCell(NodoActual.Coord, Enums.CellType.Cerrado); _Vecinos.AddRange(GetNeighbours(NodoActual)); } if (_Vecinos.Any()) { Cuadrilla.SetCell(NodoActual.Coord, Enums.CellType.Actual); var vecinoDestino = _Vecinos.First(); _Vecinos.Remove(vecinoDestino); // si el vecino es el destino if (CoordsMatch(vecinoDestino, Destino)) { // construir ruta en base a lista cerrada si se llego al destino ruta = new List <Coord> { vecinoDestino }; int?Idpariente = NodoActual.Id; while (Idpariente.HasValue) { var NodoSiguiente = Cerrada.First(x => x.Id == Idpariente); ruta.Add(NodoSiguiente.Coord); Idpariente = NodoSiguiente.ParentId; } // reordenar la ruta desde el origen al destino ruta.Reverse(); return(detallesBusqueda()); } // costo del nodo actual + el valor del paso anterior y heuristica var Hn = GetH(vecinoDestino, Destino); var CostoCelda = Cuadrilla.GetCell(vecinoDestino.X, vecinoDestino.Y).Valor; var CostoVecino = NodoActual.G + CostoCelda + Hn; // el nodo con menor valor en la lista abierta var ItemListaAbierta = _ListaAbierta.FirstOrDefault(x => x.Id == GetExistingNode(true, vecinoDestino)); if (ItemListaAbierta != null && ItemListaAbierta.F > CostoVecino) { // utilizo el nodo con menor costo en la lista para crear ruta ItemListaAbierta.F = CostoVecino; ItemListaAbierta.ParentId = NodoActual.Id; } var itemListaCerrada = Cerrada.FirstOrDefault(x => x.Id == GetExistingNode(false, vecinoDestino)); if (itemListaCerrada != null && itemListaCerrada.F > CostoVecino) { //menor costo en lista cerrada itemListaCerrada.F = CostoVecino; itemListaCerrada.ParentId = NodoActual.Id; } if (ItemListaAbierta != null || itemListaCerrada != null) { return(detallesBusqueda()); } _ListaAbierta.Add(new Node(Id++, NodoActual.Id, vecinoDestino, NodoActual.G + CostoCelda, Hn)); Cuadrilla.SetCell(vecinoDestino.X, vecinoDestino.Y, Enums.CellType.Abierto); } else { Cuadrilla.SetCell(NodoActual.Coord, Enums.CellType.Cerrado); NodoActual = null; return(MarcarRuta()); } return(detallesBusqueda()); }