【发布时间】:2014-04-05 19:51:21
【问题描述】:
我正在编写一个程序,可以生成你想要的任何大小的迷宫。它通过首先创建迷宫中的每个单元并假设它们完全被围住来做到这一点。它们每个都被声明为自己的集合。然后随机选择一个单元格,然后随机选择一个方向来打破墙壁。随机方向函数确保它也是该单元格的有效方向。该程序确保它希望加入的两个单元格没有以某种方式连接,如果它们没有连接,它会打破墙壁。如果它们已经直接或间接连接,那么它会选择一个新的随机单元格和方向。这种情况一直持续到剩下的组数仅为 1,以确保您可以从迷宫中的任何点到达任何其他点。该程序有效,但速度非常慢。我不认为它应该像现在这样慢,我不确定为什么。
我可以想象一个场景,所有单元都连接在一起,但只有一个。因此,随机选择一个单元格需要一些时间,这可能会减慢速度,但我想当你处理不到 100,000 个单元格时,它仍然不应该花这么长时间。兰德在吐出数字方面应该很快。
我在下面附上了我的代码。它相当简单,但我很抱歉缺少注释。
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;
class dset {
struct element {
element() { rank=0, parent=-1; }
int rank;
int parent;
vector<int> connections;
};
public:
dset(int nr=0,int nc=0);
int size() {return Nsets; }
int merge (int, int);
int find(int);
// Functions
bool isin(int i, vector<int> test);
int randdir(int i);
int randcell();
int dir(int, int);
void print();
vector<int> possibledir(int cell);
vector<int> walls(int cell, vector<int> possible);
private:
int Nsets;
int nrows, ncols;
vector<element> S;
};
int main(int argc, char* argv[]){
int nrows, ncols, cell, direction;
if (argc != 3){
cout << "Usage: nrows ncols\n";
}
stringstream convert;
convert << argv[1];
convert << " ";
convert << argv[2];
convert >> ncols;
convert >> nrows;
dset maze(nrows,ncols);
srand(time(NULL));
while(maze.size() != 1){
cell = maze.randcell();
// cell = 11;
direction = maze.randdir(cell);
// direction = 0;
// cout << "cell: " << cell << " direction: " << direction << " new cell: " << maze.dir(cell, direction) <<endl << endl;
// cout << maze.size() << endl<<endl;;
maze.merge(cell, maze.dir(cell, direction));
}
maze.print();
}
dset::dset(int nr,int nc) {
nrows = nr;
ncols = nc;
int N = (nrows * ncols);
if (0<N) S.insert(S.end(), N, element());
Nsets = N;
}
void dset::print(){
vector<int> wall;
cout << "MAZE " << nrows << " " << ncols << endl;
for ( int i = 0; i < (nrows*ncols); i++ ){
wall = walls(i,possibledir(i));
for( int j = 0; j < wall.size(); j++){
if (i < wall[j])
cout << i << " " << wall[j] << endl;
}
}
}
int dset::randcell(){
return (rand()%(nrows*ncols));
}
int dset::dir(int cell, int direction){
if(direction == 0)
return (cell - 1);
if(direction == 1)
return (cell - (ncols));
if(direction == 2)
return (cell+1);
if(direction == 3)
return (cell + ncols);
}
int dset::randdir(int i){
srand(time(NULL));
int direction;
vector<int> used;
//cout << "i : " << i << endl;
while (true){
direction = rand() % 4;
while (true){
if(isin(direction,used))
direction = rand()%4;
else
break;
}
// cout << "rand: " << direction << endl;
if(direction ==0){
if( i != 0){
// cout << 0 << " i%(ncols -1) :" << (i%(ncols -1)) << endl;
if(i%(ncols) != 0){
break;
}
}
}
if(direction == 1){
// cout << 1 << " i - ncols :" << (i-ncols) << endl;
if(i-ncols > 0){
break;
}
}
if (direction == 2){
// cout << 2 << " i%(ncols) :" << (i%ncols) << endl;
if ( i == 0 )
break;
if (i%ncols != ncols-1){
break;
}
}
if (direction == 3){
if (i+ncols < ((nrows*ncols))){
// cout << 3 << " i+ncols :" << (i+ncols) << endl;
break;
}
}
used.push_back(direction);
}
return direction;
}
vector<int> dset::possibledir(int cell){
vector<int> possible;
// cout << "cell " << cell << " possible connections:\n";
for (int i = 0; i < 4; i++){
if (i == 0){
if( cell != 0 ){
if(cell%(ncols) !=0){
// cout << dir(cell,i) <<endl;
possible.push_back(dir(cell,i));
}
}
}
if(i==1){
if (cell-ncols > 0){
// cout<<dir(cell,i) <<endl;
possible.push_back(dir(cell,i));
}
}
if(i==2){
if(cell == 0){
// cout<<dir(cell,i) <<endl;
possible.push_back(1);
}else if(cell%ncols != ncols-1){
// cout<<dir(cell,i) <<endl;
possible.push_back(dir(cell,i));
}
}
if(i==3){
if ( cell+ncols < ((nrows*ncols))){
// cout<<dir(cell,i) <<endl;
possible.push_back(dir(cell,i));
}
}
}
// cout << endl;
return possible;
}
vector<int> dset::walls(int cell, vector<int> possible){
vector<int> walls;
// cout << cell << " connection 0: " << S[cell].connections[0] << endl;
for(int i = 0; i < possible.size(); i++){
if (!isin(possible[i], S[cell].connections)){
// cout << "true\n";
walls.push_back(possible[i]);
}
// cout << "false\n";
}
return walls;
}
int dset::merge(int i, int j) {
int cell1 = i;
int cell2 = j;
i = find(i);
j = find(j);
if (i != j) {
element &Si = S[i];
element &Sj = S[j];
// Adjust Adjacency List
// cout << "inconnections\n";
S[cell1].connections.push_back(cell2);
S[cell2].connections.push_back(cell1);
// cout << "notinconnections\n";
// merge (union) by rank
if (Si.rank > Sj.rank) Sj.parent = i;
else if (Si.rank < Sj.rank) Si.parent = j;
else { Sj.parent = i; Si.rank +=1; }
Nsets -=1;
}
return find(i);
}
int dset::find(int i) {
if (S[i].parent == -1){
return i;
}
// recursive path compression
S[i].parent = find(S[i].parent);
return S[i].parent;
}
bool dset::isin(int i, vector<int> test){
bool out = false;
for(int j = 0; j < test.size(); j++){
if(test[j] == i)
out = true;
}
return out;
}
【问题讨论】:
标签: c++ performance random maze