Prefácio
Um algoritmo de pesquisa é comumente conhecido como algoritmo A-Star. Este é um algoritmo que possui vários nós no plano do gráfico para encontrar o menor custo de passagem. Comumente usado em jogos
Um labirinto construído através de uma matriz bidimensional, "%" representa a parede, a é o ponto de partida, B é o ponto final "#" representa o obstáculo e "*" representa o caminho calculado pelo algoritmo
Estrutura de código deste artigo:
% % % % % % % % %ornmos % % ooooo % oo # oo % % a # o b % % oo # oo % ooooo % % % % % % % % % % %ar ==========================================================================================================================================================================================================roeroeóóó ,ó quase quase quase quase experiênciaeeó oo * oo % % o * # * o % a # o B % % oo # oo % oo % % % % % % % % <
Teoria do algoritmo
A fórmula central do algoritmo é: f = g+h
Pense nos nós no mapa como uma grade.
G = o consumo de movimento de mover -se para o nó especificado na grade do ponto de partida A ao longo do caminho gerado. Neste exemplo, fazemos o custo horizontal ou vertical 10 e a direção diagonal custa 14. Tomamos esses valores porque estamos ao longo da diagonal
A distância é a raiz número 2 ou cerca de 1,414 vezes a quantidade tomada para mover horizontal ou verticalmente. Por simplicidade, aproximamos o uso de 10 e 14.
Como estamos calculando o valor G que leva a um quadrado ao longo de um caminho específico, o método de avaliação é tomar o valor G de seu nó pai e, em seguida, adicionar 14 e 10, respectivamente, de acordo com sua direção diagonal ou ângulo reto (não diagonal) em relação ao nó pai. No exemplo, este
A demanda por cada método se torna mais porque obtivemos mais de um quadrado de fora da grade inicial.
H = o consumo estimado de movimento da grade atual até o ponto final B. Por que é chamado de "estimativa"? Porque não temos como saber o comprimento do caminho com antecedência. Aqui usamos o método Manhattan, que calcula a horizontal e a vertical da grade atual para a grade de destino.
A soma do número de quadrados dos quadrados, ignorando a direção diagonal. Em seguida, multiplique o resultado por 10.
O valor de F é a soma de G e H, que é o padrão que usamos para julgar o caminho da prioridade. A grade com o menor valor de F é considerada o nó do caminho da prioridade.
Etapas de implementação
O algoritmo está escrito em Java, primeiro veja o conteúdo da classe de nó
pacote a_star_search; / ** * classe de nó * @author zx * */ public class node {private int x; // x coordena private int y; // y coordena o valor da string privada; // o valor do nó privado duplo fValue = 0; // f valor de gvalado duplo privado = 0; // g Valor hvalue duplo privado = 0; // Valate H Value Private Boolean acessível; // é acessível (é um nó privado de obstáculo) PNODE; // Nó dos pais Public Node (int x, int y, valor da string, alcance booleano) {super (); this.x = x; this.y = y; this.value = value; Acessível = acessível; } public node () {super (); } public int getx () {return x; } public void setx (int x) {this.x = x; } public int gety () {return y; } public void Sety (int y) {this.y = y; } public string getValue () {return value; } public void SetValue (valor da string) {this.value = value; } public Double getfValue () {return fValue; } public void setFValue (duplo fValue) {fValue = fValue; } public duplo getGValue () {return gvalue; } public void setGValue (duplo gvalue) {gvalue = gvalue; } public Double GethValue () {return hValue; } public void sethValue (duplo hvalue) {hValue = hValue; } public boolean isreachable () {return alcance; } public void setreachable (alcance booleano) {alcance = alcance; } public node getpNode () {return pnode; } public void setPNode (nó pnode) {pnode = pnode; }}Também preciso de uma classe de mapa. No método de construção de mapas, implemento um mapa de labirinto criando uma matriz bidimensional de nós, que inclui os pontos de partida e final.
pacote a_star_search; mapa de classe pública {node privado [] [] map; // Matriz de nó privada startNode; // iniciar o nó privado endnode; // ponto final map () {map = novo nó [7] [7]; para (int i = 0; i <7; i ++) {(int j = 0; Nó (i, j, "o", verdadeiro);}} para (int d = 0; d <7; d ++) {map [0] [d] .SetValue ("%"); map [0] [d] .SetReachable (false); map [d] [0] .SetValue ("%"); mapa [d] [0] .SetReachable (Fal se); mapa [6] [d] .SetValue ("%"); mapa [d] [6] .SetValue ("%"); mapa [d] [6] .SetReachable (false);} mapa [3] [1] .SetValue ("A"); StartNode = mapa [3] [1]; mapa [3] [5] .SetValue ("b"); endNode = map [3] [5]; for (int k = 1; k <= 3; k ++) {map [k+1] [3] .setValue ("#"); void showMap () {for (int i = 0; i <7; i ++) {for (int j = 0; j <7; j ++) {System.out.print (map [i] [j] .getValue ()+"");} system.out.println (");}}} node [] setMap (node [] [] map) {this.map = map;} public node getStartNode () {return startNode;} public void setStartNode (node startNode) {this.startNode = startNode;} public node getNode () {den) endnode; endNode;}}Aqui estão as classes Astar mais importantes
Processo de operação
1 Comece no ponto de partida A e salve -o como ponto pendente em uma "lista aberta", que é uma lista dos quadrados a serem verificados.
2 Encontre todos os quadrados acessíveis ou aceitáveis ao redor do ponto de partida e pule quadrados desagradáveis. Adicione -os à lista de abertura também. Salvar o ponto A para todas essas grades como a "grade pai". Quando queremos descrever o caminho, o quadrado dos pais
O material é muito importante. Seu objetivo específico será explicado mais tarde.
3 Exclua o ponto de partida A da lista aberta e adicione -a a uma "lista de fechamento" para salvar todos os quadrados que não precisam ser verificados novamente.
Após as etapas acima, a "lista aberta" contém todos os nós em torno do ponto de partida A, exceto pelos obstáculos. Seus nós pais são todos A. Através da fórmula F = G+H mencionados anteriormente, eles calculam os valores G, H e F de cada nó e, de acordo com o valor de F, são pequenos
Classificando para grande. E faça as seguintes operações no nó com o menor valor F
4. Remova -o da lista ON e adicione -o à lista off.
5. Verifique todas as grades adjacentes. Pule aqueles que não são passados (1. Na "lista de fechamento" e 2. Obstáculos) e adicione -os à lista aberta se ainda não estiverem nela. Pegue o quadrado selecionado como o nó pai do novo quadrado.
6. Se uma grade adjacente já estiver na lista aberta, verifique se o caminho atual é melhor. Em outras palavras, verifique se o valor G será menor se chegarmos a ele com um novo caminho. Se não, então nada
Fazer. (Aqui, não há julgamento no meu código)
7. Repetimos esse processo até que a grade de destino (ponto final "B") seja adicionada à "lista aberta", indicando que o ponto final B já está em torno do nó anterior adicionado à "lista de fechamento". Você só precisa dar um passo para atingir o ponto final B.
8. Adicionamos o ponto final B à "lista de fechamento"
9. Na última etapa, precisamos representar o caminho do ponto de partida A para o ponto final B. O papel do nó pai é exibido. Ao alterar o valor do nó pai do nó do ponto final no "Fechar a lista", você pode exibir o caminho seguindo as pistas.
Confira o código
pacote a_star_search; importar java.util.ArrayList; public class Astar {/*** Use ArrayList Array como "Lista aberta" e "Lista de fechamento"*/ArrayList <Node> Open = new ArrayList <Node> (); ArrayList <Node> Close = New ArrayList <node>; ENDNODE: Ponto final* @return*/public Double GethValue (Nó CurrentNode, Node EndNode) {return (Math.abs (currentNode.getx () - endnode.getx () + Math.abs (CurrentNode.gety () - endnode.gety ())* 10;}/** ** ** ** ** Get Gouty () - endnode.gety ())* 10;}/** ** ** ** ** Get Gouty () - endNode.gety ())* 10;}/** ** ** ** ** ** Get Gouty () - endnode.gety ())* 10;}/** ** ** ** ** ** ** **e () @surtyn)* getGValue (nó currentNode) {if (currentNode.getpnode ()! Retornar currentNode.getgValue ()+10;} retornar currentNode.getGValue ()+14;} retornar currentNode.getgValue ();}/** * Obtenha o valor f: g+h * @param currentNode * @return */public duplo getfvalue (node currentNode) {returnnode.getGue () */public)/node currentNode) {returnnode.getGue ()/)/public. em torno do nó selecionado para a "Lista aberta" * @param nó * @param mapa */public void Inopen (nó do nó, mapa mapa) {int x = node.getx (); int y = node.gety (); para (int i = 0; i <3; i ++) {para (int j = 0; Não é um obstáculo, não na lista fechada), a lista de abertura não está incluída e não é selecionada if (map.getMap () [x-1+i] [y-1+j] .isreachable () &&! Open.contains (map.getMap () [x-1+i] [y-1+j]) & &! (x == (x-1+i) && y == (y-1+j))) {map.getMap () [x-1+i] [y-1+j] .setpnode (map.getMap () [x] [y]); // O nó selecionado é usado como o nó pai. +j] .SetgValue (getGValue (map.getMap () [x-1+i] [y-1+j])); map.getMap () [x-1+i] [y-1+j] .SethValue (gethvalue (map.getMap () [x-1+i] [y-1+j], map.ge tendnode ())); map.getMap () [x-1+i] [y-1+j] .SetfValue (getfValue (map.getMap () [x-1+i] [y-1+j])); open.add (map.getMap () [x-1+i] [y-1+j]);}}}}} * Classifique os nós na lista aberta de pequeno a grande por f valor * @param arr */public void sort (ArrayList <Node> arr) {for (int i = 0; i <arr.size ()-1; i ++) {para (int j = 1; j <arr.size (); j ++) {para (d. arr.get (j) .getfValue ()) {node tmp = new node (); tmp = arr.get (i); ar.set (i, arr.get (j)); ar.set (j, tmp);}}}}}/** * nó para "close list" * @param node * * aberto) {if (open.contains (node)) {node.setReachable (false); // Defina inacessível open.remove (node); close.add (nó);}} Pesquisa pública void (mapa mapa) {// opera os nós em torno do ponto de partida, que é, é, é o inopen (map.getMap () [map.getStartNode (). getx ()] [map.getStartNode (). gety ()], map); close.add (map.getMap () [map.getStart Node (). Getx ()] [map.getStartNode (). Getx ()] [map.getStartNode (). Gety ()]); map.getMap () [map.getStartNode (). GetX ()] [map.g etstartNode (). gety ()]. setreachable (false); map.getMap () [map.getStartNode (). getX ()] [map.getStartNode (). gety ()] Do {Inopen (open.get (0), map); inclose (open.get (0), aberto); classificar (aberto);} while (! Open.contains (map.getMap () [map.getEnDNode (). getX ()] [map.getNode (). inclose (map.getMap () [map.getEndNode (). getx ()] [map.getEndNode (). gety ()], aberto); showpath (feche, map);}/** * marque o caminho * @param arr * @param map */public void ShowPath (Arraylist <Node>, map 0) {@param map * Node (); // <span style = "space branco: pré"> </span> node = map.getMap () [map.getEndNode (). Getx ()] [map.getEnDNode (). Gety ()]; == map.getstartnode (). gety ())) {// <span style = "space branco: pré"> </span> node.getpnode (). SetValue ("*"); style = "espaço em branco: pre"> </span> map.getMap () [map.getStartNode (). getx ()] [map.getStartNode (). gety ()]. setValue ("a");}}Finalmente escreva um método principal
pacote a_star_search; public class Mantest {public static void main (string [] args) {map map = new map (); Astar astar = new Astar (); map.ShowMap (); astar.search (mapa); System.out.println ("=================================================================================================================================================================eroeroeóuseó surroeroeroerororo ,óó, surro, quero ,ero momento, momento,,,,,,,,,,,,,,,,,,,, desó execit quase no Re decó quase sur decórororororororororororoóacrororoóóóóó ,óóóóóóóóóóóóroó fundo o fundo ======================================================= doc ======================================================= doc ====================================================== doc map.showMap ();Modifique o mapa e teste -o para ver o efeito
% % % % % % % % %ornmos % % ooooo % oo # oo % % a # o b % % oo # oo % ooooo % % % % % % % % % % %ar ===================================================================================== % % % % # % % % % % %
Resumir
Para garantir que o caminho mais curto (a solução ideal) seja encontrada, a chave está na seleção da função de estimativa H (n): o valor real da distância do valor de estimativa H (n) <= n no nó de destino. Nesse caso, há muitos pontos pesquisados, o intervalo de pesquisa é grande e a eficiência é baixa. Mas pode obter
Solução ideal. Se o valor estimado> valor real, o número de pesquisa de pontos é pequeno, o intervalo de pesquisa é pequeno e a eficiência é alta, mas não pode garantir que a solução ideal seja obtida.
O maior sentimento é: a coisa mais tabu sobre a pesca por três dias e dois dias secando a rede. A quantidade pode não ser grande, mas deve ser continuidade, e a chave é a persistência.
Espero que todo programador possa digitar o código e fazer o que ele gosta de fazer.
O exposto acima é todo o conteúdo deste artigo sobre programação Java e implementação do código completo de um algoritmo*. Espero que seja útil para todos. Amigos interessados podem continuar se referindo a outros tópicos relacionados neste site. Se houver alguma falha, deixe uma mensagem para apontá -la.