在C++的命令行中绘制一个心形图案通常需要使用字符画的方式,利用字符来拼接出心形的形状。
绘制简易心形
如下这段代码在命令行中绘制了一个简单的 ASCII 艺术图案,通常称为“Mandelbrot集合”或“心形”。它使用了一些数学公式来计算每个点的值,并根据该值选择合适的字符来绘制图案。
具体来说,这段代码使用了两个嵌套的循环,遍历了一定范围内的二维坐标 (x, y)。对于每个坐标点,它计算了一个值 z
和 f
,然后根据 f
的值选择要显示的字符。
z
是一个用来描述坐标点 (x, y) 是否在 Mandelbrot 集合内的中间值。f
是一个计算值,用于决定绘制字符。
在代码的内部循环中,根据 f
的值,选择不同的字符来绘制,这些字符具有不同的密度,从而实现了图案的效果。
#include <stdio.h>
#include <Windows.h>
int main()
{
for (float y = 1.5f; y > -1.5f; y -= 0.1f)
{
for (float x = -1.5f; x < 1.5f; x += 0.05f)
{
float z = x * x + y * y - 1;
float f = z * z * z - x * x * y * y * y;
putchar(f <= 0.0f ? ".:-=+*#%@"[(int)(f * -8.0f)] : ' ');
}
putchar('\n');
}
system("pause");
return 0;
}
输出效果图如下所示;
绘制精致红心
如下这段代码在命令行中生成了一个精美的三维图案,通常称为“Mandelbulb”。它使用数学公式和迭代方法生成了这个图案。
代码的核心部分是 f
函数和 h
函数,它们用来计算图案中的每个点的值。
f
函数接受三个参数x
、y
和z
,用来计算一个中间值a
。这个值a
在后续的计算中被使用。h
函数接受x
和z
作为参数,在给定的范围内迭代y
值,以寻找满足条件f(x, y, z) <= 0
的y
值。这个函数帮助确定图案的形状。
在 main
函数中,代码使用两个嵌套的循环遍历三维坐标 (x, 0, z)
,并计算每个点的值 v
。然后,根据 v
的值,选择合适的字符来绘制图案。
#include <stdio.h>
#include <Windows.h>
#include <math.h>
float f(float x, float y, float z)
{
float a = x * x + 9.0f / 4.0f * y * y + z * z - 1;
return a * a * a - x * x * z * z * z - 9.0f / 80.0f * y * y * z * z * z;
}
float h(float x, float z)
{
for (float y = 1.0f; y >= 0.0f; y -= 0.001f)
if (f(x, y, z) <= 0.0f)
return y;
return 0.0f;
}
int main()
{
for (float z = 1.5f; z > -1.5f; z -= 0.05f)
{
for (float x = -1.5f; x < 1.5f; x += 0.025f)
{
float v = f(x, 0.0f, z);
if (v <= 0.0f)
{
float y0 = h(x, z);
float ny = 0.01f;
float nx = h(x + ny, z) - y0;
float nz = h(x, z + ny) - y0;
float nd = 1.0f / sqrtf(nx * nx + ny * ny + nz * nz);
float d = (nx + ny - nz) * nd * 0.5f + 0.5f;
putchar(".:-=+*#%@"[(int)(d * 5.0f)]);
}
else
putchar(' ');
}
putchar('\n');
}
system("pause");
return 0;
}
图案的生成过程涉及到复杂的数学计算和条件判断,最终使用一系列字符来表示不同的图案区域,以创建视觉上引人入胜的效果,如下图所示;![
](https://img-blog.csdnimg.cn/direct/238deb691ee342e0b626d8701d114873.png)绘制红心保存
如下这段代码生成了一个 ASCII 艺术图案,形状类似于心形,并将图案保存为 PPM 格式的图像文件(heart.ppm)。
代码使用 f
函数和 h
函数来计算图案中每个点的值,与之前的代码类似。不同之处在于,这次代码将计算结果映射到颜色上,并将图像数据写入 PPM 文件。
主要步骤包括:
-
打开一个名为 "heart.ppm" 的文件,准备写入 PPM 格式的图像数据。
-
定义图像的宽度和高度,这里设置为 512x512。
-
写入 PPM 文件的头部信息,包括图像格式、宽度、高度和颜色最大值。
-
使用两个嵌套的循环遍历图像的每个像素。对于每个像素
(sx, sy)
,计算对应的三维坐标(x, 0, z)
。 -
调用
f
函数计算(x, 0, z)
处的值v
,如果v
小于等于 0,则表示在心形内部。 -
如果点在心形内部,计算点
(x, 0, z)
处的法向量,根据法向量的方向确定像素的颜色。这里通过法向量的计算来实现光照效果。 -
将像素的颜色写入 PPM 文件。
-
关闭文件,生成图像。
最终,运行程序会生成一个名为 "heart.ppm" 的图像文件,该图像以 PPM 格式保存,包含了生成的心形图案。这个图像文件可以使用图像查看器或处理工具打开。
#include <stdio.h>
#include <Windows.h>
#include <math.h>
float f(float x, float y, float z)
{
float a = x * x + 9.0f / 4.0f * y * y + z * z - 1;
return a * a * a - x * x * z * z * z - 9.0f / 80.0f * y * y * z * z * z;
}
float h(float x, float z)
{
for (float y = 1.0f; y >= 0.0f; y -= 0.001f)
if (f(x, y, z) <= 0.0f)
return y;
return 0.0f;
}
int main()
{
FILE* fp = fopen("heart.ppm", "w");
int sw = 512, sh = 512;
fprintf(fp, "P3\n%d %d\n255\n", sw, sh);
for (int sy = 0; sy < sh; sy++)
{
float z = 1.5f - sy * 3.0f / sh;
for (int sx = 0; sx < sw; sx++)
{
float x = sx * 3.0f / sw - 1.5f;
float v = f(x, 0.0f, z);
int r = 0;
if (v <= 0.0f)
{
float y0 = h(x, z);
float ny = 0.001f;
float nx = h(x + ny, z) - y0;
float nz = h(x, z + ny) - y0;
float nd = 1.0f / sqrtf(nx * nx + ny * ny + nz * nz);
float d = (nx + ny - nz) / sqrtf(3) * nd * 0.5f + 0.5f;
r = (int)(d * 255.0f);
}
fprintf(fp, "%d 0 0 ", r);
}
fputc('\n', fp);
}
fclose(fp);
system("pause");
}
绘制跳动的心
如下这段代码是一个控制台程序,用于在命令行中以 ASCII 字符形式绘制一个动态的心形图案。程序主要使用了数学函数和 Windows API 来实现图案的生成和动态显示。
主要步骤和功能包括:
-
f
函数和h
函数:这两个函数用于计算特定坐标(x, y, z)
处的值。f
函数计算图案的形状,h
函数用于确定图案的高度。 -
控制台初始化:使用 Windows API 初始化控制台,获取控制台输出的句柄。
-
主循环:程序进入一个无限循环,不断更新和显示心形图案。
-
使用正弦函数生成动画:程序通过正弦函数生成一个
s
值,然后根据s
值计算a
值,用于在图案中创建动画效果。 -
遍历三维坐标:程序使用嵌套的循环遍历三维坐标
(x, y, z)
,其中y
值在范围[0, 1]
内变化,x
和z
值在范围[-1.5, 1.5]
内变化。 -
计算图案点的值:对于每个坐标
(x, y, z)
,调用f
函数计算对应点的值v
,如果v
小于等于 0,则表示在心形内部。 -
显示图案字符:根据计算的
v
值,选择合适的字符(ASCII 字符数组ramp
)来表示图案的不同部分,然后将字符放入缓冲区。 -
更新控制台输出:程序在每次迭代中,根据缓冲区中的字符数组,使用 Windows API 更新控制台的输出,实现动态显示。
-
延时:程序通过
Sleep
函数来控制每帧的刷新速率,以实现动画效果。
#include <stdio.h>
#include <math.h>
#include <windows.h>
#include <tchar.h>
float f(float x, float y, float z)
{
float a = x * x + 9.0f / 4.0f * y * y + z * z - 1;
return a * a * a - x * x * z * z * z - 9.0f / 80.0f * y * y * z * z * z;
}
float h(float x, float z)
{
for (float y = 1.0f; y >= 0.0f; y -= 0.001f)
if (f(x, y, z) <= 0.0f)
return y;
return 0.0f;
}
int main()
{
HANDLE o = GetStdHandle(STD_OUTPUT_HANDLE);
_TCHAR buffer[25][80] = { _T(' ') };
_TCHAR ramp[] = _T(".:-=+*#%@");
for (float t = 0.0f;; t += 0.1f)
{
int sy = 0;
float s = sinf(t);
float a = s * s * s * s * 0.2f;
for (float z = 1.3f; z > -1.2f; z -= 0.1f)
{
_TCHAR* p = &buffer[sy++][0];
float tz = z * (1.2f - a);
for (float x = -1.5f; x < 1.5f; x += 0.05f)
{
float tx = x * (1.2f + a);
float v = f(tx, 0.0f, tz);
if (v <= 0.0f)
{
float y0 = h(tx, tz);
float ny = 0.01f;
float nx = h(tx + ny, tz) - y0;
float nz = h(tx, tz + ny) - y0;
float nd = 1.0f / sqrtf(nx * nx + ny * ny + nz * nz);
float d = (nx + ny - nz) * nd * 0.5f + 0.5f;
*p++ = ramp[(int)(d * 5.0f)];
}
else
*p++ = ' ';
}
}
for (sy = 0; sy < 25; sy++)
{
COORD coord = { 0, sy };
SetConsoleCursorPosition(o, coord);
WriteConsole(o, buffer[sy], 79, NULL, 0);
}
Sleep(33);
}
}
这段代码会在命令行中不断显示一个动态的 ASCII 艺术心形图案,可以按下 Ctrl+C 来退出程序,效果如下所示;