C++生成的线性十字绣图案

搞了这么个无聊东西,可以用来做杯垫。我想我肯定是绣十字绣的人们中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();
}


画出来的图形效果(每次运行画的都不一样哦!)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值