大概一个月前做了一下Thoughtworks的提前批作业--计算机生成迷宫,但是一直没来得及整理下,今天正好想起来就简要写一写,留作纪念。若有大神的话,希望能帮我看一下,如何做才能提升,或者这个思考的问题还有那些不全面的地方,万分感谢!
题目的话,这里在文章末尾会作说明。
对于这个问题,我选择建了一个maze类,用矩阵元素表示其网格属性,包含成员变量mazetext(最终需要输出渲染字符串),宽和高,成员函数有:构造函数,creat(string &command)函数,setmazetext(int **matrix)函数以及 getmazetext()函数。
其中:
(1)构造函数之前是先将maze初始化为2*2的非连通道路网格,即高宽均为2,渲染字符串赋值"[W] [W] [W] [W] [W]\n[W] [R] [W] [R] [W]\n[W] [W] [W] [W] [W]\n[W] [R] [W] [R] [W]\n[W] [W] [W] [W] [W]\n"; 但现在看来这部分有点占内存,可直接设为空。
(2)create(string &command)通过字符串command进行网格矩阵设置,主要过程:字符串分割获取数据,根据大小初始化道路网格,根据command第二行内容连通各数据网格。对于这些过程处理,第一部分字符串分割获取数据我采用了两个vector进行处理,其实可以直接采用一个函数,在函数中判断是否为数字,是否超出实际范围,这样就可以减少一个vector占用的内存;第二部分与第三部分的操作其实也是可以合并的,都是在处理连通问题,没必要分两次,在这里分析的就只是相邻单元格,那么就是横纵坐标有一个相等一个差二,判断连通,则可行则将其中间元素(如x同y异,则为x,(y1+y2)/2)设为1,而我之前做的判断了四种情况,繁琐不够简洁。
(3)setmazetext(int **matrix)则是根据矩阵元素值对渲染字符串mazetext进行加不同字符串。
(4)getmazetext()返回渲染字符串。
具体程序代码如下(Qt5.6.1 MinGW 32bit,C++),欢迎批评指正~~~
#ifndef MAZE_H
#define MAZE_H
#include<string.h>
#include<vector>
#include<sstream>
#include<cmath>
using namespace std;
#define MAX 100000000
//string split function(seperator " ") to get info enter from keyboard
void SplitString(const string &s,vector<string> &v,const string&c)
{
string::size_type pos1,pos2;
pos2=s.find(c);
pos1=0;
while(string::npos!=pos2)
{
v.push_back(s.substr(pos1,pos2-pos1));
pos1=pos2+c.size();
pos2=s.find(c,pos1);
}
if(pos1!=s.length())
v.push_back(s.substr(pos1));
}
bool isnum(string s)
{
stringstream sin(s);
int t;char p;
if(!(sin>>t)) return false;
if(sin>>p) return false;
else
return true;
}
class maze
{
private:
string mazetext;
int width;
int height;
public:
maze();
int create(string &command);
void setmazetext(int **matrix);
string getmazetext();
};
maze::maze()//initialization to be a maze sized 5*5
{
width=0;height=0;
mazetext="";
}
int maze::create(string &command)
{
vector<string> vsize;//size of maze in vector <string>
vector<int> vsizeint;//size of maze in vector <int>
string tmpsize,tmplink;
vector<string> v;
////////get two lines info(strings) from command
SplitString(command,v,"\n");
tmpsize=v[0];tmplink=v[1];
SplitString(tmpsize,vsize," ");
if(int(vsize.size())!=2)
{
cout<<"Incorrect command format."<<endl;
return 0;
}
for(vector<string>::size_type i=0;i!=vsize.size();++i)
{
if(!isnum(vsize[i]))
{
cout<<"Invalid number format."<<endl;return 0;
}
int tmp=atoi(vsize[i].c_str());
if(tmp<0)
{
cout<<"Incorrect command format."<<endl;return 0;
}
vsizeint.push_back(tmp);
}
/////initialize the matrix of maze
width=vsizeint[1];height=vsizeint[0];
int **matrix=new int*[2*height+1];
for(int i=0;i<2*height+1;i++)
{
matrix[i]=new int[2*width+1];
}
for(int i=0;i<2*height+1;i=i+1)
for(int j=0;j<2*width+1;j=j+1)
{
if(i%2==0||j%2==0)
matrix[i][j]=0;
else
matrix[i][j]=1;
}
////// create maze with input info
v.clear();
SplitString(tmplink,v,";");
vector<int> vgrid;
vector<string> vstrtemp;
vector<string> vstrtemp2;
for(vector<string>::size_type i=0;i!=v.size();++i)
{
if(v[i].length()!=7)
{
cout<<"Incorrect command format."<<endl;
return 0;
}
vstrtemp.clear();
SplitString(v[i],vstrtemp," ");
for(vector<string>::size_type k=0;k!=vstrtemp.size();++k)
{
if(vstrtemp[k].length()!=3)
{
cout<<"Incorrect command format."<<endl;
return 0;
}
vstrtemp2.clear();
SplitString(vstrtemp[k],vstrtemp2,",");
for(vector<string>::size_type m=0;m!=vstrtemp2.size();++m)
{
if(!isnum(vstrtemp2[m]))
{
cout<<"Invalid number format."<<endl;return 0;
}
int tmp=atoi(vstrtemp2[m].c_str());
if(tmp<0||(tmp>=height&&m%2==0)||(tmp>=width&&m%2!=0))
{
cout<<"Number out of range."<<endl;return 0;
}
vgrid.push_back(tmp);
}
}
}
for(vector<int>::size_type n=0;n!=vgrid.size();n=n+4)
{
if(!(vgrid.at(n)==vgrid.at(n+2)||vgrid.at(n+1)==vgrid.at(n+3)))
{
cout<<"Maze format error."<<endl;return 0;
}
if(!(abs(vgrid.at(n)-vgrid.at(n+2))<=1||abs(vgrid.at(n+1)-vgrid.at(n+3))<=1))
{
cout<<"Maze format error."<<endl;return 0;
}
if(vgrid.at(n)==vgrid.at(n+2))
{
if(vgrid.at(n+1)<vgrid.at(n+3))
{
matrix[2*vgrid.at(n)+1][2*vgrid.at(n+1)+2]=1;
}
else
{
matrix[2*vgrid.at(n)+1][2*vgrid.at(n+3)+2]=1;
}
}
if(vgrid.at(n+1)==vgrid.at(n+3))
{
if(vgrid.at(n)<vgrid.at(n+2))
{
matrix[2*vgrid.at(n)+2][2*vgrid.at(n+1)+1]=1;
}
else
{
matrix[2*vgrid.at(n+2)+2][2*vgrid.at(n+1)+1]=1;
}
}
}
setmazetext(matrix);
delete [] matrix;
return 1;
}
string maze::getmazetext()
{
return mazetext;
}
void maze::setmazetext(int **matrix)
{
mazetext="";
for(int i=0;i<2*height+1;i++)
{
for(int j=0;j<2*width+1;j++)
{
if(matrix[i][j]==0&&j!=2*width) mazetext+="[W] ";
if(matrix[i][j]==1&&j!=2*width) mazetext+="[R] ";
else
{
if(matrix[i][j]==0&&j==2*width) mazetext+="[W]";
if(matrix[i][j]==1&&j==2*width) mazetext+="[R]";
}
}
mazetext+="\n";
}
}
#endif // MAZE_H
#include <QCoreApplication>
#include<bits/stdc++.h>
#include"maze.h"
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
string command="";//getline twice to get
string tmpsize,tmplink;
getline(cin,tmpsize);
getline(cin,tmplink);
command=tmpsize+"\n"+tmplink;
maze m_maze;
if(m_maze.create(command))
{
string result;
result=m_maze.getmazetext();
cout<<result;
}
system("pause");
return app.exec();
}
校招题目:
用计算机生成迷宫是一个很有趣的任务。我们可以用 道路网格(Road Grid) 来表示迷宫的道路,那么 3 x 3
的 道路网格 ( 图-1 左 )可以对应一个 7 x 7 的 渲染网格(Render Grid) —— 图-1 右 的方式(迷宫的墙是灰
色的,道路是白色的):
如果我们将迷宫 道路网格 两个相邻的 cell 连通,则可以打通道路。如 图-2 所示:
连通 道路网格 有如下的约束条件:
● 每一个 cell 只能够直接与相邻正南、正北、正东、正西的 cell 连通。不能够和其他的 cell 连
通。
● 两个 cell 之间的连通一定是双向的。即 cell(0,0) 和 cell(1,0) 连通等价于 cell(1,0) 和
cell(0,0) 的连通。
要求1:将迷宫渲染为字符串
现在我们希望你书写程序,将给定迷宫的 道路网格 ,渲染为字符串输出。例如,其使用方式如下(伪代码
,仅做演示,实际实现时请应用实际语言的编程风格)
Maze maze = MazeFactory.Create(command);
String mazeText = maze.Render();
其中 command 是一个字符串。它的定义如下:
● 第一行是迷宫 道路网格 的尺寸。例如 3 x 3 的迷宫为 3 3 ,而 5 x 4 的迷宫为 5 4。
● 第二行是迷宫 道路网格 的连通性定义。如果 cell(0,1) 和 cell(0,2) 是连通的,则表示为:
0,1 0,2 ,多个连通以分号 ; 隔开。
例如,如果给定输入:
3 3
0,1 0,2;0,0 1,0;0,1 1,1;0,2 1,2;1,0 1,1;1,1 1,2;1,1 2,1;1,2 2,2;2,0 2,1
则输出字符串为(如果当前 渲染网格 为墙壁,则输出 [W] 如果为道路则输出 [R]):
[W] [W] [W] [W] [W] [W] [W]
[W] [R] [W] [R] [R] [R] [W]
[W] [R] [W] [R] [W] [R] [W]
[W] [R] [R] [R] [R] [R] [W]
[W] [W] [W] [R] [W] [R] [W]
[W] [R] [R] [R] [W] [R] [W]
[W] [W] [W] [W] [W] [W] [W]
要求2:检查输入的有效性
在处理输入的时候需要检查输入的有效性。需要检查的有效性包括如下的几个方面:
● 无效的数字:输入的字符串无法正确的转换为数字。此时,该函数的输出为字符串 ”Invalid
number format . ”
● 数字超出预定范围:数字超出了允许的范围,例如为负数等。此时,该函数的输出为字符串
”Number out of range . ”
● 格式错误:输入命令的格式不符合约定。此时,该函数的输出为字符串 ”Incorrect command
format .