在EasyX看到别人写的万花尺程序,想起来小时候玩的,就动手改进增加了一些效果。参考程序连接(侵删):万花尺_慢羊羊
我的效果如下,输入数据:【300 180 100】【450 320 141】
输出效果:
输入数据:【86 30 42】【86 38 12】【300 180 100】【600 400 140】
输出效果:
由于代码简单,就不多解释,值得注意的是:代码运行环境是VS2019 EasyX20200109,其他版本没试过,,如果代码提示参数类型有错误,可以设置 项目——属性——配置属性——高级——字符集——将Unicode设置为未设置 即可。附上代码:
//********************************************************************//
// 程序名称:万花尺程序
// 编译环境:VS2019,EasyX_20200315(beta)
//
#include
#include
#include
#include
#include
#include
#include
#include
#pragma comment(lib,"WINMM.LIB")
#define PI 3.1415926536 //π的近似值
#define WIN_X 1200 //绘图窗口尺寸X轴
#define WIN_Y 700 //绘图窗口尺寸Y轴
void CurrentTime(char*); //读取电脑时间函数
int color[15] = { //颜色数组
GREEN, // 0x00AA00 绿
LIGHTMAGENTA, // 0xFF55FF 亮紫
BLUE, // 0xAA0000 蓝
RED, // 0x0000AA 红
YELLOW, // 0x55FFFF 黄
LIGHTGRAY, // 0xAAAAAA 浅灰
MAGENTA, // 0xAA00AA 紫
LIGHTCYAN, // 0xFFFF55 亮青
WHITE, // 0xFFFFFF 白
LIGHTGREEN, // 0x55FF55 亮绿
BROWN, // 0x0055AA 棕
LIGHTRED, // 0x5555FF 亮红
CYAN, // 0xAAAA00 青
DARKGRAY, // 0x555555 深灰
LIGHTBLUE // 0xFF5555 亮蓝
};
///主程序///
*******************************************************************/
int main()
{
int circle_num=1;//不擦除绘图次数
int R=300; // 外部静圆半径
int r=180; // 内部动圆半径
int dr=100; // 内部动圆上的作图点到圆心的距离
HWND hwnd = initgraph(WIN_X, WIN_Y); // 创建绘图窗口
setorigin(WIN_X / 2, WIN_Y / 2); // 设定圆心坐标
//绘图窗口名字
SetWindowText(hwnd, "万花尺");
//mciSendString(TEXT("open H:\\我曾-隔壁老樊.mp3 alias mysong"), NULL, 0, NULL);//插入音频文件
//mciSendString(TEXT("play mysong"), NULL, 0, NULL);
begin:
// 获取用户输入
char input_pre[30];//存储用户输入的数组
bool flag;//反馈用户在输入窗口点击 “确认”键还是“取消”键
flag=InputBox(input_pre,30,"大圆(R<350)_小圆(r,
"请按顺序输入参数:","300 180 100",0,0,false);
if (flag == false)//防止误按“取消”键
{
flag=_getch();
R = 300;
r = 180;
dr = 100;
}
sscanf_s(input_pre, "%d %d %d", &R,&r,&dr);
/**********************************************************************************************************/
// 求执行次数( )
int m = R, n = r;
int tmp;
while (n != 0)//求最小公约数,即可求得绘图周期
{
tmp = m % n;
m = n;
n = tmp;
}
double maxdegree = (double)r / m * 2 * PI;//绘图周期
///
//显示输入参数
char RR[10], rr[10], drr[10],CIRcle_num[10];
//清空前次的输入
for(int W_y=5;W_y <= 105;W_y += 25)
{
outtextxy(5 - WIN_X / 2, W_y - WIN_Y / 2, " ");
}
sprintf_s(RR, "R=%d",R);
sprintf_s(rr, "r=%d", r);
sprintf_s(drr, "△r=%d", dr);
sprintf_s(CIRcle_num, "CIR=%d", (circle_num+2)/3);
settextstyle(18, 0, _T("宋体"));
settextcolor(GREEN);
outtextxy(5-WIN_X / 2, 5-WIN_Y / 2,RR);
outtextxy(5 - WIN_X / 2, 30 - WIN_Y / 2, rr);
outtextxy(5 - WIN_X / 2, 55 - WIN_Y / 2, drr);
outtextxy(5 - WIN_X / 2, 80 - WIN_Y / 2, CIRcle_num);
//
int maxnum; //旋转绘图的个数
maxnum = (int)round(162.0 * (R - 50.0) / (maxdegree * (300 - 50.0)));//根据图形复杂度和绘图尺寸调整旋转绘图个数
if (maxnum < 4) maxnum = 1;
else if (maxnum > 11) maxnum = 11;//限制绘图最大和最小个数,避免太密集
//输出绘图个数
char MAXnum[10];
sprintf_s(MAXnum, "N=%d", maxnum);
outtextxy(5 - WIN_X / 2, 105 - WIN_Y / 2, MAXnum);
/*/******************************//****************************************///
// 绘图
int x, y;
int D_FLAG = 0;//旋转的次数
int x0, y0;
double add = 0.003; //每点增量
int delay_time;//延时参数
//根据绘图像素数调整绘图速度(延时时长)
delay_time =(int)round( 100*5.0 * add );
if (delay_time > 500) delay_time = 500;//避免延时过长
for (double degree = 0; degree < maxdegree; degree += add)
{
x = (int)round(dr * cos(degree * (double(R) / r - 1)) + ((double)R - r) * cos(degree)); //圆内旋线公式 ,x坐标
y = (int)round(dr * sin(degree * (double(R) / r - 1)) - ((double)R - r) * sin(degree));
putpixel(x, y, color[circle_num - 1]);
//根据绘图像素数调整绘图速度(延时时长)
for (int us = 0;us < delay_time;us++)
for (int i = 0;i < 50000;i++);
}
旋转一定角度绘图,为了美观//
//for循环使得每次旋转2.5度,
for (D_FLAG=1;D_FLAG < maxnum;D_FLAG++)
{
if (D_FLAG == (maxnum-1))
add = 0.003;
else add = 0.02;
for (double degree = 0; degree < maxdegree; degree += add)
{
x0 = (int)round(dr * cos(degree * (double(R) / r - 1)) + ((double)R - r) * cos(degree));
y0 = (int)round(dr * sin(degree * (double(R) / r - 1)) - ((double)R - r) * sin(degree));
x = (int)round(x0 * cos(PI / 72 * D_FLAG) - y0 * sin(-PI / 72 * D_FLAG)); //逆时针旋转2.5度
y = (int)round(x0 * sin(-PI / 72 * D_FLAG) + y0 * cos(PI / 72 * D_FLAG));
if (D_FLAG == (maxnum - 1))//设置最后一次绘图颜色和绘图速度,与其他不同
{
putpixel(x, y, color[circle_num +1]);
for (int us = 0;us < delay_time;us++)
for (int i = 0;i < 50000;i++);
}
else {
putpixel(x, y, color[circle_num]);
for (int us = 0;us < delay_time;us++)
for (int i = 0;i < 100000;i++);
}
}
}
/绘图完成
///用户操作//******************************************************/
IMAGE img;//截图,方便保存
getimage(&img, -WIN_X / 2, -WIN_Y / 2, WIN_X , WIN_Y );
outtextxy(5 - WIN_X / 2, WIN_Y / 2-30, _T("按空格键继续,按s或S保存图像,按c或C重新绘制,按 ESC 退出"));
// 重新开始,或退出程序
char c = _getch();
if (c == 's'||c=='S') /'s'||'S'键为保存图片到D:盘
{
char tim1[50] = "D:\\万花尺",tim2[30],tim3[10]=".png";
CurrentTime(tim2); //获取时间并以字符类型放入tim1
strcat_s(tim1,50,tim2);
strcat_s(tim1,50, tim3);
saveimage(tim1,&img);//保存图片,以时间命名图片
contin: //防止误按 s 键
settextcolor(LIGHTCYAN);
outtextxy(5 - WIN_X / 2, 130 - WIN_Y / 2, "图片保存完成!");
outtextxy(5 - WIN_X / 2, 155 - WIN_Y / 2, "按相应键继续..");
c = _getch();
settextcolor(GREEN);
outtextxy(5 - WIN_X / 2, 130 - WIN_Y / 2, " ");//清空字样
outtextxy(5 - WIN_X / 2, 155 - WIN_Y / 2, " ");
if (c == 's' || c == 'S') goto contin;
}
switch (c) {
case 0x1b: //ESC键退出程序
closegraph();//退出绘图程序
return 0;
break;
case 0x20: //空格键键,在原窗口继续绘图
circle_num+=3;
if (circle_num > 15) circle_num = 1;
//清除提示位置
outtextxy(5 - WIN_X / 2, WIN_Y / 2 - 30, _T(" "));
goto begin;
break;
case 'c':
case 'C': //'c'||'C'键关闭原绘图窗口,并新建绘图窗口
{
circle_num = 1;
closegraph();
HWND hwnd = initgraph(WIN_X, WIN_Y); // 创建绘图窗口
setorigin(WIN_X / 2, WIN_Y / 2); // 设定圆心坐标
goto begin;
break;
}
default://其他键,退出程序
break;
}
return 0;
}
///*****************************************
/读取计算机本地时间函数//
void CurrentTime(char* TIM)
{
time_t tt;
time(&tt);
struct tm t;
localtime_s(&t, &tt);
char tttt[30];
sprintf_s(tttt, "%d_%02d_%02d_%02d_%02d_%02d",
t.tm_year + 1900,
t.tm_mon + 1,
t.tm_mday,
t.tm_hour,
t.tm_min,
t.tm_sec);
strcpy_s(TIM, strlen(tttt) + 1,tttt);
}
/*****************************************************/
/*******************************************************/
谢谢阅览,如有侵权,还请联系。