Dijkstra Algorithm

3

I'm trying to implement a maze, where you need to find a better way to get to the exit (without facing the wall). The labyrinth has already been implemented, the structure is almost ready (it runs through the entire labyrinth).

But I would like it to run only from input to output, and for that I used Dijkstra to perform this course.

Here are the classes and their codes:

Labyrinth Class:

import java.util.Collections;
import java.util.Arrays;

public class Labirinto {
    private final int x;
    private final int y;
    private final int[][] maze;
    private static char[][] drawnMaze;

    private static Grafo grafoLabirinto;



    private final static int TAMANHO = 4; //PARA AUMENTAR O TAMANHO DO LABIRINTO, BASTA MODIFICAR ESTA VARIÁVEL.




    private final static int ENTRADAX = 0;
    private final static int ENTRADAY = 1;
    private final static int SAÍDAX = (TAMANHO*2);
    private final static int SAÍDAY = (TAMANHO*2-1);





    public Labirinto(int x, int y) {
        this.x = x;
        this.y = y;
        maze = new int[this.x][this.y];
        drawnMaze = new char [TAMANHO*2+1][TAMANHO*2+1];
        generateMaze(0, 0);
    }

Class Edge:

public class Aresta {

        private Vértice origem;
        private Vértice destino;

       public Aresta(Vértice origem, Vértice destino) {
            this.origem = origem;
            this.destino = destino;
        }


        public Vértice getOrigem(){
            return this.origem;
        }

        public Vértice getDestino(){
            return this.destino;
        }

    }

Vertice Class:

import java.util.ArrayList;


public class Vértice {

    private String id;
    int x;
    int y;
    private ArrayList <Aresta> adj;


    public Vértice(String id, int x, int y){
        this.id = id;
        this.x = x;
        this.y = y;
        this.adj = new ArrayList <Aresta>();
    }

      public void addAdj(Aresta e) {
            adj.add(e);
            System.out.println(adj.size());
        }

    public String getId(){
        return this.id;
    }

    public int getX(){
        return this.x;
    }

    public int getY(){
        return this.y;
    }


    public ArrayList <Aresta> getArestas(){
        return adj;
    }

}

Dijkstra class:

/*
 * Classe para calular o caminho minimo entre dois vértices
 * Usando o algoritmo de Dijkstra
 */
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Dijkstra {

    // Atributos usados na funcao encontrarMenorCaminho

    Vértice menorCaminho = new Vértice(null, 0, 0);

    // Variavel que recebe os vértices pertencentes ao menor caminho
    Vértice verticeCaminho = new Vértice(null, 0, 0);

    // Variavel que guarda o vértice que esta sendo visitado
    Vértice atual = new Vértice(null, 0, 0);

    // Variavel que marca o vizinho do vértice atualmente visitado
    Vértice vizinho = new Vértice(null, 0, 0);

    // Lista dos vertices que ainda nao foram visitados
    List<Vértice> naoVisitados = new ArrayList<Vértice>();

    // Algoritmo de Dijkstra
    public List<Vértice> encontrarMenorCaminhoDijkstra(Grafo grafo, Vértice v1,
            Vértice v2) {

        // Adiciona a origem na lista do menor caminho
        menorCaminho.getId();

        // Colocando a distâncias iniciais
        for (Grafo ) {

            // Vértice atual tem distância zero, e todos os outros,
            // ("infinita - qualquer valor")
            if (grafo.getVertices().get(i).getDescricao()
                    .equals(v1.getDescricao())) {

                grafo.getVertices().get(i).setDistancia(0);

            } else {

                grafo.getVertices().get(i).setDistancia(9999);

            }
            // Insere o vertice na lista de vertices nao visitados
            this.naoVisitados.add(grafo.getVertices().get(i));
        }

        Collections.sort(naoVisitados);

        // O algoritmo continua ate que todos os vertices sejam visitados
        while (!this.naoVisitados.isEmpty()) {

            // Toma-se sempre o vertice com menor distancia, que eh o primeiro
            // da
            // lista

            atual = this.naoVisitados.get(0);
            System.out.println("Pegou esse vertice:  " + atual);
            /*
             * Para cada vizinho (cada aresta), calcula-se a sua possivel
             * distancia, somando a distancia do vertice atual com a da aresta
             * correspondente. Se essa distancia for menor que a distancia do
             * vizinho, esta eh atualizada.
             */
            for (int i = 0; i < atual.getArestas().size(); i++) {

                vizinho = atual.getArestas().get(i).getDestino();
                System.out.println("Olhando o vizinho de " + atual + ": "
                        + vizinho);
                if (!vizinho.verificarVisita()) {

                    // Comparando a distância do vizinho com a possível
                    // distância
                    if (vizinho.getDistancia() > (atual.getDistancia() + atual
                            .getArestas().get(i).getPeso())) {

                        vizinho.setDistancia(atual.getDistancia()
                                + atual.getArestas().get(i).getPeso());
                        vizinho.setPai(atual);

                        /*
                         * Se o vizinho eh o vertice procurado, e foi feita uma
                         * mudanca na distancia, a lista com o menor caminho
                         * anterior eh apagada, pois existe um caminho menor
                         * vertices pais, ateh o vertice origem.
                         */
                        if (vizinho == v2) {
                            menorCaminho.clear();
                            verticeCaminho = vizinho;
                            menorCaminho.addAdj(vizinho);
                            while (verticeCaminho.getPai() != null) {

                                menorCaminho.add(verticeCaminho.getPai());
                                verticeCaminho = verticeCaminho.getPai();

                            }
                            // Ordena a lista do menor caminho, para que ele
                            // seja exibido da origem ao destino.
                            Collections.sort(menorCaminho);

                        }
                    }
                }

            }
            // Marca o vertice atual como visitado e o retira da lista de nao
            // visitados
            atual.visitar();
            this.naoVisitados.remove(atual);
            /*
             * Ordena a lista, para que o vertice com menor distancia fique na
             * primeira posicao
             */

            Collections.sort(naoVisitados);
            System.out.println("Nao foram visitados ainda:"+naoVisitados);

        }

        return menorCaminho;
    }

}






