为了账号安全,请及时绑定邮箱和手机立即绑定

【算法杂谈 2】情人节,用C++画一个心:)

情人节到啦,作为程序员开发者,应该送给男女朋友什么礼物呢?我们这次不聊 算法与数据结构 ,一起用C++语言画个心作为礼物吧!(被罚跪搓衣板儿什么的概不负责= =)

严格来说,这不是一个算法问题,就当作是情人节特辑吧:)

在网上稍微查一查心形的曲线方程,会发现很多,最流行的曲线方程应该就是这个了:

嗯,方程看着复杂,我们不管这是怎么推导出来的(我真的不会啊= =,不过我会一个更丑的心形曲线的推导过程,大家有兴趣的话有时间给大家上一堂数学课:)),让我们使用拿来主义,直接使用吧!我们回忆一下圆的方程,比如:x2+y2=1,那么所有的点(x,y),若使得x2+y2==1,则这个点在这个圆的边界线上;若使得x2+y2<1,则这个点在圆内;若使得x2+y2>1,则这个点在圆外。

好了,同理,对于这个方程,若点(x,y)让方程左边等于0,则这个点在这个心形曲线上;若让方程左边小于0,则这个点在这个心形线内;若让方程左边大于0,则这个点在这个心形线外。

嗯,我们要做的就是写一个双重循环,遍历x和y的值,将心形线以内的地方,涂上某一个字符,比如‘*’。

那么我们首先要确定我们双重循环的边界。我们打印输出,肯定是要逐行输出,从上到下。所以我们的第一层循环要对y值做循环。观察一下,可以看到y的上界大概是1.3;下界大概是-1.1;所以,我们可以从1.3逐渐减少到-1.1,初始我们可以选取步长为0.1。同理,对于x,可以看出他的左右边界大概为-1.2和+1.2,我们就从-1.2遍历到1.2,步长也选择0.1。

我们的第一个代码就是这样的:

#include <iostream>
#include <cmath>
using namespace std;

int main() {

    for( float y = 1.3 ; y >= -1.1 ; y -= 0.1 ){
        for( float x = -1.2 ; x <= 1.2 ; x += 0.1)
            if( pow((x*x+y*y-1.0),3) - x*x*y*y*y <= 0.0 )
                cout<<'*';
            else
                cout<<' ';
        cout<<endl;
    }

    return 0;
}

是不是清晰易懂?运行一下,结果是这样的:

Screen Shot 2017-02-14 at 1.41.50 AM.png

咦?为什么这么瘦?看来x方向要拉伸一下。怎么拉伸?其实,我们让我们的步长稍微小一点儿就好了。因为第一层循环(y值)走了多少次,决定了图像的高度(每走一次,打印一个回车);而第二层循环(x值)走了多少次,则决定了图像的宽度(每走一次,打印一个字符)。所以,我们把x的步长缩小,x的循环就会多走几次,相应的,整个图形就会宽一些。我们将x的步长改为0.05,代码是这样的:

#include <iostream>
#include <cmath>
using namespace std;

int main() {

    for( float y = 1.3 ; y >= -1.1 ; y -= 0.1 ){
        for( float x = -1.2 ; x <= 1.2 ; x += 0.05)
            if( pow((x*x+y*y-1.0),3) - x*x*y*y*y <= 0.0 )
                cout<<'*';
            else
                cout<<' ';
        cout<<endl;
    }

    return 0;
}

结果就变成这样啦:

Screen Shot 2017-02-14 at 1.45.41 AM.png

是不是好看了许多?

一旦我们掌握了这个技巧,就可以随易变换我们的这个心形的宽和高啦。比如,我让这个心形,宽和高更多一些,同时再稍微扁一点儿。y值的步长为0.06,x值的步长为0.025,就是这样的:

#include <iostream>
#include <cmath>
using namespace std;

int main() {

    for( float y = 1.3 ; y >= -1.1 ; y -= 0.06 ){
        for( float x = -1.2 ; x <= 1.2 ; x += 0.025)
            if( pow((x*x+y*y-1.0),3) - x*x*y*y*y <= 0.0 )
                cout<<'*';
            else
                cout<<' ';
        cout<<endl;
    }

    return 0;
}

Screen Shot 2017-02-14 at 1.49.40 AM.png

是不是很酷?

当然啦,如果我们填入不同的字符,可能有不同的视觉效果哦~

Screen Shot 2017-02-14 at 1.51.17 AM.png

我们也很容易做出类似的镂空效果哦~

Screen Shot 2017-02-14 at 1.52.37 AM.png

不过,你以为心形曲线只有一个方程可以描述吗?在网上多做做功课,发现相关的方程多得很:)比如这个:

heart2.jpg

我们用同样的思路,就可以编出这样的代码:

#include <iostream>
#include <cmath>
using namespace std;

int main() {

    for( float y = 1.3 ; y >= -1.1 ; y -= 0.06 ){
        for( float x = -1.1 ; x <= 1.1 ; x += 0.025 )
            if( x*x + pow(5.0*y/4.0-sqrt(fabs(x)),2) - 1 <= 0.0 )
                cout<<'*';
            else
                cout<<' ';
        cout<<endl;
    }

    return 0;
}

得到的心形是这样的,是不是曲线很不一样:)

Screen Shot 2017-02-14 at 1.58.45 AM.png

大家可以再在网上多搜索一下,看看有没有更符合你意的心形曲线:)

熟悉其他语言,尤其是前端语言的同学,也可以利用这些方程,做出更绚丽的效果哦。尤其是使用canvas,大家不妨自己试试看,期待同学们更好的创意:)

当然了,别忘了,情人节要陪你的男/女朋友哦~ 也不要忘记学习我的课程——算法与数据结构 哦~

愿天下有情人终成眷属,大家加油!

本篇文章的所有代码可以参见这个repo: heart-curve-cplusplus


分享一下 算法与数据结构 课程群里的同学看了这篇帖子以后的创意~ 来自 @甲铁城的卡巴司机 ,他把自己的日文名字融合在了这个图案中,超赞啊!

heart-characters.jpg


关于我的更多文章,欢迎关注我的公众号:是不是很酷:)

图片描述

点击查看更多内容
221人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
全栈工程师
手记
粉丝
2.9万
获赞与收藏
1773

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消