TProcura
Biblioteca em C++ para testes paramétricos de algoritmos, e coleção de algoritmos de procura e otimização
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,5,5,regular}, // 4 em linha 5x5
39 {4,5,6,regular}, // 4 em linha 5x6
40 {4,6,7,gravidade}, // 4 em linha 6x7 gravidade
41 {4,6,14,gravidade}, // 4 em linha 6x14 gravidade
42 {5,8,12,gravidade}, // 5 em linha 8x12 gravidade
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 9x11
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 tabuleiro.Reset('.');
56
57}
58
60{
61 CJogoEmLinha* novo;
62 if (SolucaoCompleta())
63 return;
64
65 for (int j = 0; j < inst.M; j++)
66 for (int i = inst.N - 1; i >= 0; i--)
67 if (Casa(i, j) == '.') {
68 sucessores += (novo = (CJogoEmLinha*)Duplicar());
69 novo->minimizar = !minimizar;
70 novo->Casa(i, j, (minimizar ? 'x' : 'o'));
71 if (inst.variante == gravidade)
72 break; // apenas a primeira posição livre da coluna
73 }
75}
76
77bool CJogoEmLinha::VerLinha(int i, int j, int di, int dj)
78{
79 int nMax = 0, nMin = 0;
80
81 for (int k = 0;
82 i >= 0 && i < inst.N && j >= 0 && j < inst.M; // valores dentro do tabuleiro
83 i += di, j += dj, k++)
84 {
85 // contabilizar nova casa
86 switch (Casa(i, j)) {
87 case 'x': nMin++; break;
88 case 'o': nMax++; break;
89 }
90 if (k >= inst.K - 1) {
91 if (nMax == inst.K || nMin == inst.K) {
92 resultadoCompleto = (nMax == inst.K ? 1 : -1);
93 return true;
94 }
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
126 return true; // não há hipótese de mais jogadas
127}
128
129// Escrever informação de debug sobre o objecto corrente
130// (utilizar variável TProcuraConstrutiva::debug para seleccionar o detalhe pretendido)
131void CJogoEmLinha::Debug(bool completo)
132{
133 // identificação do tipo de jogo
134 NovaLinha();
135 printf("%d em Linha (%dx%d)", inst.K, inst.M, inst.N);
136 if (inst.variante == gravidade)
137 printf(" gravidade");
138 NovaLinha(); // cabeçalho
139 printf(" ");
140 for (int i = 0; i < inst.M; i++)
141 printf(" %c", 'A' + i);
142 for (int i = 0; i < inst.N; i++) {
143 NovaLinha();
144 printf("%2d", i + 1);
145 for (int j = 0; j < inst.M; j++)
146 printf(" %c", Casa(i, j));
147 printf(" %d ", i + 1);
148 }
149 NovaLinha(); // final
150 printf(" ");
151 for (int i = 0; i < inst.M; i++)
152 printf(" %c", 'A' + i);
153}
154
156{
157 TVector<int> base;
159
160 // configuração base
161 Parametro(ALGORITMO) = 2;
162 Parametro(LIMITE) = 0;
166 Parametro(HEUR_BASE) = 300;
168
169
170 for (auto& parm : parametro)
171 base += parm.valor;
172 // colocar as configurações correspondentes aos níveis
173 // - +1: P4=4 P12=2
174 configuracoes += base;
177 // Nível Base : -
178 configuracoes += base;
179 // - -1 : P10 = -5 P15 = 150
180 configuracoes += base;
183 // - -2 : P7 = 2 P10 = -5 P15 = 150
184 configuracoes += base;
188 // - -3 : P7 = 2 P10 = -20 P15 = 120
189 configuracoes += base;
193}
194
196{
197 CJogoEmLinha* suc = (CJogoEmLinha*)sucessor;
198 int diferenca = -1;
199 // verificar que há uma só diferença
200 for (int i = 0; i < inst.N * inst.M; i++)
201 if (tabuleiro[i] != suc->tabuleiro[i]) {
202 if (diferenca == -1)
203 diferenca = i;
204 else // duas diferenças
205 return "Inv";
206 }
207 return TString().printf("%c%d", 'a' + diferenca % inst.M, 1 + diferenca / inst.M);
208}
209
211{
212 instancia = { "", 1,1,10 };
214}
215
217{
219 // codificar números de 2 bits: ".xo"
220 for (int i = 0, index = 0; i < inst.N * inst.M; i++, index += 2)
221 estado.SetBits(Codigo(tabuleiro[i]), index, 2);
222}
223
225{
226 static int index[][2] = { {0,1},{1,0}, {1,1}, {1,-1} };
227 TVector<int> qMin, qMax;
228 int nMax, nMin, suspensas;
229
230 heuristica = 0;
231
232 if (ExisteHeuritica())
233 return heuristica;
234
235 qMin.Count(inst.K - 1); // contabilizar ameaças a 1, 2 e 3 (até K-1)
236 qMax.Count(inst.K - 1);
237 qMin.Reset(0);
238 qMax.Reset(0);
239 // processar todas as sequências de 4
240 for (int linha = 0; linha < inst.N; linha++) {
241 for (int coluna = 0; coluna < inst.M; coluna++) {
242 for (int dir = 0; dir < 4; dir++) { // 4 direções (horizontal, vertical, duas diagonais)
243 if ((index[dir][0] > 0 ? linha <= inst.N - inst.K : 1) &&
244 (index[dir][1] > 0 ? coluna <= inst.M - inst.K :
245 index[dir][1] < 0 ? coluna >= inst.K - 1 : 1))
246 {
247 suspensas = nMax = nMin = 0;
248 for (int i = 0; i < inst.K && (nMax == 0 || nMin == 0); i++)
249 if (Casa(linha + i * index[dir][0], coluna + i * index[dir][1]) == 'x')
250 nMin++;
251 else if (Casa(linha + i * index[dir][0], coluna + i * index[dir][1]) == 'o')
252 nMax++;
253 else if (inst.variante == gravidade) {
254 int l = linha + i * index[dir][0];
255 while (l < inst.N - 1 &&
256 Casa(l + 1, coluna + i * index[dir][1]) == '.') {
257 l++;
258 suspensas++;
259 }
260 }
261
262 // verificar resultado exato
263 if (nMax == inst.K) {
266 }
267 else if (nMin == inst.K) {
270 }
271
272 if (suspensas > 0) {
273 // contar como jogadas necessárias para ativar a ameaça
274 if (nMax > 0)
275 nMax -= suspensas;
276 if (nMin > 0)
277 nMin -= suspensas;
278
279 if (nMin < 0 || nMax < 0)
280 continue; // não contar ameaças muito distantes, a cima de K
281 }
282
283 // verificar se quem joga tem ameaça a 1, para ganhar na sua vez de jogar
284 if (minimizar ? nMin == inst.K - 1 && nMax == 0 : nMax == inst.K - 1 && nMin == 0)
285 heuristica = (minimizar ? -infinito : infinito); // vitória em 1, é igual a posição terminal
286 // não retornar de imediato, já que o jogo pode ter sido já ganho pelo adversário
287
288 // registar resultado
289 if (nMax > 0 && nMin == 0)
290 qMax[inst.K - 1 - nMax]++;
291 else if (nMin > 0 && nMax == 0)
292 qMin[inst.K - 1 - nMin]++;
293 }
294 }
295 }
296 }
297 if (heuristica != 0) {
299 }
300
301 heuristica = MaiorAmeaca(qMin, qMax, inst.K - 1);
302 // retornar a soma das ameaças
304}
@ regular
Definition JogoEmLinha.h:5
@ gravidade
Definition JogoEmLinha.h:6
@ HEUR_BASE
valor base para diferença entre ameaças de K e K-1 (100 não há diferença, 200 é o valor por omissão)
@ ORDENAR_SUCESSORES
opção de ordenar sucessores por heurística, ou por último valor registado
@ LIMITE
Valor dependente do algoritmo. Exemplo: Profundidade limitada.
@ BARALHAR_SUCESSORES
Baralhar os sucessores ao expandir.
@ RUIDO_HEURISTICA
Ruído a adicionar à heurística para testes de robustez.
@ ALGORITMO
Algoritmo base a executar.
Definition TProcura.h:70
@ LIMITE_TEMPO
Tempo limite em segundos.
Definition TProcura.h:73
void Sucessores(TVector< TNo > &sucessores)
Coloca em sucessores a lista de estados sucessores.
void Debug(bool completo=true) override
Mostra o estado no ecrã, para debug.
TString Acao(TNo sucessor)
Retorna a ação (movimento, passo, jogada, lance, etc.) que gerou o sucessor.
void TesteManual(TString nome)
Inicializa a interação com o utilizador.
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 parâmetros, indicadores e instâncias.
CJogoEmLinha(void)
TVector< char > tabuleiro
Definition JogoEmLinha.h:31
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 Codifica(TBits &estado)
Codifica o estado para um vetor de inteiros de 64 bits.
void Inicializar(void)
Coloca o objecto no estado inicial da procura.
~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.
void SetBits(uint64_t value, int bitIndex, int bitCount)
Definition TVector.h:1385
int MaiorAmeaca(TVector< int > &qMin, TVector< int > &qMax, int maxAmeaca) const
Utilitário para calculo de uma heurística standard em jogos simples.
void Sucessores(TVector< TNo > &sucessores)
Coloca em sucessores a lista de estados sucessores.
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
static int resultadoCompleto
resultado após SolucaoCompleta() retornar true (-1 vitória minimizar, 0 empate, 1 vitória maximizar)
Representa um estado no espaço de estados.
void NovaLinha(bool tudo=true)
static bool memoriaEsgotada
Flag indicando problemas de memória esgotada.
Definition TProcura.h:583
int Parametro(int id) const
Definition TProcura.h:607
static TVector< TVector< int > > configuracoes
Conjuntos de configurações para teste empírico.
Definition TProcura.h:573
virtual void TesteManual(TString nome)
Inicializa a interação com o utilizador.
Definition TProcura.cpp:103
static TParametro instancia
ID da instância atual, a ser utilizado em SolucaoVazia().
Definition TProcura.h:22
static TVector< TParametro > parametro
Parâmetros a serem utilizados na configuração atual.
Definition TProcura.h:567
TString & printf(const char *fmt,...)
Definition TVector.h:1150
Item & Last()
Definition TVector.h:227
TVector< Item > & Reset(Item const &i)
Preenche todo o vetor com um mesmo valor.
Definition TVector.h:793
int Count() const
Definition TVector.h:230
void Inicializar(void) override
Coloca o objecto no estado inicial da procura.
virtual void Codifica(TBits &estado)
Codifica o estado para um vetor de inteiros de 64 bits.
int heuristica
Estimativa para o custo até um estado objetivo, se disponível.
EVariantesJogo variante
Definition JogoEmLinha.h:17
int valor
valor do parâmetro
Definition TProcura.h:179