// 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++; } }