1.题目描述:
(1) 科赫雪花和科赫曲线
科赫曲线(Koch curve)是一个简单的分形(fractal)图形
给定一直线线段,把它等分三段,加入一个等边三角形,以三段的中间一段为底对齐,再去除该段线段。然后,对每个新线段重复进行上述步骤,就可以形成科赫曲线。
如果画 3 条科赫曲线,每次旋转 120 度,就能得到科赫雪花(Koch snowflake):
2. 题目分析:——使用 ASCII 字符完成绘画
可以使用斜线 /、反斜线 \、下划线 _ 和空格这 4 个 ASCII 字符来绘制。
3.代码实现:
(1)实现科赫曲线的具体代码
分析1: 用 C 语言实现科赫曲线
创建一个字符数组 image 作为画布,用于存储绘画的中间结果,最后再把数组打印出来。数组的大小为画布宽长之积 w * h。
设坐标系统是 x 向右、y 向下,并定义字符的左下角为坐标。例如,画笔从 (x, y) 之处往右画,便赋值 image[y * w + x] = '_' ,并把 x 增 1。
我们也定义 6 个方向,0 代表向右,1代表右上,2 代表左上等。注意水平方向(0 和 3)需要画两个下划线,其他方向只画一个字符。
每次调用 KochCurve(n, dir) 函数,表示我们要从当前位置 (x, y) 向 dir 方向绘画一条 n 阶科赫曲线。那么要画一条 n 阶科赫曲线,其实就只需要根据所需方向画 4 条 n - 1 阶科赫曲线。直到 n = 0,一条 0 阶科赫曲线就是一条直线,此时只需按 dir 用字符画一条直线。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//科赫曲线
static char* image;
static int x, y, w, h;
static void Put(int i, int j, char c) {
char *p = image + j * w + i;
if (*p == ' ' || *p == '_') // _ can be overridden by / or \.
*p = c;
}
static void KochCurve(int n, int dir) {
if (n == 0)
switch (dir % 6) {
case 0: Put(x++, y, '_');
Put(x++, y, '_'); break;
case 1: Put(x++, y--, '/'); break;
case 2: Put(--x, y--, '\\'); break;
case 3: Put(--x, y, '_');
Put(--x, y, '_'); break;
case 4: Put(--x, ++y, '/'); break;
case 5: Put(x++, ++y, '\\'); break;
}
else {
KochCurve(n - 1, dir);
KochCurve(n - 1, dir + 1);
KochCurve(n - 1, dir + 5);
KochCurve(n - 1, dir);
}
}
int main() {
w = 2;
h = 1;
for (int n = 0; n < 4; n++) {
image = (char*)malloc(w * h);
memset(image, ' ', w * h);
x = 0;
y = h - 1;
KochCurve(n, 0);
printf("\nn=%d\n\n", n);
for (int j = 0; j < h; j++) {
for (int i = 0; i < w; i++)
putchar(image[j * w + i]);
putchar('\n');
}
w *= 3;
h = n == 0 ? 1 : h * 3;
free(image);
}
system("pause");
}
实验截图:
(2)实现科赫雪花的具体代码
分析 2:科赫雪花仅仅是由 3 科赫曲线组成。我们只需改一下 main(),把画布变大一点,以及在合适的起始坐标画 3 条科赫曲线:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char* image;
static int x, y, w, h;
static void Put(int i, int j, char c) {
char *p = image + j * w + i;
if (*p == ' ' || *p == '_') // _ can be overridden by / or \.
*p = c;
}
static void KochCurve(int n, int dir) {
if (n == 0)
switch (dir % 6) {
case 0: Put(x++, y, '_');
Put(x++, y, '_'); break;
case 1: Put(x++, y--, '/'); break;
case 2: Put(--x, y--, '\\'); break;
case 3: Put(--x, y, '_');
Put(--x, y, '_'); break;
case 4: Put(--x, ++y, '/'); break;
case 5: Put(x++, ++y, '\\'); break;
}
else {
KochCurve(n - 1, dir);
KochCurve(n - 1, dir + 1);
KochCurve(n - 1, dir + 5);
KochCurve(n - 1, dir);
}
}
int main() {
w = 2;
h = 4;
for (int n = 0; n < 4; n++) {
image = (char*)malloc(w * h);
memset(image, ' ', w * h);
x = 0;
y = h / 4 - 1;
KochCurve(n, 0);
KochCurve(n, 4);
KochCurve(n, 2);
printf("\nn=%d\n\n", n);
for (int j = 0; j < h; j++) {
for (int i = 0; i < w; i++)
putchar(image[j * w + i]);
putchar('\n');
}
w *= 3;
h = n == 0 ? 4 : h * 3;
free(image);
}
system("pause");
}
实验截图: