sponsored links

聖誕節來了,教你用各種程式語言手寫一棵聖誕樹

時間已到深冬,今晚就是平安夜了,你會給你的男/女朋友送上一顆平安果嗎?

作為一名科技宅,很抱歉不能給每一位小夥伴都送上蘋果,那就送給大家一個技能吧,用各種程式語言手寫一顆聖誕樹,祈福各位關注我的小夥伴都平平安安!

C/C++

如何用 C 語言畫一個“聖誕樹”,就不介紹太簡單的方法了(for迴圈列印幾個' * ')。直接看網上大神寫的聖誕樹,有沒有很不錯的感覺!

聖誕節來了,教你用各種程式語言手寫一棵聖誕樹

下方是C語言原始碼,可以自行編譯執行。

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#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('\n'))
    for (sx = -0.35f; sx < 0.35f; sx += 0.01f)
      putchar(f(0, 0, PI * 0.5f, 1.0f, n) < 0 ? '*' : ' ');
}

由於原來聖誕樹的葉子和枝幹都是由' * '來代替,風格太過單一。經過作者的最佳化,成功升級為3D效果,還是蠻炫酷的。由於較過多的浮點運算,使得執行時間較長,執行下面的程式花了近1060s ,動手能力強的小夥伴可以嘗試最佳化一下。

聖誕節來了,教你用各種程式語言手寫一棵聖誕樹

下方是原始碼:

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#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('\n'))
    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(' ');
    }
}

python

提供一種最簡單的python實現方法,哈哈!不喜勿噴!

聖誕節來了,教你用各種程式語言手寫一棵聖誕樹

原始碼如下:

height = 5

stars = 1
for i in range(height):
    print((' ' * (height - i)) + ('*' * stars))
    stars += 2
print((' ' * height) + '|')

也可以使用簡單的圖形庫Turtle來實現,就像下面這樣子。原理也很簡單,參照前面最簡單的實現方法,載入圖形庫後把原有的*使用綠色的方塊代替,在各個角和頂部採用紅色圓形代替,樹幹用棕色方塊代替即可,最後在適當潤色一下。

聖誕節來了,教你用各種程式語言手寫一棵聖誕樹

當然還有另外一種實現方式,是一種動態的效果。

聖誕節來了,教你用各種程式語言手寫一棵聖誕樹

下面是原始碼:

from turtle import *
import random
import time

n = 80.0

speed("fastest")
screensize(bg='seashell')
left(90)
forward(3*n)
color("orange", "yellow")
begin_fill()
left(126)

for i in range(5):
    forward(n/5)
    right(144)
    forward(n/5)
    left(72)
end_fill()
right(126)

color("dark green")
backward(n*4.8)
def tree(d, s):
    if d <= 0: return
    forward(s)
    tree(d-1, s*.8)
    right(120)
    tree(d-3, s*.5)
    right(120)
    tree(d-3, s*.5)
    right(120)
    backward(s)
tree(15, n)
backward(n/2)

for i in range(200):
    a = 200 - 400 * random.random()
    b = 10 - 20 * random.random()
    up()
    forward(b)
    left(90)
    forward(a)
    down()
    if random.randint(0, 1) == 0:
            color('tomato')
    else:
        color('wheat')
    circle(2)
    up()
    backward(a)
    right(90)
    backward(b)
time.sleep(60)

JAVA

這款JAVA版本的聖誕樹和前面Python版本類似,不同的地方在於此版本引用的較多的素材和動態效果,在點選了左上角的按鈕為ON之後開始播放音樂,聖誕樹也開始閃爍變化。

聖誕節來了,教你用各種程式語言手寫一棵聖誕樹

這裡放出作者的github連結,作者為[codeXiaoMing]:

https://github.com/codeXiaoMing/christmasTree/tree/master

大家學會了嗎?快去編譯打包一下發給朋友吧!

往期推薦:

上手世界上最小的作業系統MenuetOS,僅有1.4M,安裝執行全教程

Windows系統被養蠱,這些下“崽”器簡直神了

分類: 歷史
時間: 2021-12-23

相關文章

東南西北四大“京”,北京和南京世人皆知,東京和西京去了哪裡

