原题描述:
历届试题 打印十字图
时间限制:1.0s 内存限制:256.0MB
锦囊1
使用二维数组。
锦囊2
使用二维数组把图形保存下来,然后再输出。
问题描述
小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示:
![20180309145513502](https://i-blog.csdnimg.cn/blog_migrate/819aff442d940a7f8c52e408af0ed490.png)
对方同时也需要在电脑dos窗口中以字符的形式输出该标志,并能任意控制层数。
输入格式
一个正整数 n (n<30) 表示要求打印图形的层数。
输出格式
对应包围层数的该标志。
样例输入1
1
样例输出1
![20180309154805882](https://i-blog.csdnimg.cn/blog_migrate/e0ec0de4b20d9ffa2a679720f3fa312a.png)
样例输入2
3
样例输出2
![20180309154844865](https://i-blog.csdnimg.cn/blog_migrate/83c58c25e7560a636730a132721ebfbc.png)
提示
请仔细观察样例,尤其要注意句点的数量和输出位置。
解题思路:
1、观察规律:发现中心十字始终处于中心点,没次增加外层包围都会使得用于存储数据的二维数组的两个维度成为相同的奇数值。所以中心点容易确定。
2、具有初始状态,当层数为0时,中心十字任然存在,且有包围层数正整数n,0<n<30;
3、选择一个维度观察发现除去初始状态外,包围层只能是与边界点不同的符号表示,且全局结果仅呈现两种符号
所以尝试使用类似于小游戏中地图绘制的方式生成该图案,从中心点出发将全部图形分为四个区域单独绘制(因为中心有初始状态,可以作为某种规则的初始输入参数)。
4、实现过程中注意内存管理,因为我在第一次编写该代码中因疏忽,出现内存泄露问题,使得内存占用巨大。
代码如下(并没有对高度重用部分进行细化封装,感兴趣的可以自行封装,加深代码理解):
#include <iostream>
using namespace std;
class Point
{
public:
int m_x_i;
int m_y_i;
Point(int x,int y):m_x_i(x),m_y_i(y){}
~Point(){}
void deletePoint(Point* p)
{
if (p!= NULL)
delete p;
p=NULL;
}
int getX(){return this->m_x_i;}
int getY(){return this->m_y_i;}
void setX(int x){m_x_i= x;}
void setY(int y){m_y_i= y;}
//获取周围8个点
Point* getLeftPoint(const Point& pt){Point* rpt= new Point(pt.m_x_i, pt.m_y_i-1); return rpt;} // 获取左边的点
Point* getRightPoint(const Point& pt){Point* rpt= new Point(pt.m_x_i, pt.m_y_i+1); return rpt;} // 获取右边的点
Point* getUppPoint(const Point& pt){Point* rpt= new Point(pt.m_x_i-1, pt.m_y_i); return rpt;} // 获取上边的点
Point* getDownPoint(const Point& pt){Point* rpt= new Point(pt.m_x_i+1, pt.m_y_i); return rpt;} // 获取下边的点
Point* getLeft_UppPoint(const Point& pt){Point* rpt= new Point(pt.m_x_i-1, pt.m_y_i-1); return rpt;} // 获取左上边的点
Point* getRight_UppPoint(const Point& pt){Point* rpt= new Point(pt.m_x_i-1, pt.m_y_i+1); return rpt;} // 获取右上边的点
Point* getLeft_DownPoint(const Point& pt){Point* rpt= new Point(pt.m_x_i+1, pt.m_y_i-1); return rpt;} // 获取左下边的点
Point* getRight_DownPoint(const Point& pt){Point* rpt= new Point(pt.m_x_i+1, pt.m_y_i+1); return rpt;} // 获取右下边的点
};
class PrintGraphics
{
public:
int** m_map_ipp;
int m_level_i;
PrintGraphics(int n); // 自定义构造函数
~PrintGraphics(){ delete []m_map_ipp;} // 析构函数
void mapInit(void); // 地图初始化
void asRuleSet(void); // 依据规则设置地图
void printMap(void); // 打印最终地图
};
PrintGraphics::PrintGraphics(int n):m_level_i(4*n+5) // 自定义构造函数
{
//分配存储空间
m_map_ipp= new int*[4*n+5];
for( int i=0; i<(4*n+5); i++ )
{
m_map_ipp[i] = new int [4*n+5] ;
}
//执行初始化
this->mapInit();
//执行按规则铺地图
this->asRuleSet();
}
void PrintGraphics:: mapInit(void)
{
// 预初始化
for(int i=0;i<m_level_i;++i)
{
for(int j=0;j<m_level_i;++j)
m_map_ipp[i][j]=-1;
}
//初始化四个边角
m_map_ipp[0][0]=m_map_ipp[m_level_i-1][0]=m_map_ipp[0][m_level_i-1]=m_map_ipp[m_level_i-1][m_level_i-1]= '.';
//初始化中心十字架
for(int i=(m_level_i-5)/2;i<(m_level_i/2)+3;++i)
m_map_ipp[i][m_level_i/2]='$';
for(int i=(m_level_i-5)/2;i<(m_level_i/2)+3;++i)
m_map_ipp[m_level_i/2][i]='$';
}
void PrintGraphics:: asRuleSet(void)
{
int markFoot= 0; // 标记行走步长
Point* markStartPoint= new Point(m_level_i/2,m_level_i/2); //初始化设置为十字中心 ,起始点标记
Point* startPoint=new Point(markStartPoint->getX(),markStartPoint->getY()); //设置起始点
Point* PointContainer= NULL; //点容器,用于解决内存泄露问题
//左上区域设置
do{
//如果当前点的左边未被设置
PointContainer= startPoint->getLeftPoint(*startPoint); //将要查询的点放入容器中
if(m_map_ipp[PointContainer->getX()][PointContainer->getY()] == -1)
{
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '$') // 如果当前点为 $ ,设置成 .
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '.';
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '.') // 如果当前点为 . ,设置成 $
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '$';
}
//释放内存
if(PointContainer != NULL)
PointContainer->deletePoint(PointContainer);
//如果当前点的左上边未被设置
PointContainer= startPoint->getLeft_UppPoint(*startPoint); //将要查询的点放入容器中
if(m_map_ipp[PointContainer->getX()][PointContainer->getY()] == -1)
{
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '$') // 如果当前点为 $ ,设置成 .
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '.';
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '.') // 如果当前点为 . ,设置成 $
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '$';
}
//释放内存
if(PointContainer != NULL)
PointContainer->deletePoint(PointContainer);
//如果当前点的上边未被设置
PointContainer= startPoint->getUppPoint(*startPoint); //将要查询的点放入容器中
if(m_map_ipp[PointContainer->getX()][PointContainer->getY()] == -1)
{
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '$') // 如果当前点为 $ ,设置成 .
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '.';
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '.') // 如果当前点为 . ,设置成 $
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '$';
}
//释放内存
if(PointContainer != NULL)
PointContainer->deletePoint(PointContainer);
//进入上一行
if(startPoint->getX() != 1 && startPoint->getY() == 1 && markFoot <= m_level_i/2 -2)
{
markFoot+=1;
startPoint->setX(markStartPoint->getX()-markFoot);
startPoint->setY(markStartPoint->getY());
}
else
//没有到达最左,向左走;
startPoint->setY(startPoint->getY()-1);
}while(startPoint->getX() != 0 &&startPoint->getY()!= 0);
markFoot = 0; //重置
startPoint->setX(markStartPoint->getX());
startPoint->setY(markStartPoint->getY());
//右上区域设置
do{
//如果当前点的上边未被设置
PointContainer= startPoint->getUppPoint(*startPoint); //将要查询的点放入容器中
if(m_map_ipp[PointContainer->getX()][PointContainer->getY()] == -1)
{
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '$') // 如果当前点为 $ ,设置成 .
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '.';
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '.') // 如果当前点为 . ,设置成 $
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '$';
}
//释放内存
if(PointContainer != NULL)
PointContainer->deletePoint(PointContainer);
//如果当前点的右上边未被设置
PointContainer= startPoint->getRight_UppPoint(*startPoint); //将要查询的点放入容器中
if(m_map_ipp[PointContainer->getX()][PointContainer->getY()] == -1)
{
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '$') // 如果当前点为 $ ,设置成 .
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '.';
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '.') // 如果当前点为 . ,设置成 $
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '$';
}
//释放内存
if(PointContainer != NULL)
PointContainer->deletePoint(PointContainer);
//如果当前点的右边未被设置
PointContainer= startPoint->getRightPoint(*startPoint); //将要查询的点放入容器中
if(m_map_ipp[PointContainer->getX()][PointContainer->getY()] == -1)
{
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '$') // 如果当前点为 $ ,设置成 .
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '.';
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '.') // 如果当前点为 . ,设置成 $
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '$';
}
//释放内存
if(PointContainer != NULL)
PointContainer->deletePoint(PointContainer);
//进入上一行
if(startPoint->getX() != 1 && startPoint->getY() == markStartPoint->getX()*2-1 && markFoot <= m_level_i/2 -2)
{
markFoot+=1;
startPoint->setX(markStartPoint->getX()-markFoot);
startPoint->setY(markStartPoint->getY());
}
else
//没有到达最右,向右走;
startPoint->setY(startPoint->getY()+1);
}while(startPoint->getX() != 0 &&startPoint->getY()!= markStartPoint->getX()*2);
markFoot = 0; //重置
startPoint->setX(markStartPoint->getX());
startPoint->setY(markStartPoint->getY());
//右下区域设置
do{
//如果当前点的右边未被设置
PointContainer= startPoint->getRightPoint(*startPoint); //将要查询的点放入容器中
if(m_map_ipp[PointContainer->getX()][PointContainer->getY()] == -1)
{
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '$') // 如果当前点为 $ ,设置成 .
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '.';
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '.') // 如果当前点为 . ,设置成 $
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '$';
}
//释放内存
if(PointContainer != NULL)
PointContainer->deletePoint(PointContainer);
//如果当前点的右下边未被设置
PointContainer= startPoint->getRight_DownPoint(*startPoint); //将要查询的点放入容器中
if(m_map_ipp[PointContainer->getX()][PointContainer->getY()] == -1)
{
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '$') // 如果当前点为 $ ,设置成 .
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '.';
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '.') // 如果当前点为 . ,设置成 $
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '$';
}
//释放内存
if(PointContainer != NULL)
PointContainer->deletePoint(PointContainer);
//如果当前点的下边未被设置
PointContainer= startPoint->getDownPoint(*startPoint); //将要查询的点放入容器中
if(m_map_ipp[PointContainer->getX()][PointContainer->getY()] == -1)
{
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '$') // 如果当前点为 $ ,设置成 .
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '.';
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '.') // 如果当前点为 . ,设置成 $
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '$';
}
//释放内存
if(PointContainer != NULL)
PointContainer->deletePoint(PointContainer);
//进入下一行
if(startPoint->getX() != markStartPoint->getX()*2-1 && startPoint->getY() == markStartPoint->getX()*2-1 && markFoot <= m_level_i/2 -2)
{
markFoot+=1;
startPoint->setX(markStartPoint->getX()+markFoot);
startPoint->setY(markStartPoint->getY());
}
else
//没有到达最右,向右走;
startPoint->setY(startPoint->getY()+1);
}while(startPoint->getX() != 0 &&startPoint->getY()!= markStartPoint->getX()*2);
//左下区域设置
markFoot = 0; //重置
startPoint->setX(markStartPoint->getX());
startPoint->setY(markStartPoint->getY());
do{
//如果当前点的左边未被设置
PointContainer= startPoint->getLeftPoint(*startPoint); //将要查询的点放入容器中
if(m_map_ipp[PointContainer->getX()][PointContainer->getY()] == -1)
{
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '$') // 如果当前点为 $ ,设置成 .
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '.';
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '.') // 如果当前点为 . ,设置成 $
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '$';
}
//释放内存
if(PointContainer != NULL)
PointContainer->deletePoint(PointContainer);
//如果当前点的左下边未被设置
PointContainer= startPoint->getLeft_DownPoint(*startPoint); //将要查询的点放入容器中
if(m_map_ipp[PointContainer->getX()][PointContainer->getY()] == -1)
{
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '$') // 如果当前点为 $ ,设置成 .
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '.';
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '.') // 如果当前点为 . ,设置成 $
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '$';
}
//释放内存
if(PointContainer != NULL)
PointContainer->deletePoint(PointContainer);
//如果当前点的下边未被设置
PointContainer= startPoint->getDownPoint(*startPoint); //将要查询的点放入容器中
if(m_map_ipp[PointContainer->getX()][PointContainer->getY()] == -1)
{
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '$') // 如果当前点为 $ ,设置成 .
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '.';
if(m_map_ipp[startPoint->getX()][startPoint->getY()] == '.') // 如果当前点为 . ,设置成 $
m_map_ipp[PointContainer->getX()][PointContainer->getY()] = '$';
}
//释放内存
if(PointContainer != NULL)
PointContainer->deletePoint(PointContainer);
//进入下一行
if((startPoint->getX() !=markStartPoint->getX()*2) && startPoint->getY() == 1 && markFoot <= m_level_i/2 -2)
{
markFoot+=1;
startPoint->setX(markStartPoint->getX()+markFoot);
startPoint->setY(markStartPoint->getY());
}
else
//没有到达最左,向左走;
startPoint->setY(startPoint->getY()-1);
}while(startPoint->getX() != markStartPoint->getX()*2 && startPoint->getY()!= 0);
startPoint->deletePoint(startPoint);
markStartPoint->deletePoint(markStartPoint);
}
void PrintGraphics::printMap(void)
{
for(int i=0;i<m_level_i;++i)
{
for(int j=0;j<m_level_i;++j)
cout<<(char)m_map_ipp[i][j];
cout<<endl;
}
}
int main(void)
{
int max;
cin>>max;
PrintGraphics pg1(max);
pg1.printMap();
return 0;
}
输出示例:
评测结果: