如何用 C 語言畫一個「聖誕樹」?
相關問題
如何用數學軟體畫一個「聖誕樹」? - Python
我使用了左右鏡像的Sierpinski triangle,每層減去上方一小塊,再用符號點綴。可生成不同層數的「聖誕樹」,如下圖是5層的結果。
#include &
#include &
int main(int argc, char* argv[]) {
int n = argc &> 1 ? atoi(argv[1]) : 4;
for (int j = 1; j &<= n; j++) {
int s = 1 &<&< j, k = (1 &<&< n) - s, x;
for (int y = s - j; y &>= 0; y--, putchar("
")) {
for (x = 0; x &< y + k; x++) printf(" ");
for (x = 0; x + y &< s; x++) printf("%c ", "!" ^ y x);
for (x = 1; x + y &< s; x++) printf("%c ", "!" ^ y (s - y - x - 1));
}
}
}
基本代碼來自Sierpinski triangle的實現,字元的想法來自於code golf - Draw A Sierpinski Triangle。
--更新1: 上面的是我嘗試盡量用最少代碼來畫一個抽象一點的聖誕樹,因此樹榦都沒有。然後,我嘗試用更真實一點的風格。因為樹是一個比較自相似的形狀,這次使用遞歸方式描述樹榦和分支。n = 0的時候,就是只畫一主樹榦,樹榦越高就越幼:n = 1的時候,利用遞歸畫向兩面分支,旋轉,越高的部分縮得越小。#include &
#include &
#define PI 3.14159265359
float sx, sy;
float sdCircle(float px, float py, float r) {
float dx = px - sx, dy = py - sy;
return sqrtf(dx * dx + dy * dy) - r;
}
float opUnion(float d1, float d2) {
return d1 &< d2 ? d1 : d2;
}
#define T px + scale * r * cosf(theta), py + scale * r * sin(theta)
float f(float px, float py, float theta, float scale, int n) {
float d = 0.0f;
for (float r = 0.0f; r &< 0.8f; r += 0.02f)
d = opUnion(d, sdCircle(T, 0.05f * scale * (0.95f - r)));
if (n &> 0)
for (int t = -1; t &<= 1; t += 2) {
float tt = theta + t * 1.8f;
float ss = scale * 0.9f;
for (float r = 0.2f; r &< 0.8f; r += 0.1f) {
d = opUnion(d, f(T, tt, ss * 0.5f, n - 1));
ss *= 0.8f;
}
}
return d;
}
int main(int argc, char* argv[]) {
int n = argc &> 1 ? atoi(argv[1]) : 3;
for (sy = 0.8f; sy &> 0.0f; sy -= 0.02f, putchar("
"))
for (sx = -0.35f; sx &< 0.35f; sx += 0.01f)
putchar(f(0, 0, PI * 0.5f, 1.0f, n) &< 0 ? "*" : " ");
}
這段代碼實際上是用了圓形的距離場來建模,並且沒有優化。
這是一棵「祼樹」,未能稱得上是「聖誕樹」。
--
更新2: 簡單地加入裝飾及絲帶,在命令行可以選擇放大倍率,下圖是兩倍大的。// f() 及之前的部分沿上
int ribbon() {
float x = (fmodf(sy, 0.1f) / 0.1f - 0.5f) * 0.5f;
return sx &>= x - 0.05f sx &<= x + 0.05f;
}
int main(int argc, char* argv[]) {
int n = argc &> 1 ? atoi(argv[1]) : 3;
float zoom = argc &> 2 ? atof(argv[2]) : 1.0f;
for (sy = 0.8f; sy &> 0.0f; sy -= 0.02f / zoom, putchar("
"))
for (sx = -0.35f; sx &< 0.35f; sx += 0.01f / zoom) {
if (f(0, 0, PI * 0.5f, 1.0f, n) &< 0.0f) {
if (sy &< 0.1f)
putchar(".");
else {
if (ribbon())
putchar("=");
else
putchar("............................#jo"[rand() % 32]);
}
}
else
putchar(" ");
}
}
2D的我想已差不多了。接下來看看有沒有空嘗試3D的。
--
更新3:終於要3D了。之前每個節點是往左和右分支,在三維中我們可以更自由一點,我嘗試在每個節點申出6個分支。最後用了簡單的Lambertian著色(即max(dot(N, L), 0)。n = 1 的時候比較容易看出立體的著色:
因為需要三維旋轉,不能像二維簡單使用一個角度來代表旋轉,所以這段代碼加入了不少矩陣運算。當然用四元數也是可以的。
#include &
#include &
#include &
#define PI 3.14159265359f
float sx, sy;
typedef float Mat[4][4];
typedef float Vec[4];
void scale(Mat* m, float s) {
Mat temp = { {s,0,0,0}, {0,s,0,0 }, { 0,0,s,0 }, { 0,0,0,1 } };
memcpy(m, temp, sizeof(Mat));
}
void rotateY(Mat* m, float t) {
float c = cosf(t), s = sinf(t);
Mat temp = { {c,0,s,0}, {0,1,0,0}, {-s,0,c,0}, {0,0,0,1} };
memcpy(m, temp, sizeof(Mat));
}
void rotateZ(Mat* m, float t) {
float c = cosf(t), s = sinf(t);
Mat temp = { {c,-s,0,0}, {s,c,0,0}, {0,0,1,0}, {0,0,0,1} };
memcpy(m, temp, sizeof(Mat));
}
void translate(Mat* m, float x, float y, float z) {
Mat temp = { {1,0,0,x}, {0,1,0,y}, {0,0,1,z}, {0,0,0,1} };
memcpy(m, temp, sizeof(Mat));
}
void mul(Mat* m, Mat a, Mat b) {
Mat temp;
for (int j = 0; j &< 4; j++)
for (int i = 0; i &< 4; i++) {
temp[j][i] = 0.0f;
for (int k = 0; k &< 4; k++)
temp[j][i] += a[j][k] * b[k][i];
}
memcpy(m, temp, sizeof(Mat));
}
void transformPosition(Vec* r, Mat m, Vec v) {
Vec temp = { 0, 0, 0, 0 };
for (int j = 0; j &< 4; j++)
for (int i = 0; i &< 4; i++)
temp[j] += m[j][i] * v[i];
memcpy(r, temp, sizeof(Vec));
}
float transformLength(Mat m, float r) {
return sqrtf(m[0][0] * m[0][0] + m[0][1] * m[0][1] + m[0][2] * m[0][2]) * r;
}
float sphere(Vec c, float r) {
float dx = c[0] - sx, dy = c[1] - sy;
float a = dx * dx + dy * dy;
return a &< r * r ? sqrtf(r * r - a) + c[2] : -1.0f;
}
float opUnion(float z1, float z2) {
return z1 &> z2 ? z1 : z2;
}
float f(Mat m, int n) {
float z = -1.0f;
for (float r = 0.0f; r &< 0.8f; r += 0.02f) {
Vec v = { 0.0f, r, 0.0f, 1.0f };
transformPosition(v, m, v);
z = opUnion(z, sphere(v, transformLength(m, 0.05f * (0.95f - r))));
}
if (n &> 0) {
Mat ry, rz, s, t, m2, m3;
rotateZ(rz, 1.8f);
for (int p = 0; p &< 6; p++) {
rotateY(ry, p * (2 * PI / 6));
mul(m2, ry, rz);
float ss = 0.45f;
for (float r = 0.2f; r &< 0.8f; r += 0.1f) {
scale(s, ss);
translate(t, 0.0f, r, 0.0f);
mul(m3, s, m2);
mul(m3, t, m3);
mul(m3, m, m3);
z = opUnion(z, f(m3, n - 1));
ss *= 0.8f;
}
}
}
return z;
}
float f0(float x, float y, int n) {
sx = x;
sy = y;
Mat m;
scale(m, 1.0f);
return f(m, n);
}
int main(int argc, char* argv[]) {
int n = argc &> 1 ? atoi(argv[1]) : 3;
float zoom = argc &> 2 ? atof(argv[2]) : 1.0f;
for (float y = 0.8f; y &> -0.0f; y -= 0.02f / zoom, putchar("
"))
for (float x = -0.35f; x &< 0.35f; x += 0.01f / zoom) {
float z = f0(x, y, n);
if (z &> -1.0f) {
float nz = 0.001f;
float nx = f0(x + nz, y, n) - z;
float ny = f0(x, y + nz, n) - z;
float nd = sqrtf(nx * nx + ny * ny + nz * nz);
float d = (nx - ny + nz) / sqrtf(3) / nd;
d = d &> 0.0f ? d : 0.0f;
// d = d &< 1.0f ? d : 1.0f;
putchar(".-:=+*#%@@"[(int)(d * 9.0f)]);
}
else
putchar(" ");
}
}
--
更新4:發現之前的TransformLength()寫錯了,上面已更正。另外,考慮提升性能時,一般是需要一些空間剖分的方式去加速檢查,但這裡剛好是一個樹狀的場景結構,可以簡單使用Bounding volume hierarchy,我使用了球體作為包圍體積。只需加幾句代碼,便可以大大縮減運行時間。
另外,考慮到太小的葉片是很難採樣得到好看的結果,我嘗試以一個較大的球體去表現葉片(就如素描時考慮更整體的光暗而不是每片葉片的光暗),我覺得結果有進步。
float f(Mat m, int n) {
// Culling
{
Vec v = { 0.0f, 0.5f, 0.0f, 1.0f };
transformPosition(v, m, v);
if (sphere(v, transformLength(m, 0.55f)) == -1.0f)
return -1.0f;
}
float z = -1.0f;
if (n == 0) { // Leaf
Vec v = { 0.0f, 0.5f, 0.0f, 1.0f };
transformPosition(v, m, v);
z = sphere(v, transformLength(m, 0.3f));
}
else { // Branch
for (float r = 0.0f; r &< 0.8f; r += 0.02f) {
Vec v = { 0.0f, r, 0.0f, 1.0f };
transformPosition(v, m, v);
z = opUnion(z, sphere(v, transformLength(m, 0.05f * (0.95f - r))));
}
}
// ...
}
其實我在回答這問題的時候,並沒有計劃,只是一步一步地嘗試。現在我覺得用這規模的代碼大概不能再怎麼進展了。不過今天看到大堂里的聖誕樹,覺得那些裝飾物還挻有趣的,有時候除了畫整體,也可以畫局部,看看是否能再更新。
--相關回答:如何用C語言畫一個「心形」? - Milo Yip 的回答昨天畫個心,今天畫個聖誕樹。。。
#include &
int main(int argc, char **argv) {
puts("xf0x9fx8ex84");
return 0;
}
不謝,給你半棵樹,湊合用
#include &
int main(){
printf("*
");
printf("**
");
printf("***
");
printf("*****
");
printf("*******
");
printf("*********
");
printf("***********
");
printf("*************
");
printf("***************
");
printf("*****************
");
printf("*
");
printf("*
");
printf("*
");
printf("*
");
}
轉自: 老手是這樣教新手編程的
#define M 002354l
#define A 000644l
#define G 000132l
#define I 000322l
#define C 000374l
#define a ;
#define b for
#define c ++
#define d %
#define e int
#define f ,
#define g -
#define h 011
#define i =
#define j {
#define k )
#define l "
"
#define m main
#define n &<
#define o }
#define p &>
#define q
#define r (
#define s ||
#define t ?
#define u putchar
#define v void
#define w "*"
#define x :
#define y " "
#define _ /
#define C_O_O_L return
e u r e k a
e
m r
v k j
j j j j
j j j j j
j j j j j j
j j j j j j j
j e z a b r z i
M _ A _ G _ I _ C
a z n G a u r z d h
+ z _ h p M _ A q z d
h + z _ h n M _ G q z _
h n z d h + M _ I q z _ h
p z d h g M _ C t w x y k f
z d h g h + 1 s u r l k f z c
k a u r l k a j j j j j j j j j
j j C_O_O_L M _ A _ G _ I _ C a o
o o o o o o o o o o o o o o o o o o
o o o o
o o o o
o o o o
o o o o
#include
char* ct = " ****
*****
*******
*
*
";int main(int argc, char** argv){ printf(ct); return 0;}//保證想畫啥畫啥
要是不限定是C語言這裡有一個JS的例子(動態3D旋轉聖誕樹)
M=Math;Q=M.random;J=[];U=16;T=M.sin;E=M.sqrt;for(O=k=0;x=z=j=i=k&<200;)with(M[k]=k?c.cloneNode(0):c){width=height=k?32:W=446;with(getContext("2d"))if(k&>10|!k)for(font="60px Impact",V="rgba(";I=i*U,fillStyle=k?k==13?V+"205,205,215,.15)":V+(147+I)+","+(k%2?128+I:0)+","+I+",.5)":"#cca",i&<7;)beginPath(fill(arc(U-i/3,24-i/2,k==13?4-(i++)/2:8-i++,0,M.PI*2,1)));else for(;x=T(i),y=Q()*2-1,D=x*x+y*y,B=E(D-x/.9-1.5*y+1),R=67*(B+1)*(L=k/9+.8)&>&>1,i++&
哥們你是準備在聖誕節表白嗎?
這個用for循環
#include&
int main()
{
printf(" __________________________________________________
");
printf(" | _ |
");
printf(" | /|,/ _ _ _ / ` /_ _ . _ _/_ _ _ _ _|
");
printf(" |/ / /_" / / /_/ /_, / / / / _ / / / / /_| _ |
");
printf(" | _/ |
");
printf(" | ~~** 每晚都要看日出 **~~ |
");
printf(" |__________________________________________________|
");
printf("
");
printf("
");
printf(" * ,
");
printf(" _/^\_
");
printf(" &< &>
");
printf(" * `/` *
");
printf(" ,@.*;@,
");
printf(" /_o.I %_ *
");
printf(" * (`"--:o(_@;
");
printf(" /`;--.,__ `") *
");
printf(" ;@`o % O,*`"`
");
printf(" * (`"--)_@ ;o %"() *
");
printf(" /`;--._`""--._O"@;
");
printf(" /*,()~o`;-.,_ `""`)
");
printf(" * /`,@ ;+ () o*`;-";
");
printf(" (`""--.,_0 +% @" ()
");
printf(" /-.,_ ``""--....-"`) *
");
printf(" * /@%;o`:;"--,.__ __."
");
printf(" ;*,(); @ % ^;~`『`o;@(); *
");
printf(" /(); o^~; ().o@*`;%O
");
printf(" ` = .==~~==,,,.,=~= ~===`
");
printf(" _____.----.0--""---------...___...-----._
");
printf(" "` ( * */ ___\0//___
");
printf(" =, )_ % |\ | | \| ~
");
printf(" .--" ") @ | \| | |
");
printf(" _0 o( )_- . ., |\_|_|_\| `
");
printf(" `~~~` ` `- == -- == = -`
");
printf("
");
printf(".:*~*:._.:*~*:._.:*~*:._.:*~*:._.:*~*:._.:*~*:.:*~*:
");
return 0;
}
聖誕樹是昨天晚上,hexo部署到Coding,Coding返回的。
/*聖誕樹*/
int j,k,l;
for (int j = 1; j &< 5; ++j) {printf(" "); for (int k = j; k &< 5; ++k) { printf(" ");//輸出空格 } for (int l = 0; l &< j*2-1; ++l) { printf("*");//輸出*號 } printf(" ");//每次循環換行 } for (int j = 1; j &< 10; ++j) {printf(" "); for (int k = j; k &< 10; ++k) { printf(" ");//輸出空格 } for (int l = 0; l &< j*2-1; ++l) { printf("*");//輸出*號 } printf(" ");//每次循環換行 } for (int j = 1; j &< 20; ++j) {printf(" "); for (int k = j; k &< 20; ++k) { printf(" ");//輸出空格 } for (int l = 0; l &< j*2-1; ++l) { printf("*");//輸出*號 } printf(" ");//每次循環換行 } for (int j = 1; j &< 12; ++j) { printf(" "); for (int k = 1; k &< 5; ++k) { for (int l = 1; l &< 3; ++l) { printf("*"); } }printf(" "); } return 0; }
#includeint main()
{int a;
printf(" *
");
printf(" ***
");
printf(" *****
");
printf(" *******
");
printf(" *********
");
printf(" ***********
");
printf(" **
");
printf(" **
");
printf(" **
");
printf(" **
");
scanf("%d",a);
return 0;
}c語言上機課看到這個問題,隨手畫了一個
又是不會做作業的來提問的吧
這個估計是大學生來求作業的啊╯﹏╰
推薦閱讀:
※如何評價C# 6的這個新特性?
※怎樣減輕程序中 if 語句的依賴?
※遊戲中的隨機地圖是如何保存的?
※數據結構存儲數據內存不夠如何解決?
※零基礎自學反彙編相關的計算機知識,該如何入門,有什麼書可以推薦?