Last Update: 04/07/2020 12:01:17
As seguintes tarefas deverão ser entregues (através do github) até ao dia 19 de Abril às 20h00:
jogÉ obrigatório criar um módulo de listas ligadas. Ele deve implementar as funções com os seguintes protótipos:
// Cria uma lista vazia
LISTA criar_lista();
// Insere um valor na cabeça da lista
LISTA insere_cabeca(LISTA L, void *valor);
// Devolve a cabeça da lista
void *devolve_cabeca(LISTA L);
// Devolve a cauda da lista
LISTA proximo(LISTA L);
// Remove a cabeça da lista (libertando o espaço ocupado) e devolve a cauda
LISTA remove_cabeca(LISTA L);
// Devolve verdareiro se a lista é vazia
int lista_esta_vazia(LISTA L);
O tipo LISTA deve ser um apontador para uma estrutura. Eis um exemplo da utilização deste módulo:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lista.h"
#define BUF_SIZE 1024
int main() {
LISTA L = criar_lista(); // Criar uma lista vazia
char linha[BUF_SIZE];
printf("Insira várias linhas, acabando com CTRL-D:\n");
// control-D é a tecla CTRL e a tecla D ao mesmo tempo
// Em windows é capaz de ser CTRL-Z
while(fgets(linha, BUF_SIZE, stdin) != 0) {
// A função strdup cria uma cópia da string que foi lida
// Insere uma cópia da linha lida na cabeça da lista
L = insere_cabeca(L, strdup(linha));
}
printf("\n==============================\n");
printf( "= PERCURSO =\n");
printf( "==============================\n\n");
// percorre sem remover os elementos da lista
for(LISTA T = L; !lista_esta_vazia(T); T = proximo(T)) {
// Vai buscar a cabeça da lista
// Passa do tipo genérico void * para char *
char *str = (char *) devolve_cabeca(T);
printf("%s", str);
}
printf("\n==============================\n");
printf( "= REMOCAO =\n");
printf( "==============================\n\n");
// percorre e vai removendo a cabeça
while(!lista_esta_vazia(L)) {
char *str = (char *) devolve_cabeca(L);
L = remove_cabeca(L);
printf("%s", str);
free(str);
}
return 0;
}
O comando jog deve permitir que o jogador atual peça ao computador para jogar por si. Nesta etapa, pretende-se que o comando funcione da seguinte forma:
Esta secção apresenta várias heurísticas possíveis. Para este guião, qualquer das heurísticas apresentadas abaixo será aceite. Para o guião 10, terão que implementar uma das outras estratégias.
Sabemos que no jogo do Rastos um jogador ganha se:
Assim, as estratégias para jogar baseiam-se nestes dois objetivos. Como o primeiro objetivo pode não ser possível de conseguir, é preciso ter sempre em mente o segundo objetivo.
Neste caso, a heurística será escolher simplesmente uma das hipóteses possíveis.
Neste caso pretende-se escolher a casa que fique mais perto do objetivo do jogador atual. Assim:
A heurística anterior não funciona corretamente caso hajam casas ocupadas, visto que a branca não pode ir para cima das casas que estão ocupadas. Neste caso, pretende-se usar o algoritmo Flood Fill para decidir qual é a casa que está mais próxima do destino. É possível que não haja caminho para a casas destino; neste caso, sugere-se que:
Esta estratégia conta as áreas e considera que se no fim de jogar deixarmos uma área com um número par de casas livres, então ganharemos desde que todas essas casas sejam preenchidas sistemáticamente. Assim, esta estratégia conta, para cada jogada possível, o tamanho da área que se deixa para o outro jogador e escolhe aquela que deixa uma área com um tamanho par.
Este algoritmo é utilizado quando queremos prever o que vai acontecer daqui a várias jogadas. Neste caso, o que se pretende é criar uma função (mais uma vez uma heurística) que avalie cada posição. Após isso, o algoritmo irá experimentar todas as jogadas possíveis de cada um dos jogadores, até uma dada profundidade e avaliar a posição final em cada caso e escolher a jogada mais proveitosa para o jogador atual. Assume-se que cada jogador escolhe a jogada mais proveitosa. A razão do algoritmo se chamar Minimax é que enquanto que o jogador atual tenta maximizar a sua posição, o adversário pretende minimizar essa vantagem.
Segue-se um exemplo em que se utilizou a estratégia da escolha aleatória:
8 .......2
7 ........
6 ........
5 ....*...
4 ........
3 ........
2 ........
1 1.......
abcdefgh
# 01 PL1 (1)> e4
8 .......2
7 ........
6 ........
5 ....#...
4 ....*...
3 ........
2 ........
1 1.......
abcdefgh
# 02 PL2 (1)> d5
8 .......2
7 ........
6 ........
5 ...*#...
4 ....#...
3 ........
2 ........
1 1.......
abcdefgh
# 03 PL1 (2)> jog
8 .......2
7 ........
6 ........
5 ...##...
4 ..*.#...
3 ........
2 ........
1 1.......
abcdefgh
# 04 PL2 (2)>