A *算法需要很长时间才能解决

时间:2016-04-30 19:37:39

标签: java path-finding a-star

我必须使用算法来查找学校项目的路径。我在地图上有一系列12个目标,必须在路径结束之前到达。地图是70x70阵列。我已经做了什么:

我找到所有目标并添加一个列表

目标用数字10到21标记,我列在0到12的列表中。(21是最后一个目标)

private casa[] acharCasas(){
    casa[] casas = new casa[12];
    for (int linha = 0; linha < jogo.getMapa().length; linha++) {
        for (int coluna = 0; coluna < jogo.getMapa()[0].length; coluna++) {
            if(jogo.getMapa()[linha][coluna] >= 10 &&  jogo.getMapa()[linha][coluna] <= 21){
                casas[jogo.getMapa()[linha][coluna]-10] = new casa (linha,coluna);
            }
        }
    }
    return casas;
}

我制定启发式总成本+与未访问的其他房屋的距离

casas_visitadas是已访问目标的数量,posL = rowposC = Col。我想做的是计算你到达下一个未完成目标的距离,+从这个目标到下一个目标的距离......到最终目标。

    public double distanciaDasOutrasCasas(){
        double somaTotal = 0;
        int posL = linha,posC = coluna;
        for (int i = casas_visitadas; i < 12; i++) {
            somaTotal += Math.sqrt( 
                Math.pow( (double) (casas[i].linha - posL),2) + 
                Math.pow( (double) (casas[i].coluna - posC),2)
            );
            posL = casas[i].linha;
            posC = casas[i].coluna;
        }
        return somaTotal;
    }

我检查所有可能的动作

我将它们添加到ArrayList中。以下是构造函数:

  public ArrayList<Direcao> movimentosPossiveis(){
        ArrayList<Direcao> movimentos = new ArrayList<>();
        if (linha > 0) movimentos.add(Direcao.CIMA); // if isnt the first row add UP
        if (coluna > 0) movimentos.add(Direcao.ESQUERDA);//if inst the first col add LEFT
        if (linha < jogo.getMapa().length) movimentos.add(Direcao.BAIXO); // last row add down
        if (coluna < jogo.getMapa()[linha].length) movimentos.add(Direcao.DIREITA); // add right
        return movimentos;
    }

    public ArrayList<cell> permutaCelula(){
        ArrayList<Direcao> movimentos = movimentosPossiveis();
        ArrayList<cell> novasCelulas = new ArrayList<>();
        for (Iterator<Direcao> iterator = movimentos.iterator(); iterator.hasNext();) {
            Direcao D = iterator.next();
            switch (D){
                case CIMA:
                    novasCelulas.add(
                            new cell(this /*father*/, Direcao.CIMA /*direction from father */, custo_total /*total cost*/, linha-1/*row-1*/, coluna/*col*/, casas_visitadas/*goals visiteds*/)
                    );
                    break;
                case BAIXO:

                    novasCelulas.add(
                            new cell(this, Direcao.CIMA, custo_total, linha+1, coluna, casas_visitadas)
                    );
                    break;
                case ESQUERDA:
                    novasCelulas.add(
                            new cell(this, Direcao.CIMA, custo_total, linha, coluna-1, casas_visitadas)
                    );
                    break;
                case DIREITA:
                    novasCelulas.add(
                            new cell(this, Direcao.CIMA, custo_total, linha, coluna+1, casas_visitadas)
                    );
                    break;
            }
        }
        return novasCelulas;
    }

    public double convertePesoDoChao(){
        System.out.println(" L " + this.linha + " Coluna "+ coluna);
        int chao = jogo.getMapa()[this.linha][this.coluna];

        switch (chao) {
            case 0:
                return 200; //rock field, slowest field
    case 1:
        return 1;
    case 2:
        return 3.5;
    case 3:
        return 5;
            case 22:
                    if(quantidadeDeCavaleirosVivos() != 0) return Double.MAX_VALUE; // cant go to master without find all goals
                    finalizado = true; // found
                    caminhoFinal = converteCelulaParaMovimentos(); // converts cells movements 
                    return 0;
            default:
                casas_visitadas++;
                return 0;
        }
    }
public cell(cell pai, Direcao oPaiMexeuPraQualDirecao, double custo_total, int linha, int coluna, int casas_visitadas) {
        this.pai = pai; // father
        this.oPaiMexeuPraQualDirecao = oPaiMexeuPraQualDirecao; // direction from father
        this.linha = linha; //row
        this.coluna = coluna; // col
        this.casas_visitadas = casas_visitadas; //goals visited
        this.custo_total = custo_total + convertePesoDoChao(); // fathers total cost + field cost
    }
    public cell(int linha, int coluna) { //starter cell
        this.linha = linha;
        this.coluna = coluna;
        this.custo_total = 0;
        this.pai = null;
    }

启发式

我的启发式是总费用+距离目标

public double heuristica(){
    return custo_total *10 + distanciaDasOutrasCasas();
}

主循环

if(!finalizado){
        this.jogo = jogo;
        colunaInicial = jogo.getColuna();
        linhaInicial = jogo.getLinha();
        casas = acharCasas();
        ArrayList<cell> franja = new ArrayList<>();
        franja.add(new cell(linhaInicial,colunaInicial));
        while(!finalizado){
            Collections.sort(franja);
            franja.addAll(franja.get(0).permutaCelula());
            franja.remove(0);
        }
    }

问题

总共花了三个多小时,花了太长时间才找到方法......任何提示?我检查了Netbeans分析器,问题是对数组进行排序。

我的完整代码is here

obs:在完整的代码上,游戏调用动作移动,在第一次调用时我需要找到最好的方法,并保存它,稍后我只是弹出一堆动作

obs2:对不起我的英文不好,我在某些部分使用谷歌翻译

0 个答案:

没有答案