    public static void main(String[] args) {
        int x = args.length >= 1 ? (Integer.parseInt(args[0])) : TAMANHO;
        int y = args.length == 2 ? (Integer.parseInt(args[1])) : TAMANHO;
        Labirinto maze = new Labirinto(x, y);
        maze.display();
        //maze.displaySkeleton();
        maze.displayStringMaze();

        grafoLabirinto = BFS.gerarGrafo(new Vértice("0", 0, 1), drawnMaze);
        System.out.println(grafoLabirinto.toString());
    }








    public void displaySkeleton(){
        for(int i=0; i < maze.length; i++){
            for(int j=0; j < maze.length; j++){
                System.out.print(maze[i][j]);
            }
            System.out.println("");
        }

    }

    public void displayStringMaze(){
        for(int i=0; i < TAMANHO*2+1; i++){
            for(int j=0; j < TAMANHO*2+1; j++){
                System.out.print(drawnMaze[i][j]);
            }
            System.out.println("");
            }
        }






    public void display() {

        int lineIterator = 0;
        int colIterator = -1;

        for (int i = 0; i < y; i++) {

            // draw the north edge
            for (int j = 0; j < x; j++) {   
                if((maze[j][i] & 1) == 0){
                    drawnMaze[lineIterator][++colIterator] = '█';
                    drawnMaze[lineIterator][++colIterator] = '█';
                }else{
                    drawnMaze[lineIterator][++colIterator] = '█';
                    drawnMaze[lineIterator][++colIterator] = ' ';
                }
            }
            drawnMaze[lineIterator++][++colIterator] = '█';
            colIterator = -1;


            // draw the west edge
            for (int j = 0; j < x; j++) {

                if((maze[j][i] & 8) == 0){
                    drawnMaze[lineIterator][++colIterator] = '█';
                    drawnMaze[lineIterator][++colIterator] = ' ';
                }else{
                    drawnMaze[lineIterator][++colIterator] = ' ';
                    drawnMaze[lineIterator][++colIterator] = ' ';
                }
            }
            drawnMaze[lineIterator++][++colIterator] = '█';
            colIterator = -1;

        }


        // draw the bottom line
        for (int j = 0; j < x; j++) {

            drawnMaze[lineIterator][++colIterator] = '█';
            drawnMaze[lineIterator][++colIterator] = '█';

        }

        drawnMaze[lineIterator][++colIterator] = '█';

        //draw entrance & exit
        drawnMaze[ENTRADAX][ENTRADAY] = 'e';
        drawnMaze[SAÍDAX][SAÍDAY] = 's';

    }


