Exemplo n.º 1
0
        // Acha todos os caminhos usando o algoritmo de backtracking de cada labirinto especificado...
        public void AcharCaminhos(ref DataGridView dgvLab, ref List <Posicao[]> caminhos, ref int[] qtdPosicoesEmCadaCaminho) //encontra os caminhos
        {
            Posicao posAtual = new Posicao(1, 1);                                                                             //nova posição no início do labirinto

            Posicao[] vetorPos = new Posicao[labirinto.Matriz.Length];
            qtdPosicoesEmCadaCaminho = new int[labirinto.Matriz.Length * 10]; //Garante que não há estouro
            caminhos = new List <Posicao[]>();
            Posicao proxPosicao = null;

            bool temCaminho;
            bool achouSaida = false;
            int  qtdPosicoes = 0, qtdCaminhos = 0;

            Pintar(ref dgvLab, posAtual.Linha, posAtual.Coluna);

            while (true)
            {
                while (true) //loop eterno
                {
                    proxPosicao = (Posicao)posAtual.Clone();


                    temCaminho = TemCaminho(ref posAtual, ref proxPosicao); //verifica se tem caminho

                    // Sinaliza no labirinto da classe Labirinto e no labirinto visual (dgvLab) para qual lugar prosseguiu
                    // o cursor depois de usar a Rosa dos Ventos (método TemCaminho()).
                    if (temCaminho)
                    {
                        proxPosicao.OndeParou = -1;
                        pilha.Empilhar(posAtual);
                        posAtual = (Posicao)proxPosicao.Clone();

                        // Verifica-se se o lugar para onde o cursor foi é a saída ou não.
                        if ((char)dgvLab[posAtual.Coluna, posAtual.Linha].Value != SAIDA)
                        {
                            dgvLab[posAtual.Coluna, posAtual.Linha].Value          = JA_PASSOU;
                            this.labirinto.Matriz[posAtual.Linha, posAtual.Coluna] = JA_PASSOU;
                            Pintar(ref dgvLab, posAtual.Linha, posAtual.Coluna);
                        }
                        else
                        {
                            Pintar(ref dgvLab, posAtual.Linha, posAtual.Coluna);
                            if (listaCaminhos.Count == 0)
                            {
                                System.Threading.Thread.Sleep(500);
                            }

                            achouSaida = true;
                            break;
                        }
                    }
                    // Volta a posição anterior - pois não há mais lugares para ir da posição atual, a não ser voltar!
                    else
                    {
                        if (pilha.EstaVazia)
                        {
                            Pintar(ref dgvLab, 1, 1);
                            break; //Não há caminhos
                        }

                        proxPosicao = (Posicao)pilha.OTopo().Clone();

                        dgvLab[posAtual.Coluna, posAtual.Linha].Value          = VAZIO;
                        this.labirinto.Matriz[posAtual.Linha, posAtual.Coluna] = VAZIO;
                        Pintar(ref dgvLab, proxPosicao.Linha, proxPosicao.Coluna);

                        posAtual = (Posicao)pilha.Desempilhar().Clone();
                    }
                }

                // Quando a saída, no labirinto: "S", é achada pelo algoritmo e o caminho feito para chegar até a saída
                // é adicionado a ArrayList de strings "listaCaminhos", que será usada posteriormente no método "MostrarCaminhos".
                if (achouSaida)
                {
                    string ret = "";
                    int    linhaAtual, colunaAtual;
                    PilhaLista <Posicao> pilhaClonada = pilha.Copia();
                    while (!pilhaClonada.EstaVazia)
                    {
                        linhaAtual  = pilhaClonada.OTopo().Linha;
                        colunaAtual = pilhaClonada.OTopo().Coluna;

                        Posicao posicaoAtual = new Posicao(linhaAtual, colunaAtual);
                        vetorPos[qtdPosicoes] = posicaoAtual;

                        ret += $"Linha: {linhaAtual}, Coluna: {colunaAtual}|";
                        pilhaClonada.Desempilhar();
                        qtdPosicoes++;
                    }
                    qtdPosicoesEmCadaCaminho[qtdCaminhos] = qtdPosicoes;
                    caminhos.Add(vetorPos);

                    listaCaminhos.Add(ret);

                    // Reseta-se todas as variáveis usadas para encontrarmos um caminho diferente do já encontrado!
                    qtdPosicoes = 0;
                    vetorPos    = new Posicao[labirinto.Matriz.Length];
                    achouSaida  = false;
                }
                else
                {
                    if (listaCaminhos.Count > 0)
                    {
                        break; //Encontrou todos os caminhos
                    }
                    else
                    {
                        listaCaminhos.Add("Não há caminhos");
                    }
                }

                if (pilha.EstaVazia)
                {
                    break;
                }

                posAtual = (Posicao)pilha.Desempilhar().Clone();
                qtdCaminhos++;
            }
        }