東南西北四大“京”,北京和南京世人皆知,東京和西京去了哪裡
東南西北四大"京",北京和南京世人皆知,東京和西京去了哪裡 中國有660多座城市,每座城市都有自己的名字,在歷史上的長河中很多城市都改了名字,比如說合肥,歷史上合肥曾叫廬州,再比如 ...

詩詞 | 世人皆知傳奇一生的李清照,卻不知一代才女商景蘭

詩詞 | 世人皆知傳奇一生的李清照,卻不知一代才女商景蘭
歡迎大家閱讀"景德鎮南河公安"頭條號.如果您喜歡本頭條號釋出的文章,還可點選左上角關注我的頭條號,每天都有精彩文章推薦. 1 人生實苦,唯有自渡 她出身名門,精通文墨,俊慧靈秀,卻 ...

世人皆知“負荊請罪”,卻不知長平之戰後,廉頗和藺相如是何結局

世人皆知“負荊請罪”,卻不知長平之戰後,廉頗和藺相如是何結局
<史記>曾言:"廉頗聞之,肉袒負荊."亂世之中,群雄迭起,四方英雄齊登場.春秋戰國之際,負荊請罪傳為佳話,致廉頗及藺相如家喻戶曉,留名青史. 在中華傳統文化中,有著許多 ...

甲午海戰,方伯謙被問罪是冤還是不冤(一)
甲午中日海戰,被歷史所銘記,歷史中有民族英雄鄧世昌,也有臨陣脫逃者方伯謙.鄧世昌一直被人們廣為傳頌,可是方伯謙被冠以可恥的臨陣脫逃者這個頭銜兒,卻傳出了不同的聲音.有的人認為方伯謙,並不是臨陣脫逃,而 ...

忠貞不渝的張學友,和他人盡皆知的紅顏知己

忠貞不渝的張學友,和他人盡皆知的紅顏知己
歌神張學友,在事業如日中天的時候,選擇迎娶女星羅美薇.英年早婚之後,張學友事業家庭兩不誤,這讓他在四大天王中,多多少少都顯得有些"異類". 對待感情能拿到滿分,張學友跟其他三位天王 ...

甲午海戰,丁汝昌殉國本是民族英雄,為何清廷卻聲討他不讓下葬?

甲午海戰,丁汝昌殉國本是民族英雄,為何清廷卻聲討他不讓下葬?
甲午海戰,丁汝昌殉國本是民族英雄,為何清廷卻聲討他不讓下葬? 清朝海軍的實力曾是亞洲第一.世界第九,想不到吧,然而甲午海戰中卻慘敗給日本,讓北洋水師全軍覆沒,海軍也從此沒落. 在這場海戰中,有很多可歌 ...

石縫裡一種“白人參”,路過不留意當雜草,少有人知具體珍貴价值

石縫裡一種“白人參”,路過不留意當雜草,少有人知具體珍貴价值
其實在家居生活中的很多花卉植物,也許放到野外讓它們自由生長,過一段時間之後再去看,也將會同化為野花野草之流的植物,所以大家平時可別嫌棄阿野給大家介紹的野草,基本上每種植物,只要用心呵護都能夠作為一種家 ...

江蘇低調古鎮,5A級景區擁有4000年曆史,少有人知仍保留原始風貌

江蘇低調古鎮,5A級景區擁有4000年曆史,少有人知仍保留原始風貌
有一些景區的景色是非常不錯的,但是名氣卻並不是很高,知道這個些景區的人好像並不是很多,所以景區內的客流量比較少,看起來有點荒涼.這樣景色秀麗的景區名氣不大會被大家稱為是低調的景區. 今天就給大家介紹江 ...

甲午海戰,中國賠償日本白銀2億兩相當於現在多少錢?

甲午海戰,中國賠償日本白銀2億兩相當於現在多少錢?
近日,日本開啟了28年來最大軍演,投入10萬兵力,演習干預釣魚島或臺灣"事變",是針對中國的嚴重挑釁,對此絕不應該手軟. 1894年9月17日,日海軍在黃海北部大東溝海域挑釁清海軍 ...

許三觀賣血記 血水供養兒女 只嘆世人皆苦

許三觀賣血記 血水供養兒女 只嘆世人皆苦
這一天,許三觀走在街上,他頭髮白了,牙齒掉了七顆,不過他眼睛很好,眼睛看東西還像過去一樣清楚,耳朵也很好,耳朵可以聽得很遠. 這時的許三觀已是年過六十了,他的兩個兒子一樂和二樂,在八年前和六年前已經抽 ...

