Buscar

Problema do Passeio do Cavalo



Continue navegando


Prévia do material em texto

Problema do Passeio do Cavalo: A partir de uma posição inicial é possível 
visitar todas as posições do tabuleiro com o cavalo (peça), de modo a passar 
por cada casa uma única vez?
Algumas posições centrais 
permitem escolher oito 
possíveis movimentos
Estratégia: Vamos 
ordenar os possíveis 
movimentos no sentido 
antí-horário.
1
2
3
45
6
7
8
Um possível passeio, .... Upa, upa cavalinho
1
2
3
45
6
7
8
E assim, sucessivamente, ..., 
Problema do Passeio do Cavalo
Algumas posições próximas 
das bordas do tabuleiro não 
permitem escolher a 
totalidade dos oito 
movimentos
Problema? 
Estou 
representando o 
tabuleiro por um 
array 2D.
Problema do Passeio do Cavalo
Problema 01: O tabuleiro 
está sendo representado por 
uma matriz (array 2d). Como 
detectar se o cavalo está fora do 
tabuleiro?
Problema 02: Como detectar 
se uma dada casa já foi visitada? 
Lembre-se que eu quero visitar 
cada casa (posição), uma única 
vez. 
A solução para o 
Problema 01 seria 
criar linhas e colunas 
adjacentes ao 
tabuleiro original, 
mas não permitir que 
estas posições sejam 
visitadas (a rigor elas 
não existem), ou 
seja, representá-las, 
mas não permitir que 
o movimento seja 
realizado para elas.
Já que estamos 
representando o 
tabuleiro por um 
array 2D, a solução 
para o Problema 
02 seria associar o 
valor 0 (zero) para 
indicar as casas 
não visitadas e o 
valor 1 (um) para 
as casas já
visitadas. Com 
essa abordagem é
possível saber se a 
partir de uma casa, 
podemos ou não 
realizar um dado 
movimento. 
0 1 2 3 4 5 6 7 8 9 10 11
0
1 
2 
3 
4 
5
6
7
8
9
10
11
Inicialização
do tabuleiro. 
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
Código Associado a Inicialização do Tabuleiro. 
#define MAX1 12
#define MAX2 10
...
int Tabuleiro[MAX1][MAX1];
...
void Inicializa_Tabuleiro(void){
int i,j;
// visitando todas as casas
for(i=0; i < MAX1; i++)
for(j=0; j < MAX1; j++) Tabuleiro[i][j] = 1;
// atualizando corretamente as casas verdadeiras do tabuleiro real
for(i=2; i < MAX2; i++)
for(j=2; j < MAX2; j++) Tabuleiro[i][j] = 0;
return;
}
Código Associado a Impressão do Tabuleiro. 
void Imprime_Tabuleiro(void) {
int i = 0, j;
for (; i < MAX1; i++) {
for (j=0; j < MAX1; j++) printf("%4d", Tabuleiro[i][j]);
printf("\n");
} // for mais interno
return;
}
Vamos associar ao conteúdo da matriz Tabuleiro na posição (i,j) (Tabuleiro[i][j]), 
o número inteiro que corresponde a ordem em que a “casa” foi visitada. 
Código Associado a Leitura da Posição Inicial de onde o cavalo irá iniciar o passeio. 
Observe que o usuário não possui as informações de como o tabuleiro está
representado. Para todos os efeitos, ele conhece um tabuleiro 8x8 (normal).
void Leitura_Posicao_Inicial(int *Posi, int *Posj) {
printf(" Introduza a linha da POSICAO INICIAL>> ");
scanf("%d",Posi); // 1 <= Posi <= 8
printf("\n\n");
printf(" Introduza a coluna da POSICAO INICIAL>> ");
scanf("%d",Posj); // 1 <= Posj <= 8
// atualizando as posições para o tabuleiro real (12x12)
(*Posi)++; // atualizando a posição da linha
(*Posj)++; // atualizando a posição da coluna
return;
} // Leitura_Posicao_Inicial
Questão Fundamental: Como descobrir o próximo movimento a partir de uma 
posição (i,j) arbitrária ?
Movimento 1 : (i-2,j+1)
Movimento 2 : (i-1,j+2)
Movimento 3 : (i+1,j+2)
Movimento 4 : (i+2,j+1)
Movimento 5 : (i+2,j-1)
Movimento 6 : (i+1,j-2)
Movimento 7 : (i-1,j-2)
Movimento 8 : (i-2,j-1)
i
j
i
j
Código Associado a descoberta do Próximo Movimento para onde o cavalo irá a partir 
de onde ele está, ou seja, continuar o seu passeio. 
int Proximo_Movimento(int Posx, int Posy) {
int pos=0; // indica que não é possível continuar
if (Tabuleiro[Posx-2][Posy+1] == 0) pos=1;
else if (Tabuleiro[Posx-1][Posy+2] == 0) pos=2;
else if (Tabuleiro[Posx+1][Posy+2] == 0) pos=3;
else if (Tabuleiro[Posx+2][Posy+1] == 0) pos=4;
else if (Tabuleiro[Posx+2][Posy-1] == 0) pos=5;
else if (Tabuleiro[Posx+1][Posy-2] == 0) pos=6;
else if (Tabuleiro[Posx-1][Posy-2] == 0) pos=7;
else if (Tabuleiro[Posx-2][Posy-1] == 0) pos=8;
return(pos);
} // Proximo_Movimento
Código associado a atualização da posição para onde o cavalo irá a partir de onde ele 
está, ou seja, esta posição recebe um valor diferente de zero. 
void Atualiza_Nova_Posicao(int Visita, int Mov, 
int *Posx, int *Posy) {
switch( Mov ) {
case 1: *Posx-=2; *Posy+=1; break;
case 2: *Posx-=1; *Posy+=2; break;
case 3: *Posx+=1; *Posy+=2; break;
case 4: *Posx+=2; *Posy+=1; break;
case 5: *Posx+=2; *Posy-=1; break;
case 6: *Posx+=1; *Posy-=2; break;
case 7: *Posx-=1; *Posy-=2; break;
case 8: *Posx-=2; *Posy-=1;
}
Tabuleiro[*Posx][*Posy] = Visita;
return;
}
Código associado a função main(). 
int main(void) {
int pi, pj, continua_loop = 1, ordem_visita = 1;
int prox_mov = 0;
Inicializa_Tabuleiro();
Leitura_Posicao_Inicial(&pi, &pj);
Tabuleiro[pi][pj] = 1;
do {
prox_mov = Proximo_Movimento(pi,pj);
if ( prox_mov ) {
ordem_visita++;
Atualiza_Nova_Posicao(ordem_visita, prox_mov, &pi, &pj);
}
else continua_loop = 0;
} while (continua_loop);
printf("\n\n\n");
Imprime_Tabuleiro();
printf("\n\n\nNumero de casas visitadas >>> %d \n\n", ordem_visita);
system("Pause");
return(0);
} // main
Pergunta 1: A partir de qual posição inicial, eu consigo maximizar o 
número de movimentos do cavalo?
Pergunta 2: Há mais de uma posição que maximiza o número 
movimentos do cavalo?
Pergunta 3: Qual a posição inicial em que o número de 
movimentos do cavalo é mínimo?
Pergunta 4: Existe uma posição inicial que permite passear por 
todas as casas do tabuleiro, segundo a estratégia adotada?
Observação: Observem que nossa estratégia é muito simples, 
podemos implementar estratégias mais elaboradas com o uso de 
pilhas (backtracking) que conseguem realizar um percurso por 
todas as casas do tabuleiro uma única vez.