我认为没有任何内置的 python 可以帮助您解决这个问题。我建议您只寻找一个合适的 ascii 文本库来轻松构建那种类型的 ascii 文本脚本,figlet 是现有的数百个脚本之一。
如果您想自己编写代码,我只需安装 pillow 并使用它来用我想要的形状填充自定义缓冲区,请看下面的 5 分钟示例,该示例“呈现”文本和矩形到这样的缓冲区。请注意,它没有进行越界检查,并且可能很慢……但我想您可以在此基础上开始工作:
from PIL import Image, ImageFont, ImageDraw
class AsciiBuffer():
def __init__(self, width, height):
self.font_size = 15
self.font = ImageFont.truetype('arialbd.ttf', self.font_size)
self.width = width
self.height = height
self.clear()
def clear(self):
self.buffer = [['*' for x in range(self.width)]
for y in range(self.height)]
def draw_text(self, x0, y0, text):
size = self.font.getsize(text)
image = Image.new('1', size, 1)
draw = ImageDraw.Draw(image)
draw.text((0, 0), text, font=self.font)
for y in range(size[1]):
line = []
for x in range(size[0]):
if image.getpixel((x, y)):
self.buffer[y0 + y][x0 + x] = ' '
else:
self.buffer[y0 + y][x0 + x] = '#'
def draw_rectangle(self, x0, y0, w, h, fill=' '):
for y in range(h):
for x in range(w):
self.buffer[y0 + y][x0 + x] = fill
def render(self):
for y in range(self.height):
print(''.join(self.buffer[y]))
if __name__ == "__main__":
k = 20
ab = AsciiBuffer(k * 3 + 4, k * 3 + 4)
n = 1
for i in range(3):
for j in range(3):
x = 1 + (k + 1) * i
y = 1 + (k + 1) * j
ab.draw_rectangle(x, y, k, k)
ab.draw_text(x + int(k / 4), y, str(n))
n += 1
ab.render()
输出:
重构:
无论如何,上面的代码有很多问题,其中之一是 AsciiBuffer 类与 PIL 耦合,当这个类应该尽可能虚拟时,例如,只绘制“文本精灵”就可以了,所以这里有一点重构,我将向您展示如何从多行字符串(例如您在问题中发布的字符串)或从 PIL 呈现的某些系统字体生成“文本精灵”:
import sys
from PIL import Image, ImageFont, ImageDraw
class SpriteGenerator():
def __init__(self):
pass
def from_multiline_string(self, text, length):
buf = []
for l in text.splitlines():
buf.append(list(l) + [' '] * (length - len(l)))
return buf
def from_pil(self, text, font_name='arialbd.ttf', font_size=15):
font = ImageFont.truetype(font_name, font_size)
size = font.getsize(text)
image = Image.new('1', size, 1)
draw = ImageDraw.Draw(image)
draw.text((0, 0), text, font=font)
buf = []
for y in range(size[1]):
line = []
for x in range(size[0]):
if image.getpixel((x, y)):
line.append(' ')
else:
line.append('#')
buf.append(line)
return buf
class AsciiBuffer():
def __init__(self, width, height):
self.width = width
self.height = height
self.clear()
def clear(self):
self.buffer = [['*' for x in range(self.width)]
for y in range(self.height)]
def draw_sprite(self, x0, y0, sprite):
for y, row in enumerate((sprite)):
for x, pixel in enumerate(row):
self.buffer[y0 + y][x0 + x] = pixel
def draw_rectangle(self, x0, y0, w, h, fill=' '):
for y in range(h):
for x in range(w):
self.buffer[y0 + y][x0 + x] = fill
def render(self):
for y in range(self.height):
print(''.join(self.buffer[y]))
if __name__ == "__main__":
num = """
______
/ ___ \\
\\/ \\ \\
___) /
(___ (
) \\
/\\___/ /
\\______/
"""
k = 15
ab = AsciiBuffer(k * 3 + 4, k * 3 + 4)
sg = SpriteGenerator()
n = 1
for i in range(3):
for j in range(3):
x = 1 + (k + 1) * i
y = 1 + (k + 1) * j
ab.draw_rectangle(x, y, k, k)
if n == 3:
ab.draw_sprite(
x + int(k / 4), y, sg.from_multiline_string(num, 11))
else:
ab.draw_sprite(
x + int(k / 4), y, sg.from_pil(str(n), font_size=k))
n += 1
ab.render()
输出: