TProcuraAdversa
Algoritmos de procura adversa
Loading...
Searching...
No Matches
JogoEmLinha.cpp
Go to the documentation of this file.
1#include "JogoEmLinha.h"
2#include <stdio.h>
3
4// dados da instância
5TJogoEmLinha CJogoEmLinha::inst = { 3,3,3,regular }; // Jogo do Galo
6
10
14
15// Cria um objecto que é uma cópia deste
17{
18 CJogoEmLinha* clone = new CJogoEmLinha;
19 if (clone != NULL)
20 clone->Copiar(this);
21 else
22 memoriaEsgotada = true;
23 return clone;
24}
25
26// Fica com uma cópia de objecto
28{
29 tabuleiro = ((CJogoEmLinha*)objecto)->tabuleiro;
30 minimizar = ((CJogoEmLinha*)objecto)->minimizar;
31}
32
33// Coloca o objecto no estado inicial da procura
35{
36 TJogoEmLinha instancias[] = {
37 {3,3,3,regular}, // Jogo do Galo
38 {4,4,4,regular}, // 4 em linha 4x4
39 {4,4,6,regular}, // 4 em linha 4x6
40 {4,6,7,gravidade}, // 4 em linha 6x7 gravidade
41 {4,6,14,gravidade}, // 4 em linha 6x14 gravidade
42 {5,8,8,regular}, // 5 em linha 8x8
43 {5,8,12,regular}, // 5 em linha 8x12
44 {5,9,9,regular}, // 5 em linha 9x9
45 {6,9,11,regular}, // 6 em linha 10x10
46 {6,12,12,regular}, // 6 em linha 12x12
47 };
48
50 infinito = 10000;
51 minimizar = true;
52 inst = instancias[instancia.valor - 1];
53
55 for (int i = 0; i < inst.N * inst.M; i++)
56 tabuleiro[i] = '.';
57
58 tamanhoCodificado = (inst.N * inst.M * 2) / 64 + 1;
59}
60
62{
63 CJogoEmLinha* novo;
64 if (SolucaoCompleta())
65 return;
66
67 for (int j = 0; j < inst.M; j++)
68 for (int i = inst.N - 1; i >= 0; i--)
69 if (Casa(i,j) == '.') {
70 sucessores.Add(novo = (CJogoEmLinha*)Duplicar());
71 novo->minimizar = !minimizar;
72 novo->Casa(i, j, (minimizar ? 'x' : 'o'));
73 if (inst.variante == gravidade)
74 break; // apenas a primeira posição livre da coluna
75 }
77}
78
79bool CJogoEmLinha::VerLinha(int i, int j, int di, int dj)
80{
81 int nMax = 0, nMin = 0;
82
83 for (int k = 0;
84 i >= 0 && i < inst.N && j >= 0 && j < inst.M; // valores dentro do tabuleiro
85 i += di, j += dj, k++)
86 {
87 // contabilizar nova casa
88 switch (Casa(i, j)) {
89 case 'x': nMin++; break;
90 case 'o': nMax++; break;
91 }
92 if (k >= inst.K - 1) {
93 if (nMax == inst.K || nMin == inst.K)
94 return true;
95 switch (Casa(i-di*(inst.K-1), j - dj * (inst.K - 1))) {
96 case 'x': nMin--; break;
97 case 'o': nMax--; break;
98 }
99 }
100 }
101 return false;
102}
103
104// Retorna verdade caso o estado actual seja um estado objectivo
106{
107 // Processar linhas e diagonais
108 for (int linha = 0; linha < inst.N; linha++)
109 if (VerLinha(linha, 0, 0, 1) ||
110 VerLinha(linha, 0, 1, 1) ||
111 VerLinha(linha, inst.M - 1, 1, -1))
112 return true;
113
114 // Processar colunas e diagonais
115 for (int coluna = 0; coluna < inst.M; coluna++)
116 if (VerLinha(0, coluna, 1, 0) ||
117 VerLinha(0, coluna, 1, 1) ||
118 VerLinha(0, coluna, 1, -1))
119 return true;
120
121 // verificar se há espaço para mais jogadas
122 for (int i = 0; i < inst.N * inst.M; i++)
123 if (tabuleiro[i] == '.')
124 return false; // podem ser feitas mais jogadas
125 return true; // não há hipótese de mais jogadas
126}
127
128// Escrever informação de debug sobre o objecto currente
129// (utilizar variável TProcuraConstrutiva::debug para seleccionar o detalhe pretendido)
131{
132 // identificação do tipo de jogo
133 NovaLinha();
134 printf("%d em Linha (%dx%d)", inst.K, inst.M, inst.N);
135 if (inst.variante == gravidade)
136 printf(" gravidade");
137 NovaLinha(); // cabeçalho
138 printf(" ");
139 for (int i = 0; i < inst.M; i++)
140 printf(" %c", 'A' + i);
141 for (int i = 0; i < inst.N; i++) {
142 NovaLinha();
143 printf("%2d", i + 1);
144 for (int j = 0; j < inst.M; j++)
145 printf(" %c", Casa(i, j));
146 printf(" %d ", i + 1);
147 }
148 NovaLinha(); // final
149 printf(" ");
150 for (int i = 0; i < inst.M; i++)
151 printf(" %c", 'A' + i);
152}
153
158
159const char* CJogoEmLinha::Acao(TNo sucessor)
160{
161 static char str[20];
162 CJogoEmLinha* suc = (CJogoEmLinha*)sucessor;
163 int diferenca = -1;
164 // verificar que há uma só diferença
165 for (int i = 0; i < inst.N * inst.M; i++)
166 if (tabuleiro[i] != suc->tabuleiro[i]) {
167 if (diferenca == -1)
168 diferenca = i;
169 else // duas diferenças
170 return "Inv";
171 }
172 sprintf(str, "%c%d", 'a' + diferenca % inst.M, 1 + diferenca / inst.M);
173 return str;
174}
175
176void CJogoEmLinha::TesteManual(const char* nome)
177{
178 instancia = { NULL, 1,1,10, NULL, NULL };
180}
181
183{
185 // codificar números de 2 bits: ".xo"
186 for (int i = 0, index = 0; i < inst.N * inst.M; i++, index += 2)
187 estado[index >> 6] |= ((uint64_t)Codigo(tabuleiro[i])) << (index & 63);
188}
189
191{
192 static int index[][2] = { {0,1},{1,0}, {1,1}, {1,-1} };
193 TVector<int> qMin, qMax;
194 int nMax, nMin;
195
196 heuristica = 0;
197
198 if (ExisteHeuritica())
199 return heuristica;
200
201 qMin.Count(inst.K - 1); // contabilizar ameaças a 1, 2 e 3 (até K-1)
202 qMax.Count(inst.K - 1);
203 qMin.Reset(0);
204 qMax.Reset(0);
205 // processar todas as sequências de 4
206 for (int linha = 0; linha < inst.N; linha++) {
207 for (int coluna = 0; coluna < inst.M; coluna++) {
208 for (int dir = 0; dir < 4; dir++) { // 4 direções (horizontal, vertical, duas diagonais)
209 if ((index[dir][0] > 0 ? linha <= inst.N - inst.K : 1) &&
210 (index[dir][1] > 0 ? coluna <= inst.M - inst.K :
211 index[dir][1] < 0 ? coluna >= inst.K - 1 : 1))
212 {
213 nMax = nMin = 0;
214 for (int i = 0; i < inst.K && (nMax == 0 || nMin == 0); i++)
215 if (Casa(linha + i * index[dir][0], coluna + i * index[dir][1]) == 'x')
216 nMin++;
217 else if (Casa(linha + i * index[dir][0], coluna + i * index[dir][1]) == 'o')
218 nMax++;
219 // verificar resultado exato
220 if (nMax == inst.K) {
223 }
224 else if (nMin == inst.K) {
227 }
228 // verificar se quem joga tem ameaça a 1, para ganhar na sua vez de jogar
229 if (minimizar ? nMin == inst.K - 1 && nMax == 0 : nMax == inst.K - 1 && nMin == 0)
230 heuristica = (minimizar ? -infinito : infinito); // vitória em 1, é igual a posição terminal
231 // não reteornar de imediato, já que o jogo pode ter sido já ganho pelo adversário
232
233 // registar resultado
234 if (nMax > 0 && nMin == 0)
235 qMax[inst.K - 1 - nMax]++;
236 else if (nMin > 0 && nMax == 0)
237 qMin[inst.K - 1 - nMin]++;
238 }
239 }
240 }
241 }
242 if (heuristica != 0)
244
245 heuristica = MaiorAmeaca(qMin, qMax, inst.K - 1);
246 // retornar a soma das ameaças
248}
@ regular
Definition JogoEmLinha.h:5
@ gravidade
Definition JogoEmLinha.h:6
#define OBJETO_HASHTABLE
void Sucessores(TVector< TNo > &sucessores)
Coloca em sucessores a lista de estados sucessores.
void Debug(void)
Mostra o estado no ecrã, para debug.
const char * Acao(TNo sucessor)
Retorna a ação (movimento, passo, jogada, lance, etc.) que gerou o sucessor.
char Casa(int i, int j)
Definition JogoEmLinha.h:69
bool SolucaoCompleta(void)
Verifica se o estado actual é objectivo (é uma solução completa)
void ResetParametros()
Inicializa os parametros.
CJogoEmLinha(void)
TVector< char > tabuleiro
Definition JogoEmLinha.h:31
void Codifica(uint64_t estado[OBJETO_HASHTABLE])
Codifica o estado para um vetor de inteiros de 64 bits.
int Codigo(char peca)
Definition JogoEmLinha.h:67
static TJogoEmLinha inst
Definition JogoEmLinha.h:5
void Copiar(TProcuraConstrutiva *objecto)
bool VerLinha(int i, int j, int di, int dj)
void SolucaoVazia(void)
Coloca o objecto no estado inicial da procura.
void TesteManual(const char *nome)
Inicializa a interação com o utilizador.
~CJogoEmLinha(void)
TProcuraConstrutiva * Duplicar(void)
Cria um objecto que é uma cópia deste.
int Heuristica(void)
Função para calcular quanto falta para o final, o valor da heurística.
int MaiorAmeaca(TVector< int > &qMin, TVector< int > &qMax, int maxAmeaca)
Utilitário para calculo de uma heurística standard em jogos simples.
bool minimizar
o jogador actual deve minimizar o custo (ou maximizar caso tenha o valor falso)
int Heuristica(void)
chamar após calcular a heurística (grava o valor, dependendo da parametrização)
bool ExisteHeuritica(void)
void ResetParametros()
Método para inicializar os parâmetros (redefinir se forem adicionados parâmetros específicos)
static int infinito
valor de infinito (vitoria/derrota), omissao 1000
Representa um estado no espaço de estados.
void NovaLinha(bool tudo=true)
void Add(Item a)
Definition TVector.h:54
int Count()
Definition TVector.h:70
void Reset(Item const &i)
Definition TVector.h:309
virtual void Sucessores(TVector< TNo > &sucessores)
Coloca em sucessores a lista de estados sucessores.
virtual void SolucaoVazia(void)
Coloca o objecto no estado inicial da procura.
virtual void TesteManual(const char *nome)
Inicializa a interação com o utilizador.
virtual void Codifica(uint64_t estado[OBJETO_HASHTABLE])
Codifica o estado para um vetor de inteiros de 64 bits.
int heuristica
Estimativa para o custo até um estado objetivo, se disponível.
static bool memoriaEsgotada
Flag indicando problemas de memória esgotada.
static int tamanhoCodificado
Número de inteiros de 64 bits utilizados para codificar um objeto (≤ OBJETO_HASHTABLE).
static TParametro instancia
ID da instância atual, a ser utilizado em SolucaoVazia().
EVariantesJogo variante
Definition JogoEmLinha.h:17
int valor
valor do parametro