    private void generateMaze(int cx, int cy) {
        DIR[] dirs = DIR.values();
        Collections.shuffle(Arrays.asList(dirs));
        for (DIR dir : dirs) {
            int nx = cx + dir.dx;
            int ny = cy + dir.dy;
            if (between(nx, x) && between(ny, y)
                    && (maze[nx][ny] == 0)) {
                maze[cx][cy] |= dir.bit;
                maze[nx][ny] |= dir.opposite.bit;
                generateMaze(nx, ny);
            }
        }
    }

    private static boolean between(int v, int upper) {
        return (v >= 0) && (v < upper);
    }

    private enum DIR {
        N(1, 0, -1), S(4, 0, 1), E(4, 1, 0), W(8, -1, 0);
        private final int bit;
        private final int dx;
        private final int dy;
        private DIR opposite;

        // use the static initializer to resolve forward references
        static {
            N.opposite = S;
            S.opposite = N;
            E.opposite = W;
            W.opposite = E;
        }

        private DIR(int bit, int dx, int dy) {
            this.bit = bit;
            this.dx = dx;
            this.dy = dy;
        }
    };

/*  
    public static void encontraCaminho(){ 
          int k = 0;
          int pos;
          int aux = 0;
          for(int i = 0; i < TAMANHO ; i ++){
            for(int j = 0; j<TAMANHO-1;j++){
              if(k==0){ //verificando se é a primeira execução
                k++;
                grafoLabirinto[ENTRADAX][ENTRADAY] = 2; // mudar espaço vago para um espaço percorrido
                grafoLabirinto[SAÍDAX][SAÍDAY] = 2;
                j = ENTRADAY;
                i = ENTRADAX;
              }
              if(grafoLabirinto == 0){
                grafoLabirinto[i][j] = 2;
                if(grafoLabirinto[i][j+1]==0){
                    aux++;
                }else if(grafoLabirinto[i+1][j]==0){
                    aux++;
                }else if(grafoLabirinto[i-1][j]==0){
                    aux++;
                }
              }
            }
          }
        }
 */


}

This is a simple example of graph implementation represented by the list of adjacencies:

import java.util.List;
import java.util.ArrayList;

public class Grafo {

    List<Vértice> vértices;
    List<Aresta> arestas;

    public Grafo() {
        vértices = new ArrayList<Vértice>();
        arestas = new ArrayList<Aresta>();
    }

    public Vértice addVertice(Vértice v) {
        v = new Vértice(v.getId(), v.getX(), v.getY());
        vértices.add(v);
        return v;
    }

    public Aresta addAresta(Vértice origem, Vértice destino) {
        Aresta e = new Aresta(origem, destino);
        arestas.add(e);
        return e;
    }

    public String arestasToString(){
        String s = "";
        for(Aresta a: arestas){
            s += "{" + a.getDestino().getId() +" , " +a.getOrigem().getId() + "}";
        }
        return s;
    }

    public String toString() {
        String r = "";

        for (Vértice u : vértices) {
            r+= String.format("%s (%d,%d) -> ", u.getId(), u.getX(), u.getY());
            //r += u.getId() + " " + u.getX() +" -> ";

            for (Aresta e : u.getArestas()) {
                Vértice v = e.getDestino();
                r += v.getId() + ", ";
            }

            r += "\n";

        }

        return r;
    }

    public void ligarArestas(){
        for(Vértice v : vértices){
            for(Aresta a : arestas){
                if(v.getId()==a.getOrigem().getId()){
                    v.getArestas().add(a);
                }
            }
        }
    }



    /*
    public static void main(String[] args) {
        Grafo g = new Grafo();
        Vertice s = g.addVertice("s");
        Vertice t = g.addVertice("t");
        Vertice y = g.addVertice("y");
        Aresta st = g.addAresta(s, t);
        Aresta sy = g.addAresta(s, y);
        Aresta ty = g.addAresta(t, y);
        Aresta yt = g.addAresta(y, t);
        System.out.println(g);
    }

    */
}

My question is: how do I implement the Dijkstra class in this labyrinth context, where do I just need to go from input to output (without going through dead-ends)?

    
asked by anonymous 17.06.2017 / 17:54

0 answers