问题
8.[S.C.Johnnson]七段显示设备实现十进制数字:
的廉价显示。七段显示通常如下编号:
编写一个使用5个七段显示数字来显示16位正整数的程序。输出为一个5个字节的数组,当且仅当数字j中的第i段点亮时,字节j中的位i置1
分析
简单翻译一下题目的意思,编写一个程序,实现给定一个数字,包含5位,在终端输出图像
举个例子,向程序输入82367,在终端显示
这题需要解决的核心问题时,如何将数转换为图像(二维数组)
举个例子
这是7段显示的编码,如果我们提前知道所有数对应的编码,同时知道编码对应二维数组的坐标。那么我们就可以通过数转换为编码,编码对应坐标,最后根据坐标进行可视化
现在,我们拥有一个7 x 4的二维数组,如果我们要绘制8,如上图所示,8对应的七段编码为[0, 1, 2, 3, 4, 5, 6, 7]
以编码0为例子,0对应7 x 4的二维数组的坐标是:(6, 1), (6, 2)。以此类推,获取剩下编码对应的坐标,即可将数字转换为二维数组的坐标。然后在数组中填充对应的内容,最后就完成了对应过程
代码
为了程序可维护性,做了一些抽象。
Rule是规则类,定义了一些列规则
- 一个七段显示,对应数组的维度
- 每个七段显示之间的间隔
- 每个数字对应的编号
- 编号对应的坐标
Number是数字类,用于维护一个0~9之间数字与二维数组之间的转换
Display是显示屏类,用于集中维护5个7段显示,并打印数字
代码
from typing import List
'''
定义规则
'''
class Rule:
# 七段显示数字的数组维度
number_row = 7
number_col = 4
# 5个七段显示数字之间的间隔
interval = 2
const = {
'horizon': '-',
'vertical': '|',
}
def __init__(self):
# 七段显示的编号坐标
self.id_pos = {
0: [(6, 1, Rule.const['horizon']), (6, 2, Rule.const['horizon'])]
, 1: [(3, 1, Rule.const['horizon']), (3, 2, Rule.const['horizon'])]
, 2: [(0, 1, Rule.const['horizon']), (0, 2, Rule.const['horizon'])]
, 3: [(1, 0, Rule.const['vertical']), (2, 0, Rule.const['vertical'])]
, 4: [(1, 3, Rule.const['vertical']), (2, 3, Rule.const['vertical'])]
, 5: [(4, 0, Rule.const['vertical']), (5, 0, Rule.const['vertical'])]
, 6: [(4, 3, Rule.const['vertical']), (5, 3, Rule.const['vertical'])]
}
# 数字通过七段显示展示时, 需要的七段显示编号
self.number_ids = {
0: [x for x in range(7) if x not in (1,)]
, 1: [4, 6]
, 2: [x for x in range(7) if x not in (3, 6)]
, 3: [x for x in range(7) if x not in (3, 5)]
, 4: [x for x in range(7) if x not in (2, 5)]
, 5: [x for x in range(7) if x not in (4, 5)]
, 6: [x for x in range(7) if x not in (4,)]
, 7: [x for x in range(7) if x not in (1, 3, 5, 0)]
, 8: range(7)
, 9: [x for x in range(7) if x not in (0, 5)]
}
class Number:
def __init__(self, number: int):
self.rule = Rule()
self.number = number
def set_number(self, number):
self.number = number
'''
将0-9中的数字转换为图像(二维数组)
'''
def gen_graphic(self) -> List[List]:
# 获取数字对应7段显示的编号
ids = self.rule.number_ids[self.number]
graphic = [[' ' for _ in range(Rule.number_col)] for _ in range(Rule.number_row)]
# 遍历所有编号, 获取编号对应的坐标集合
for id in ids:
# (x, y) -> 数组坐标; w -> 数组需要填充的字符内容
for x, y, w in self.rule.id_pos[id]:
graphic[x][y] = w
return graphic
class Display:
def __init__(self):
# 5个7段显示需要的数组维度
self.graphic = [[' ' for _ in range(5 * Rule.number_col + 4 * Rule.interval)] for _ in range(Rule.number_row)]
# 5个7段显示
self.number_list = [Number(i) for i in range(5)]
'''
图像归位
'''
def clear(self):
self.graphic = [[' ' for _ in range(5 * Rule.number_col + 4 * Rule.interval)] for _ in range(Rule.number_row)]
'''
显示数字
'''
def display(self, number: int):
self.clear()
self.reader(number)
self.writer()
'''
读取需要显示的数字
'''
def reader(self, number: int):
params = []
while number != 0:
params.append(number % 10)
number //= 10
size = len(params)
for _ in range(size, 5):
params.append(0)
params.reverse()
# 赋值不同的数字
for idx, n in enumerate(self.number_list):
n.set_number(params[idx])
'''
赋值graphic, 打印图像
'''
def writer(self):
for idx, n in enumerate(self.number_list):
# 数组拷贝, 将5个七段显示绘制的二维数组拷贝到display中的数组
new_gra = n.gen_graphic()
for i in range(len(new_gra)):
# col_len需要考虑每个七段显示之间的间隔
col_len = Rule.number_col + Rule.interval
self.graphic[i][idx * col_len: (idx + 1) * col_len] = new_gra[i]
# 绘图
for row in self.graphic:
for r in row:
print(r, end='')
print()
测试
display = Display()
print(82367)
display.display(82367)
print(12345)
display.display(12345)
print(53245)
display.display(53245)