/// <summary> /// Olha aos arredores do agente em busca de entidades para ele trabalhar. /// </summary> /// <returns>Lista de entidades encontradas.</returns> public List <Entidade> OlhaArredores() { List <Entidade> entidadesEncontradas = new List <Entidade>(); foreach (Direcoes valor in Enum.GetValues(typeof(Direcoes))) { Coordenadas coordenadas = Geral.GetCoordenadasPorDirecao(this.Coordenadas, valor); Entidade entidade = Ambiente.GetEntidade(coordenadas); if (entidade is Agente || entidade is Lixeira || entidade is Lixo) { entidadesEncontradas.Add(entidade); } else if (valor == Direcoes.NENHUMA && entidade is Multiplo) { entidadesEncontradas.AddRange((entidade as Multiplo).Entidades.Except(new List <Entidade> { this })); } Thread.Sleep(MainWindow.VelocidadeAgentes); } return(entidadesEncontradas); }
/// <summary> /// Agente com informações básicas do ambiente. /// </summary> /// <param name="coordenadas">Posição no ambiente.</param> /// <param name="numero">Numero de identificação.</param> public Agente(Coordenadas coordenadas, int numero) : base(coordenadas) { Numero = numero; SacoLixoSeco = new ObservableCollection <Lixo>(); SacoLixoOrganico = new ObservableCollection <Lixo>(); _naoEncontrouNada = 0; CapacidadeMaximaLixoOrganico = 2; CapacidadeMaximaLixoSeco = 2; }
/// <summary> /// Pega uma entidade na posição desejada. /// </summary> /// <param name="coordenadas">Posição no ambiente.</param> /// <returns>Entidade encontrada.</returns> public static Entidade GetEntidade(Coordenadas coordenadas) { if (Geral.EstaLimite(coordenadas)) { return(_ambiente[coordenadas.Y, coordenadas.X]); } return(null); }
/// <summary> /// Move uma entidade para outro ponto qualquer. Se Já houver uma entidade, as duas se transformam em uma entidade múltipla que contém as duas. /// Se houver só um item nessa lista depois de mover, esse item se toma o lugar da entidade múltipla. /// </summary> /// <param name="destino">Posição de destino no ambiente.</param> /// <param name="entidade">Entidade que será movida.</param> public static void MoveEntidade(Coordenadas destino, Entidade entidade) { Entidade orig = _ambiente[entidade.Coordenadas.Y, entidade.Coordenadas.X]; if (orig is Multiplo) { (orig as Multiplo).Entidades.Remove(entidade); if ((orig as Multiplo).Entidades.Count == 1) { _ambiente[entidade.Coordenadas.Y, entidade.Coordenadas.X] = (orig as Multiplo).Entidades[0]; } else if ((orig as Multiplo).Entidades.Count == 0) { _ambiente[entidade.Coordenadas.Y, entidade.Coordenadas.X] = null; } } else { _ambiente[entidade.Coordenadas.Y, entidade.Coordenadas.X] = null; } AmbienteChange?.Invoke(_ambiente[entidade.Coordenadas.Y, entidade.Coordenadas.X], new Coordenadas { X = entidade.Coordenadas.X, Y = entidade.Coordenadas.Y }); entidade.Coordenadas = destino; Entidade dest = _ambiente[destino.Y, destino.X]; if (dest != null) { Multiplo multiplo; if (dest is Multiplo) { multiplo = dest as Multiplo; multiplo.Entidades.Add(entidade); } else { multiplo = new Multiplo(destino); multiplo.Entidades.Add(_ambiente[destino.Y, destino.X]); multiplo.Entidades.Add(entidade); } _ambiente[destino.Y, destino.X] = multiplo; } else { _ambiente[destino.Y, destino.X] = entidade; } AmbienteChange?.Invoke(_ambiente[destino.Y, destino.X], destino); }
/// <summary> /// Pega lixo em determinada coordenada. /// </summary> /// <param name="coordenadas">Coordenadas de onde o lixo está.</param> /// <returns>Se conseguiu pegar o lixo ou não.</returns> public bool PegaLixo(Coordenadas coordenadas) { Entidade entidade = Ambiente.GetEntidade(coordenadas); Lixo lixo = null; if (entidade is Multiplo) { lixo = (entidade as Multiplo).Entidades.Find(e => e is Lixo) as Lixo; } else if (entidade is Lixo) { lixo = entidade as Lixo; } if (lixo != null && (lixo.Tipo == TipoLixo.ORGANICO && !SacoLixoOrganicoEstaCheio() || lixo.Tipo == TipoLixo.SECO && !SacoLixoSecoEstaCheio())) { bool sucesso = VaiAte(coordenadas); Multiplo multiplo = Ambiente.GetEntidade(this.Coordenadas) as Multiplo; if (multiplo != null && sucesso) { sucesso = false; lixo = multiplo.Entidades.Find(e => e is Lixo) as Lixo; if (lixo.Tipo == TipoLixo.ORGANICO && !SacoLixoOrganicoEstaCheio()) { this.SacoLixoOrganico.Add(lixo); multiplo.Entidades.Remove(lixo); sucesso = true; } else if (lixo.Tipo == TipoLixo.SECO && !SacoLixoSecoEstaCheio()) { this.SacoLixoSeco.Add(lixo); multiplo.Entidades.Remove(lixo); sucesso = true; } if (multiplo.Entidades.Count <= 1) { Ambiente.AtualizaEntidade(this); } else { Ambiente.AtualizaEntidade(multiplo); } } return(sucesso); } return(false); }
/// <summary> /// Verifica se uma coordenada é diretamente do lado de outra. /// </summary> /// <param name="pontoFinal">Ponto a ser verificado a coordenada.</param> /// <returns></returns> private bool EstaDiretamenteAoLado(Coordenadas pontoFinal) { if (Geral.GetCoordenadasPorDirecao(this.Coordenadas, Direcoes.CIMA).X == pontoFinal.X && Geral.GetCoordenadasPorDirecao(this.Coordenadas, Direcoes.CIMA).Y == pontoFinal.Y || Geral.GetCoordenadasPorDirecao(this.Coordenadas, Direcoes.BAIXO).X == pontoFinal.X && Geral.GetCoordenadasPorDirecao(this.Coordenadas, Direcoes.BAIXO).Y == pontoFinal.Y || Geral.GetCoordenadasPorDirecao(this.Coordenadas, Direcoes.ESQUERDA).X == pontoFinal.X && Geral.GetCoordenadasPorDirecao(this.Coordenadas, Direcoes.ESQUERDA).Y == pontoFinal.Y || Geral.GetCoordenadasPorDirecao(this.Coordenadas, Direcoes.DIREITA).X == pontoFinal.X && Geral.GetCoordenadasPorDirecao(this.Coordenadas, Direcoes.DIREITA).Y == pontoFinal.Y) { return(true); } return(false); }
/// <summary> /// Move o agente aleatoriamente em uma posição adjacente ou na linha ou na coluna do agente. /// </summary> /// <param name="adjacente">Se ele deve se mover somente na linha ou coluna adjacente.</param> /// <returns>Retorno se conseguiu se mover ou não.</returns> public bool MoveAleatoriamente(bool adjacente = true) { Coordenadas coordenadas = new Coordenadas { X = this.Coordenadas.X, Y = this.Coordenadas.Y }; List <Direcoes> direcoes = new List <Direcoes> { Direcoes.CIMA, Direcoes.BAIXO, Direcoes.ESQUERDA, Direcoes.DIREITA, }; while (!Geral.PodeCaminhar(coordenadas) && !Geral.EstaTrancado(this.Coordenadas)) { if (adjacente) { direcoes.Shuffle(); foreach (Direcoes direcao in direcoes) { coordenadas = Geral.GetCoordenadasPorDirecao(this.Coordenadas, direcao); if (Geral.PodeCaminhar(coordenadas)) { break; } } } else { // Se for zero move no x, se não, no y. if (Geral.Random.Next(2) == 0) { coordenadas.X = Geral.Random.Next(Ambiente.Colunas); coordenadas.Y = this.Coordenadas.Y; } else { coordenadas.X = this.Coordenadas.X; coordenadas.Y = Geral.Random.Next(Ambiente.Linhas); } } } return(VaiAte(coordenadas)); }
private bool Desviou(Direcoes[] sentidoObstaculo, Coordenadas pontoObstaculo, Coordenadas pontoFinal) { Direcoes[] direcoesChecar = GetSentidoAtePonto(pontoObstaculo); Direcoes[] pontoFinalDirecoes = GetSentidoAtePonto(pontoFinal); if (EstaDiretamenteAoLado(pontoFinal)) { return(true); } if (sentidoObstaculo[0] != Direcoes.NENHUMA) { if (direcoesChecar[0] == Direcoes.ESQUERDA && sentidoObstaculo[0] == Direcoes.DIREITA) { return(true); } else if (direcoesChecar[0] == Direcoes.DIREITA && sentidoObstaculo[0] == Direcoes.ESQUERDA) { return(true); } else if (pontoFinalDirecoes[0] == GetSentidoAtePonto(this.Coordenadas)[0]) { return(true); } } else { if (direcoesChecar[1] == Direcoes.CIMA && sentidoObstaculo[1] == Direcoes.BAIXO) { return(true); } else if (direcoesChecar[1] == Direcoes.BAIXO && sentidoObstaculo[1] == Direcoes.CIMA) { return(true); } else if (pontoFinalDirecoes[1] == GetSentidoAtePonto(this.Coordenadas)[1]) { return(true); } } return(false); }
public bool DespejaLixo(Coordenadas coordenadas) { Lixeira lixeira = Ambiente.GetEntidade(coordenadas) as Lixeira; ObservableCollection <Lixo> sacoLixo = null; if (lixeira.Tipo == TipoLixo.ORGANICO) { sacoLixo = this.SacoLixoOrganico; } else if (lixeira.Tipo == TipoLixo.SECO) { sacoLixo = this.SacoLixoSeco; } if (lixeira != null && sacoLixo != null) { VaiAte(coordenadas); if (EstaDiretamenteAoLado(coordenadas)) { while (sacoLixo.Count != 0 && !lixeira.EstaCheia()) { Lixo lixo = sacoLixo.First(); if (lixo != null) { lixeira.Lixos.Add(lixo); sacoLixo.Remove(lixo); } } Ambiente.AtualizaEntidade(lixeira); Ambiente.AtualizaEntidade(this); if (sacoLixo.Count == 0) { return(true); } } } return(false); }
/// <summary> /// Retorna o sentido até o ponto que o agente precisa tomar. /// </summary> /// <param name="pontoFinal">Ponto a ser verificado o sentido.</param> /// <returns>Array de duas posições onde a primeira é a direção de x e a segunda é a direção de y.</returns> private Direcoes[] GetSentidoAtePonto(Coordenadas pontoFinal) { Direcoes sentidoX; Direcoes sentidoY; #region Decide se o agente precisará ir para direita ou esquerda para chegar. if (pontoFinal.X > this.Coordenadas.X) { sentidoX = Direcoes.DIREITA; } else if (pontoFinal.X < this.Coordenadas.X) { sentidoX = Direcoes.ESQUERDA; } else { sentidoX = Direcoes.NENHUMA; } #endregion Decide se o agente precisará ir para direita ou esquerda para chegar. #region Decide se o agente precisará ir para cima ou para baixo para chegar. if (pontoFinal.Y > this.Coordenadas.Y) { sentidoY = Direcoes.BAIXO; } else if (pontoFinal.Y < this.Coordenadas.Y) { sentidoY = Direcoes.CIMA; } else { sentidoY = Direcoes.NENHUMA; } #endregion Decide se o agente precisará ir para cima ou para baixo para chegar. return(new Direcoes[] { sentidoX, sentidoY }); }
/// <summary> /// Coloca uma entidade na posição definida. /// </summary> /// <param name="coordenadas">Posição no ambiente.</param> /// <param name="entidade">Entidade que será colocada.</param> public static void SetEntidade(Coordenadas coordenadas, Entidade entidade) { Entidade pos = _ambiente[coordenadas.Y, coordenadas.X]; if (pos != null) { _entidades.Remove(pos); _agentes.Remove(pos as Agente); _lixeiras.Remove(pos as Lixeira); _lixos.Remove(pos as Lixo); } _ambiente[coordenadas.Y, coordenadas.X] = entidade; if (entidade != null) { entidade.Coordenadas.X = coordenadas.X; entidade.Coordenadas.Y = coordenadas.Y; if (entidade is Agente) { _agentes.Add(entidade as Agente); } else if (entidade is Lixeira) { _lixeiras.Add(entidade as Lixeira); } else if (entidade is Lixo) { _lixos.Add(entidade as Lixo); } _entidades.Add(entidade); } AmbienteChange?.Invoke(entidade, coordenadas); }
/// <summary> /// Lixo com informações básicas do ambiente e tipo. /// </summary> /// <param name="coordenadas">Posição no ambiente.</param> /// <param name="tipo">Tipo de lixo que ele é.</param> public Lixo(Coordenadas coordenadas, TipoLixo tipo) : base(coordenadas) { Tipo = tipo; }
/// <summary> /// Entidade com posição pré definida de espaço. /// </summary> /// <param name="coordenadas">Posição y no ambiente.</param> public Entidade(Coordenadas coordenadas) { Coordenadas = coordenadas; }
/// <summary> /// Lixeira com informações básicas do ambiente. /// </summary> /// <param name="coordenadas">Posição no ambiente.</param> /// <param name="tipo">Tipo de lixo que ela suporta.</param> public Lixeira(Coordenadas coordenadas, TipoLixo tipo) : base(coordenadas) { Lixos = new ObservableCollection <Lixo>(); Tipo = tipo; }
public Multiplo(Coordenadas coordenadas) : base(coordenadas) { Entidades = new List <Entidade>(); }
/// <summary> /// Desvia de uma entidade no caminho. /// </summary> /// <param name="pontoObstaculo">Coordenadas da entidade a ser desviada.</param> /// <param name="pontoFinal">Coordenadas do ponto em que ele tentará chegar com esse desvio (otimiza o melhor lugar para ele escolher onde desviar).</param> public void Desvia(Coordenadas pontoObstaculo, Coordenadas pontoFinal) { Direcoes direcaoIr; // A direção que ele está indo quando encontrou o obstáculo. Direcoes direcaoDesvio; // Direção que ele deverá ir para desviar. Direcoes direcaoChecagem; // Direção que ele deverá checar se pode caminhar para se livrar do obstáculo. Direcoes[] sentidoObstaculo = GetSentidoAtePonto(pontoObstaculo); // Em que sentidos o obstáculo está do agente. Direcoes[] sentidoCaminho = GetSentidoAtePonto(pontoFinal); // Em que sentido está o lugar ao qual o agente quer chegar. #region Vê para onde ele sempre tentará chegar. if (Math.Abs(pontoFinal.X - this.Coordenadas.X) > Math.Abs(pontoFinal.Y - this.Coordenadas.Y)) { direcaoIr = pontoFinal.X > this.Coordenadas.X ? Direcoes.DIREITA : Direcoes.ESQUERDA; } else { direcaoIr = pontoFinal.Y > this.Coordenadas.Y ? Direcoes.BAIXO : Direcoes.CIMA; } #endregion Vê para onde ele sempre tentará chegar. direcaoChecagem = direcaoIr; #region Vê o foco para tentar desviar. if (direcaoIr == Direcoes.ESQUERDA || direcaoIr == Direcoes.DIREITA) { direcaoDesvio = sentidoCaminho[1] == Direcoes.BAIXO ? Direcoes.BAIXO : Direcoes.CIMA; } else { direcaoDesvio = sentidoCaminho[0] == Direcoes.ESQUERDA ? Direcoes.ESQUERDA : Direcoes.DIREITA; } #endregion Vê o foco para tentar desviar. int qtdMudancasDirecao = 0; int demaisCaminho = 0; bool semFim = false; while (!Desviou(sentidoObstaculo, pontoObstaculo, pontoFinal) && !semFim) { Coordenadas coordenadasDesvio = Geral.GetCoordenadasPorDirecao(this.Coordenadas, direcaoDesvio); Coordenadas coordenadasChecagem = Geral.GetCoordenadasPorDirecao(this.Coordenadas, direcaoChecagem); Coordenadas coordenadasDestino = Geral.GetCoordenadasPorDirecao(this.Coordenadas, direcaoIr); if (Geral.PodeCaminhar(coordenadasDestino)) { VaiAte(coordenadasDestino); } else if (Geral.PodeCaminhar(coordenadasChecagem) && demaisCaminho < 3) { demaisCaminho++; VaiAte(coordenadasChecagem); } else if (Geral.PodeCaminhar(coordenadasDesvio) && !Geral.PodeCaminhar(coordenadasChecagem) && demaisCaminho < 3) { demaisCaminho++; VaiAte(coordenadasDesvio); } else if ((!Geral.PodeCaminhar(coordenadasDesvio) && !Geral.PodeCaminhar(coordenadasChecagem)) || demaisCaminho >= 3) { if (demaisCaminho >= 3) { demaisCaminho = 0; } if (direcaoDesvio == direcaoIr && qtdMudancasDirecao >= 3) { break; } if (direcaoDesvio == Direcoes.BAIXO) { direcaoDesvio = Direcoes.ESQUERDA; direcaoChecagem = Direcoes.BAIXO; qtdMudancasDirecao++; } else if (direcaoDesvio == Direcoes.ESQUERDA) { direcaoDesvio = Direcoes.CIMA; direcaoChecagem = Direcoes.ESQUERDA; qtdMudancasDirecao++; } else if (direcaoDesvio == Direcoes.CIMA) { direcaoDesvio = Direcoes.DIREITA; direcaoChecagem = Direcoes.CIMA; qtdMudancasDirecao++; } else if (direcaoDesvio == Direcoes.DIREITA) { direcaoDesvio = Direcoes.BAIXO; direcaoChecagem = Direcoes.DIREITA; qtdMudancasDirecao++; } } else { semFim = true; } } }
/// <summary> /// Vai até a coordenada informada passo a passo. /// </summary> /// <param name="coordenadas">Coordenadas para onde o agente deverá ir.</param> /// <returns>Se conseguiu ou não se mover até o local desejado.</returns> public bool VaiAte(Coordenadas coordenadas) { int desviou = 0; int andou = 0; int tentativas = 0; while ((this.Coordenadas.X != coordenadas.X || this.Coordenadas.Y != coordenadas.Y)) { if (tentativas > 3) { return(false); } Coordenadas canditata = new Coordenadas(); if (((Ambiente.GetEntidade(coordenadas) is Agente || Ambiente.GetEntidade(coordenadas) is Lixeira)) && EstaDiretamenteAoLado(coordenadas)) { break; } int distanciaX = coordenadas.X - this.Coordenadas.X; int distanciaY = coordenadas.Y - this.Coordenadas.Y; if (Math.Abs(distanciaX) > Math.Abs(distanciaY)) { if (coordenadas.X > this.Coordenadas.X) { canditata.X = this.Coordenadas.X + 1; } else { canditata.X = this.Coordenadas.X - 1; } canditata.Y = this.Coordenadas.Y; } else { if (coordenadas.Y > this.Coordenadas.Y) { canditata.Y = this.Coordenadas.Y + 1; } else { canditata.Y = this.Coordenadas.Y - 1; } canditata.X = this.Coordenadas.X; } if (Geral.PodeCaminhar(canditata)) { Ambiente.MoveEntidade(canditata, this); if (andou > 2) { desviou = 0; } andou++; } else { if (desviou < 2) { Desvia(canditata, coordenadas); desviou++; } else { MoveAleatoriamente(); MoveAleatoriamente(); desviou = 0; } tentativas++; andou = 0; } Thread.Sleep(MainWindow.VelocidadeAgentes); } return(true); }