(圣诞礼物)在终端下画个圣诞树陪你过节

写在前面

圣诞节快乐,老早之前看过一个老外闲得蛋疼,用 Perl 在终端上画了一个圣诞树,这不瞅着时间刚好圣诞节嘛,用我们的大 Python 画了一个。下文会讲讲怎么画出这么个东西出来。

来来来,先上图, duang ~

怎么样,酷不酷,我是多寂寞的程序员啊。

好了,懂的人自然懂是什么原理,不懂的,来来来,我给你讲讲你就懂了。

原理

其实就是趁你不注意的时候,把终端清屏,然后画一个图,然后再趁你一不留神,又清屏,又画一张图。啊,就这么简单。

当然,windows 下是 cls, 类 Unix 下是 clear, 于是这里要注意一下。

至于颜色嘛,终端的字符颜色是用转义序列控制的,是文本模式下的系统显示功能,和具体的语言无关。转义序列是以 ESC 开头,可以用 \033 完成相同的工作(ESC 的 ASCII 码用十进制表 示就是 27, = 用八进制表示的 33)。

1
\033[显示方式;前景色;背景色m

就是这个样子

显示方式:0(默认值)、1(高亮)、22(非粗体)、4(下划线)、24(非下划线)、 5(闪烁)、25(非闪烁)、7(反显)、27(非反显)

前景色:30(黑色)、31(红色)、32(绿色)、 33(黄色)、34(蓝色)、35(洋 红)、36(青色)、37(白色)

背景色:40(黑色)、41(红色)、42(绿色)、 43(黄色)、44(蓝色)、45(洋 红)、46(青色)、47(白色)

比如我们要输出一个红色的字符串:

1
print "\033[1;31;40m%s\033[0m" % " 输出红色字符"

哦,对了,一定要注意后面要恢复成默认颜色,你可以试试不恢复的话是什么情况,哈哈哈,就不告诉你,自己实践一把就懂了。

好了,直接看代码吧。

Python 源代码

先上源代码。后面再说分析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env python
# coding:utf-8
import os
import sys
import platform
import random
import time


class UI(object):
def __init__(self):
os_name = platform.uname()[0]
self.IS_WIN = os_name == 'Windows'
self.IS_MAC = os_name == 'Darwin'
if self.IS_WIN:
self.RED = 0x0C
self.GREY = 0x07
self.BLUE = 0x09
self.CYAN = 0x0B
self.LINK = 0x30
self.BLACK = 0x0
self.GREEN = 0x0A
self.WHITE = 0x0F
self.PURPLE = 0x0D
self.YELLOW = 0x0E
else:
self.RED = '\033[1;31m'
self.GREY = '\033[38m'
self.BLUE = '\033[1;34m'
self.CYAN = '\033[36m'
self.LINK = '\033[0;36;4m'
self.BLACK = '\033[0m'
self.GREEN = '\033[32m'
self.WHITE = '\033[37m'
self.PURPLE = '\033[35m'
self.YELLOW = '\033[33m'
self.p = self.win_print if self.IS_WIN else self.os_print

def clear(self):
os.system('cls' if self.IS_WIN else 'clear')
return self

def win_reset(self, color):
from ctypes import windll
handler = windll.kernel32.GetStdHandle(-11)
return windll.kernel32.SetConsoleTextAttribute(handler, color)

def win_print(self, msg, color, enter=True):
color = color or self.BLACK
self.win_reset(color | color | color)
sys.stdout.write(('%s\n' if enter else '%s') % msg)
self.win_reset(self.RED | self.GREEN | self.BLUE)
return self

def os_print(self, msg, color, enter=True):
color = color or self.BLACK
sys.stdout.write(
('%s%s%s\n' if enter else '%s%s%s') % (color, msg, self.BLACK))
return self


def tree(ui, level=3):
a = range(0, (level + 1) * 4, 2)
b = a[0:2]
for i in range(2, len(a) - 2, 2):
b.append(a[i])
b.append(a[i + 1])
b.append(a[i])
b.append(a[i + 1])
b.append(a[-2])
b.append(a[-1])
light = True
while True:
ui.clear()
ui.p(u'\t圣诞节快乐!\n\t\t\tMedici.Yan 2015', ui.RED)
print
light = not light
lamp(ui, b, light)
for i in range(2, len(b)):
ui.p(
'%s/' % (' ' * b[len(b) - i - 1]), ui.GREEN, enter=False)
neon(ui, 2 * b[i] + 1)
ui.p('\\', ui.GREEN, enter=True)
time.sleep(1.2)


def neon(ui, space_len):
colors = [ui.RED, ui.GREY, ui.BLUE, ui.CYAN, ui.YELLOW]
for i in range(space_len):
if random.randint(0, 16) == 5:
ui.p('o', colors[random.randint(0, len(colors) - 1)], enter=False)
else:
ui.p(' ', ui.RED, enter=False)


def lamp(ui, tree_arr, light):
colors = [ui.WHITE, ui.BLUE]
if not light:
colors.reverse()
ui.p(' ' * (tree_arr[-1] + 1), ui.BLACK, enter=False)
ui.p('|', colors[1])
ui.p(' ' * tree_arr[-1], ui.BLACK, enter=False)
ui.p('\\', colors[1], enter=False)
ui.p('|', colors[0], enter=False)
ui.p('/', colors[1])
ui.p(' ' * tree_arr[-2], ui.BLACK, enter=False)
ui.p('-', colors[0], enter=False)
ui.p('-', colors[1], enter=False)
ui.p('=', colors[0], enter=False)
ui.p('O', colors[1], enter=False)
ui.p('=', colors[0], enter=False)
ui.p('-', colors[1], enter=False)
ui.p('-', colors[0], enter=True)

ui.p(' ' * tree_arr[-1], ui.BLACK, enter=False)
ui.p('/', colors[1], enter=False)
ui.p('|', colors[0], enter=False)
ui.p('\\', colors[1])
ui.p(' ' * tree_arr[-2], ui.BLACK, enter=False)
ui.p('/ ', ui.GREEN, enter=False)
ui.p('|', colors[1], enter=False)
ui.p(' \\', ui.GREEN, enter=True)


def main():
ui = UI()
max_rows = 4
tree(ui, max_rows)

if __name__ == '__main__':
main()