魅族18Spro和vivoX70Pro對比,該買哪個,一看皆知
如果非要在這兩款手機中選擇一款手機進行購買,我個人是更加傾向於魅族18Spro這款手機會更多一些的.我給到的理由有以下幾點,大家不妨參考一下. 理由一:首先魅族18Spro這款手機的效能是會比vivo ...

塞翁失馬,焉知非福,這句話對人有誤導,可謂說理不清,講理不準

塞翁失馬,焉知非福,這句話對人有誤導,可謂說理不清,講理不準
上文講到胡大媽以運動(晨練)和遊戲(打麻將)的方式來排解憂抑,這個系列故事告一段落.胡大媽的方法必然會有效果的,但必然會出現新的問題.這個必然性讓我想起了一個成語,塞翁失馬,焉知非福.這個成語本來要講 ...

甘肅少有人知的避暑仙境,被稱隴右第一名山,夏季最高氣溫僅18度

甘肅少有人知的避暑仙境,被稱隴右第一名山,夏季最高氣溫僅18度
近些年,出於我們國家的社會經濟的持續發展,導致我們個人的日常生活也由此發生改變,旅遊具有代表性的一個方面,今天的旅遊在人們生活中扮演著重要角色,因為旅遊的過程中,我們可以把自己的壓力釋放出來,放鬆身心 ...

5個少有人知的免費實用軟體

5個少有人知的免費實用軟體
1.Qdown 此前分享了一款除了迅雷外比較好用的免費下載工具[Xdown],獲得了不少網友的好評.今天繼續分享一款完全免費的下載工具[Qdown]可以作為補充,它是基於 aria2 集成了 Aria ...

劉邦一生作詩2首,皆為千古絕唱,乾隆4萬首,僅一首入選小學課本

劉邦一生作詩2首,皆為千古絕唱,乾隆4萬首,僅一首入選小學課本
我們現在家長給孩子起名字,時常會看到一個字--"贇",這個字的寓意很好,首先這個孩子是我們的寶貝,其次希望他以後"能文能武",也就是希望他不僅要讀書好還要體格好 ...

呂碧城張愛玲孤老終生,蕭紅石評梅含恨而終,民國才女為何皆薄命
所謂"自古紅顏多薄命"之說,從來都不是空穴來風,如若不信,請將視線轉移到民國,看一看民國時的薄命女. 至於阮玲玉.周璇這些大美人的故事,世人怕是已經聽厭了,還有一類女子,她們雖算不 ...

一個人真正的成熟,從三次離別開始

一個人真正的成熟,從三次離別開始
作者:洞見RDJ 凡事在成熟之前,都是有苦味的. 聽過這樣一件事. 早年有人給陳忠實介紹了一份很多人夢寐以求的好差事. 當時陳忠實正處於創作期,想全心全意寫<白鹿原>,便婉言推辭. 陳忠實 ...

明清傳奇:書生寺廟遇道士,道士賞賜書生一位前朝皇后

明清傳奇:書生寺廟遇道士,道士賞賜書生一位前朝皇后
清朝初年,福建書生林士樾客居在京城,住在城外的一座破廟中. 有一天寺廟裡來了箇中年道人,住在林士樾對面的廂房.道人對林士樾態度冷淡,兩人基本無話可談. 一天晚上,月向別時圓,勾起林士樾的陣陣思鄉之情. ...

甘肅武威,有多“威武”?

甘肅武威,有多“威武”?
▲ 一條蜿蜒的公路通向武威,勾畫出"絲路門戶"的前世今生.圖/視覺中國 -風物君語- 河西心臟,絲路咽喉 一面銅奔馬,一面涼州詞 茫茫戈壁的河西走廊,最先誕生的"四胞胎城 ...

蘇軾因想念分別多年的弟弟,寫下了一首中秋詞,竟成了千古名篇

蘇軾因想念分別多年的弟弟,寫下了一首中秋詞,竟成了千古名篇
"古來聖賢皆寂寞,惟有飲者留其名."自古以來,中國不僅是詩的國度,更是酒的故鄉. 不知從何時起,酒與詩便結下了不解之緣.感覺我國哪個時代都有好酒之文人墨客.遷客騷人,所以我們在翻閱 ...