-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmapa_labirinto.cpp
210 lines (172 loc) · 4.92 KB
/
mapa_labirinto.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/*
Implementação do algoritmo de Kruskal
Para detectar ciclos iremos utilizar o algoritmo Union-Find que detecta
ciclos em grafos NÃO direcionados.
*/
#include <iostream>
#include <vector>
#include <algorithm> // sort
#include <random>
#include <queue>
#include <string.h> // memset
#include <mapa_labirinto.h>
using namespace std;
class Aresta
{
int vertice1, vertice2, peso;
public:
Aresta(){
vertice1=vertice2=peso=0;
}
Aresta(int v1, int v2, int peso)
{
vertice1 = v1;
vertice2 = v2;
this->peso = peso;
}
int obterVertice1()
{
return vertice1;
}
int obterVertice2()
{
return vertice2;
}
int obterPeso()
{
return peso;
}
// sobrescrita do operador "<"
bool operator < (const Aresta& aresta2) const
{
return (peso < aresta2.peso);
}
};
class Grafo
{
int V; // número de vértices
vector<Aresta> arestas; // vetor de arestas
public:
Grafo(int V)
{
this->V = V;
}
vector<Aresta> getArestas(){
return arestas;
}
// função que adiciona uma aresta
void adicionarAresta(int v1, int v2, int peso)
{
Aresta aresta(v1, v2, peso);
arestas.push_back(aresta);
}
// função que busca o subconjunto de um elemento "i"
int buscar(int subset[], int i)
{
if(subset[i] == -1)
return i;
return buscar(subset, subset[i]);
}
// função para unir dois subconjuntos em um único subconjunto
void unir(int subset[], int v1, int v2)
{
int v1_set = buscar(subset, v1);
int v2_set = buscar(subset, v2);
subset[v1_set] = v2_set;
}
void copy_arestas(vector<Aresta> &result){
result=arestas;
}
void kruskal(vector<Aresta> &arvore)
{
int size_arestas = arestas.size();
// ordena as arestas pelo menor peso
sort(arestas.begin(), arestas.end());
// aloca memória para criar "V" subconjuntos
int * subset = new int[V];
// inicializa todos os subconjuntos como conjuntos de um único elemento
memset(subset, -1, sizeof(int) * V);
for(int i = 0; i < size_arestas; i++)
{
int v1 = buscar(subset, arestas[i].obterVertice1());
int v2 = buscar(subset, arestas[i].obterVertice2());
if(v1 != v2)
{
// se forem diferentes é porque NÃO forma ciclo, insere no vetor
arvore.push_back(arestas[i]);
unir(subset, v1, v2); // faz a união
}
}
}
};
void criar_uma_arvore(int x,int y, vector<Aresta> &res){
srand((unsigned)time(0));
Grafo g(x*y); // grafo
int n;
for(int i=0;i<y;i++)
for(int j=0;j<x-1;j++){
n=i*x+j;
g.adicionarAresta(n, n+1, rand()%3+1);
}
for(int i=0;i<y-1;i++)
for(int j=0;j<x;j++){
n=i*x+j;
g.adicionarAresta(n, n+x, rand()%3+1);
}
g.kruskal(res);
}
void transformar_arvore_em_labirinto(int **lab,int x, int y, vector<Aresta> &arvore){
int c=x*2-1,l=y*2-1;
for(int i = 0; i < l; i++)
for(int j = 0; j < c; j++)
lab[i][j]=i%2||j%2;
int size_arvore = arvore.size();
for(int i = 0; i < size_arvore; i++){
// TODO transformar a posição int do vertice em seu linha coluna
// 0 00 1 02 2 04 3 06
// 4 20 5 22 6 24 7 26
int nv1 = arvore[i].obterVertice1();//2
int lv1=nv1/x*2;//0
int cv1=nv1%x*2;//4
int nv2 = arvore[i].obterVertice2();//3
int lv2=nv2/x*2;//0
int cv2=nv2%x*2;//6
cout<<"ok "<<i;
if(cv1==cv2) {
cout<<"ok "<<i<<"("<<lv1+1<<","<<cv1<<") |"<<endl;
lab[lv1+1][cv1]=0;
} else if(lv1==lv2){
cout<<"ok "<<i<<" "<<nv1<<" ("<<lv1<<","<<cv1+1<<") - "<<l<<"x"<<c<<endl;
lab[lv1][cv1+1]=0;//5 0
}
}
}
void criar_labrinto(int **lab,int l, int c){
int x=((c%2)?(c+1):c)/2,y=((l%2)?(l+1):l)/2;
vector<Aresta> arvore;
criar_uma_arvore(x, y,arvore); // roda o algoritmo de Kruskal
int size_arvore = arvore.size();
cout<<"size: "<<size_arvore<<endl;
// mostra as arestas selecionadas com seus respectivos pesos
for(int i = 0; i < size_arvore; i++)
{
char v1 = 'A' + arvore[i].obterVertice1();
char v2 = 'A' + arvore[i].obterVertice2();
cout << "(" << v1 << ", " << v2 << ") = " << arvore[i].obterPeso() << endl;
}
transformar_arvore_em_labirinto(lab,x,y,arvore);
}
void printMatriz(int **mat,int l,int c){
for(int i = 0; i < l; i++){
for(int j = 0; j < c; j++)
cout<<mat[i][j]<<' ';
cout<<endl;
}
}
void printLabirinto(int **mat,int l,int c){
for(int i = 0; i < l; i++){
for(int j = 0; j < c; j++)
if(mat[i][j])cout<<"▓"; else cout<<"·";
cout<<endl;
}
}