搞了这么个无聊东西,可以用来做杯垫。我想我肯定是绣十字绣的人们中C++最好的,哈哈。
另外感慨一下,上学项目用Java,找工作学习JS,最后入职做C++。语言只是个工具啊!始终没搞明白Visual Stdio上面怎么画图,于是用字符串打出来了。
#include <iostream>
#include <set>
#include <list>
#include <ctime>
#include <cstdlib>
#include <string>
#include <windows.h>
using namespace std;
//规则:从一点开始画图。每次可以从现有的点上出发,往上下左右四个方向画。但新增的点不能碰到现有的点。画布最外面留白一圈
#define random(x) (rand()%x) //随机数
#define ROW 50 //行数
#define COL 50 //列数
#define seedX ROW/2 //初始位置,默认为中心
#define seedY COL/2
int b[ROW][COL]; //画布
struct point
{
int x;
int y;
};
struct compare //set的排序函数
{
bool operator()(const point &p1,const point &p2)const
{
//return p1.x * COL + p1.y < p2.x * COL + p2.y;
return p1.x==p2.x ? p1.y<p2.y: p1.x<p2.x;
}
};
void init() //初始化,全部置0
{
for(int i=0;i<ROW;i++)
{
for(int j=0;j<COL;j++)
{
b[i][j]=0;
}
}
}
void print() //打印画布01序列
{
for(int i=0;i<ROW;i++)
{
for(int j=0;j<COL;j++)
{
cout<<b[i][j];
}
cout<<endl;
}
}
void printAs() //以方块形式打印图案
{
string b2[ROW][COL];
int count = 0;
for(int i=0; i<ROW; i++)
{
for(int j=0; j<COL; j++)
{
if(b[i][j])
{
b2[i][j]="■";
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0xF1);
/*输出颜色说明。导入windows.h,使用SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0x71)。参数中的16进制数字第一位表示背景颜色,第二位表示文字颜色,代码含义为
0 = 黑色 8 = 灰色
1 = 蓝色 9 = 淡蓝色
2 = 绿色 A = 淡绿色
3 = 湖蓝色 B = 淡浅绿
4 = 红色 C = 淡红色
5 = 紫色 D = 淡紫色
6 = 黄色 E = 淡黄色
7 = 白色 F = 亮白色
如果背景为“白色”,会显示cmd默认的颜色
*/
count++;
}
else
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0xF9);
b2[i][j]="□";
}
cout<<b2[i][j];
}
cout<<count<<endl;
}
}
void print(set<point,compare> pl) //测试函数,打印set中的值
{
set<point,compare>::iterator iter = pl.begin();
for(; iter!=pl.end(); iter++)
{
cout<<iter->x<<","<<iter->y<<" - ";
}
cout<<endl;
}
bool isNext(int x, int y, char dir) //判断某个位置是不是可以画下一笔
{
if(0<x && ROW-1>x && 0<y && COL-1>y)
{
int temp = 0;
switch(dir)
{
case 'U':
{ temp = b[x-1][y-1]+b[x-1][y]+b[x-1][y+1]+b[x][y-1]+b[x][y]+b[x][y+1];
break;
}
case 'D':
{
temp = b[x][y-1]+b[x][y]+b[x][y+1]+b[x+1][y-1]+b[x+1][y]+b[x+1][y+1];
break;
}
case 'L':
{
temp = b[x-1][y-1]+b[x-1][y]+b[x][y-1]+b[x][y]+b[x+1][y-1]+b[x+1][y];
break;
}
case 'R':
{
temp = b[x-1][y]+b[x-1][y+1]+b[x][y]+b[x][y+1]+b[x+1][y]+b[x+1][y+1];
break;
}
}
if(temp==0)
return true;
}
return false;
}
void findAndErase(point p, set<point,compare> &nextSet) //新添加点之后,删除候选列表中不能继续画的点
{
set<point,compare>::iterator iterErase;
iterErase = nextSet.find(p);
if(iterErase != nextSet.end())
{
nextSet.erase(iterErase);
}
}
void setNextSet(point seed, set<point,compare> &nextSet) //设置候选列表
{
int x = seed.x;//x为行,y为列
int y = seed.y;
point p;
p.x = x-1;
p.y = y;
if(isNext(x-1,y,'U'))
{
nextSet.insert(p);
}
else
{
findAndErase(p,nextSet);
}
p.x = x+1;
p.y = y;
if(isNext(x+1,y,'D'))
{
nextSet.insert(p);
}
else
{
findAndErase(p,nextSet);
}
p.x = x;
p.y = y-1;
if(isNext(x,y-1,'L'))
{
nextSet.insert(p);
}
else
{
findAndErase(p,nextSet);
}
p.x = x;
p.y = y+1;
if(isNext(x,y+1,'R'))
{
nextSet.insert(p);
}
else
{
findAndErase(p,nextSet);
}
p.x = x-1;
p.y = y-1;
findAndErase(p,nextSet); //角上相邻的
p.x = x+1;
p.y = y-1;
findAndErase(p,nextSet);
p.x = x-1;
p.y = y+1;
findAndErase(p,nextSet);
p.x = x+1;
p.y = y+1;
findAndErase(p,nextSet);
}
//通过随机数获取下一步的位置。种子在main中生成
set<point,compare>::iterator getNextIter(set<point,compare> &nextSet)
{
int count = nextSet.size();
set<point,compare>::iterator iterNext = nextSet.begin();
int pos = int(random(count));
for(int i = 0; i<pos; i++)
{
iterNext++;
}
return iterNext;
}
//画下一格:从候选里面选出一个;更改b的值;判断它四个正方向的候选,如果是候选加入,不是候选尝试查找删除;判断它四个斜方向,从候选列表删除。
void darwNext(set<point,compare> &nextSet)
{
set<point,compare>::iterator iterNext;
iterNext = getNextIter(nextSet);
point next;
next.x = iterNext->x;
next.y = iterNext->y;
b[next.x][next.y]=1;
nextSet.erase(iterNext);
setNextSet(next, nextSet);
}
void generate() //采用默认seed生成
{
b[seedX][seedY]=1;
set<point,compare> nextSet;
point seed;
seed.x = seedX;
seed.y = seedY;
setNextSet(seed,nextSet);
while(!nextSet.empty())
{
darwNext(nextSet);
}
}
void main()
{
init();
srand(unsigned(time(0)));
generate();
printAs();
}
画出来的图形效果(每次运行画的都不一样哦!)