Eu tenho bots em uma formação retangular com linhas e colunas. Um problema surge quando um bot é adicionado ou removido da formação. Quando isso acontece, os robôs precisam se reorganizar para que a formação retangular ainda tenha aproximadamente a mesma proporção e seja o mais retangular possível. Como fazer isso?
Algumas ideias:
Quando um bot é adicionado ou removido, use o novo número total de bots e a proporção desejada desejada para calcular a nova largura e altura da formação que melhor se encaixa nessa proporção. De alguma forma, reorganize os robôs para se ajustarem às novas dimensões.
Quando um bot é removido, mova o bot que estava atrás dele para o seu lugar e continue até chegar ao final da formação. Então, mesmo fora da classificação traseira, tanto quanto possível, de alguma forma embaralhando os bots na classificação traseira.
Outra idéia que é completamente diferente é imitar a maneira como as estruturas das moléculas permanecem juntas. Faça com que cada bot queira estar cercado por outros quatro bots, atraindo os quatro bots mais próximos e repelindo o resto. Repelir todos os bots (incluindo os quatro) que estão muito próximos para garantir a separação usando a lei do quadrado inverso. Você também precisaria de uma força adicional para moldar toda a estrutura. Mas isso parece muito caro computacionalmente.
ATUALIZAÇÃO : Então, analisando a resposta de sarahm, criei uma boa função geral que fornece boas dimensões.
Primeiro resolvi a equação simultânea abaixo para largura e altura e depois arredondei as respostas.
width/height=aspect ratio of your choice
width*height=number of bots
Isso fornece o retângulo inteiro mais próximo dessa proporção para o seu número de bots. O retângulo mais próximo será na metade do tempo muito grande e na metade do tempo será muito pequeno (é claro que às vezes será correto, mas quem se importa com isso). Nos casos em que o retângulo é um pouco grande demais, nada precisa ser feito. O ranking traseiro acaba ficando quase cheio, o que é ideal. Nos casos em que o retângulo é um pouco pequeno demais, você tem problemas, porque esse pequeno excesso de excesso terá que ir para sua própria classificação, criando uma classificação com apenas alguns bots, o que não parece bonito. Há também casos em que a diferença é grande(maior que a metade da largura); nesse caso, adicione ou subtraia uma classificação para diminuir a diferença. Em seguida, quando o retângulo for muito pequeno, adicione uma coluna para torná-lo um pouco maior. Depois de fazer isso, parece que o back rank sempre terá pelo menos metade do número de bots que os outros.
ATUALIZAR
Depois de obter as dimensões, compare-as com as dimensões atuais. Se a fachada da nova dimensão for maior, para cada classificação, solte bots da classificação abaixo e empurre-os para a classificação atual até que o número de bots nessa classificação seja igual à fachada. Continue esse algoritmo até chegar à classificação de trás. Usando esse algoritmo, os bots se moverão para caber na nova dimensão com eficiência. Depois disso, eu simplesmente empurro o novo velho para a fila de trás. O algoritmo é um pouco diferente para os casos em que a nova fachada é menor, mas você pode descobrir!
Há mais dois problemas a seguir. Exclusão e um método de adição mais flexível, em que novos bots não são necessariamente atribuídos ao back rank, mas a posição mais próxima deles no momento em que são adicionados.
fonte
Respostas:
Outra técnica é imitar a usada pelos batalhões napoleônicos (e provavelmente já nas falanges gregas, se não mais).
A fachada geralmente é mantida constante e, quando um homem cai (em qualquer posição, exceto na parte de trás), ele é substituído pelo homem diretamente atrás dele, dando um passo à frente. Os suboficiais são embaralhados pelos suboficiais para garantir que alguns homens se encontrem no extremo de cada flanco e, caso contrário, preencham uniformemente.
A fachada é reduzida apenas quando a fila de trás cai abaixo das densidades pré-especificadas. Da mesma forma, quando a fila de trás está cheia, os extras começam a preencher uma fila adicional de ambos os flancos, e então a fachada é aumentada.
Ao mudar de fachada, sugiro que seus bots saiam da fila de trás para os dois flancos ao aumentar a fachada e entrem nos dois flancos para a fila de trás ao reduzir a fachada.
Se estou certo ao deduzir que você está procurando uma impressão "militar" e fazer com que as organizações de bot pareçam falanges, acredito que esse reorganização ordenada é a melhor maneira de atingir esse objetivo.
Atualização :
Uma maneira simples de gerenciar a fila de trás é dividir as unidades da fila de trás em três esquadrões: um em cada flanco e outro no centro. Dependendo se a fachada é ímpar ou par, e se o número de unidades da fila de trás é congruente a 0,1 ou 2 mod 3, há exatamente seis casos para gerenciar.
Como um aprimoramento ao acima, considere espaçar a (s) última (s) unidade (s) de cada esquadrão da linha de trás quando o preenchimento cair abaixo de um limite, assim:
xxx.x .... x.xxx.x .... x. xxx
ou este:
xx.xx..x.xxx.x ... xxxx
Um pouco mais de trabalho, para uma aparência ainda melhor.
Atualização # 2 :
Uma reflexão adicional sobre a profundidade da formação. O impacto do tiro de vôlei, combinado com a baioneta moderna, tornou profundidades de 3 ou 4 adequadas no final do século XVIII e início do século XIX. (Os britânicos raramente brigavam em duas fileiras, ao contrário da crença popular, até o final de uma batalha; por um lado, faziam suas filas muito longas para formarem um quadrado rapidamente.) Antes disso, era comum ter profundidades maiores, talvez até 8 ou 10 para uma falange grega equipada com Sarissa. Escolha uma profundidade que crie a impressão que você deseja.
Os exércitos na vida real tentam manter a fachada da unidade o maior tempo possível, às custas do aumento da fragilidade da unidade, pois isso simplifica a disposição de um campo de batalha. César em Fársalo reduziu deliberadamente a profundidade de sua unidade para aumentar a fachada para corresponder à das forças de Pompeu. Como diz a citação: "Vencemos ou morremos hoje; os homens de Pompeu têm outras opções". (que César havia inteligente e cuidadosamente assegurado, é claro).
fonte
Supondo que uma unidade é uma estrutura de dados linear (por exemplo, uma lista ) de bots.
Primeiro, você deve adicionar / remover o bot de / para a estrutura de dados e determinar o novo número de bots na unidade.
Em seguida, você deve determinar a nova quantidade de linhas e colunas usando https://en.wikipedia.org/wiki/Integer_factorization .
Obviamente, isso nem sempre é possível devido aos números primos . Quando o novo tamanho da unidade é um número primo, você precisa usar o próximo tamanho de unidade maior que não é.
Em seguida, apenas itere sobre a estrutura de dados, atribuindo bots em ordem às linhas e colunas.
Para colocar os bots, apenas itere sobre a estrutura de dados, atribuindo a cada bot uma posição deslocada da posição das unidades por uma quantidade determinada pela linha e coluna em que o bot está (ou defina esse ponto como um alvo para o movimento dos bots).
Para fazer uma unidade com o centro em um canto , a posição de um bot é dada por
unitPosition + cabeçalho * columnNumber * botSeparationDistance + rightVector * rowNumber * botSeparationDistance
Para fazer uma unidade com o centro no meio , a posição de um bot é dada por
unitPosition + posição * (* columnNumber unitSeparationDistance - 0,5 * (* numberOfColumns botSeparationDistance) + rightVector * RowNumber * botSeparationDistance - 0,5 * (* NumberOfRows botSeparationDistance)
onde cabeçalho é um vetor apontando na direção em que a unidade está voltada e rightVector é um vetor ortogonal ao cabeçalho .
O botSeparationDistance pode ser ajustado para fazer com que os bots fiquem mais afastados ou mais próximos.
Se você está se sentindo fantasia, você pode compensar a última fileira de bots por rightVector * 0.5 * (numberOfColumns - actualNumberOfBotsInRow) para centrar -los sobre a formação .
fonte
Eu armazenaria as posições possíveis em um gráfico com valores maiores sendo retângulos menores.
Toda vez que um robô é removido, pesquise todos os outros robôs e encontre aquele em um nó com o menor valor. Use um algoritmo A * ou BST para encontrar um caminho do menor valor para o espaço vago. Se não houver robô com um valor menor que o removido, não faça nada.
Você também deve poder controlar como o retângulo decai fazendo isso. Por exemplo, no gráfico abaixo, quando um robô sai do lado inferior, ele vem ocupar seu lugar.
Aqui o de 3,8 é removido, de modo que o de 2,5 chega e preenche seu lugar.
Outro exemplo. Aqui 2.8 é removido para que o menor nó 2.2 chegue ao seu lugar.
Você provavelmente deseja um anel de nós com o valor 0 que você nunca preenche do lado de fora para que seu algoritmo de busca de caminhos encontre o buraco.
Um bom tutorial sobre A * pode ser encontrado aqui .
fonte