1

我需要编写一个程序来制作七段显示。它将像这样工作:

def numbers(number, width):
  # Code to make number

典型的输出可能如下所示:

numbers(100, 2)

    --   -- 
 | |  | |  |
 | |  | |  |

 | |  | |  |
 | |  | |  |
    --   --

numbers(24, 1)

 -  
  | | |
 -   -
|     |
 -

numbers(1234567890, 1)

   -   -       -   -   -   -   -   - 
|   |   | | | |   |     | | | | | | |
   -   -   -   -   -       -   -     
| |     |   |   | | |   | | |   | | |
   -   -       -   -       -   -   - 

numbers(8453, 3)

 ---         ---   --- 
|   | |   | |         |
|   | |   | |         |
|   | |   | |         |
 ---   ---   ---   --- 
|   |     |     |     |
|   |     |     |     |
|   |     |     |     |
 ---         ---   --- 

无论如何,这些只是一些示例(请注意,输入需要很长时间)。我知道我可以使用诸如此类的东西'-' * number,但这只是令人沮丧,因为我无法弄清楚!我觉得我应该使用类或其他东西,但我不能完全确定它。

谢谢你。

4

4 回答 4

3

不要尝试以编程方式生成段。手动输入它们,但通常采用编码方式。这种编码应该允许您产生不同的输出。 对这些进行编程。

请考虑以下代码

class SSDigit(object):
    """A 7-segment digit"""
    def __init__(self):
        self.lines= []

ssdig0= SSDigit()
ssdig1.lines.append("     ")
ssdig0.lines.append("  -  ")
ssdig0.lines.append(" | | ")
ssdig0.lines.append("     ")
ssdig0.lines.append(" | | ")
ssdig0.lines.append("  -  ")
ssdig1.lines.append("     ")

ssdig1= SSDigit()
ssdig1.lines.append("     ")
ssdig1.lines.append("     ")
ssdig1.lines.append("   | ")
ssdig1.lines.append("     ")
ssdig1.lines.append("   | ")
ssdig1.lines.append("     ")
ssdig1.lines.append("     ")

.....

class LineType(object):
    """Each of the 2 line types (1 horizontal segment or 2 vertical),
       with their possible representations and segment positions"""
    def __init__(self):
        self.valueForRepr= {}
        self.segmentPos= []

class Line(object):
    """Each of the 5 lines a SSDigit has, with its LineType"""
    def __init__(self):
        self.type= None

digits= [ ssdig0, ssdig1, ssdig2, ssdig3, ssdig4, ssdig5, ssdig6, ssdig7, ssdig8, ssdig9 ]

linetype1= LineType()
linetype1.valueForRepr["     "]= [0]
linetype1.valueForRepr["  -  "]= [1]
linetype1.segmentPos= [3]

linetype2= LineType()
linetype2.valueForRepr["     "]= [0,0]
linetype2.valueForRepr["   | "]= [0,1]
linetype2.valueForRepr[" |   "]= [1,0]
linetype2.valueForRepr[" | | "]= [1,1]
linetype2.segmentPos= [2,4]

typeforline= [ linetype1, linetype2, linetype1, linetype2, linetype1 ]

# Validate error-prone typing !!!
for digit in digits :
    for linenum, linetype in enumerate(typeforline) :
        if digit.lines[linenum] not in linetype.valueForRepr :
            print("Error in digit {:d}, line {:d}".format(digit,linenum))

def printNumber(num):
    num= str(num)
    for linenum, linetype in enumerate(typeforline) :
        line= ""
        for d in num :
            line+= digits[int(d)].lines[linenum]
        print( line )

printNumber(3475649560458)

为每个输入的字符串SSDigit只是规范表示。它的结构只是为了便于开发人员可视化。产生不同尺寸和形式所需的信息通过这些表示和其他结构进行编码。

例如,

def printNumberDoubleSize(num):
    num= str(num)
    for linenum, linetype in enumerate(typeforline) :
        line= ""
        for d in num :
            line+= digits[int(d)].lines[linenum]
        print( line )

printNumberDoubleSize(3475649560458)

下一步是意识到,考虑到间距,显示器由一个 7x5 矩阵组成:

  01234
0   
1   -
2  | |
3   -
4  | |
5   -
6

并且矩阵中的每一行和每一列都是逻辑行,即可以由多个物理行和/或列组成,例如:

   012   34
   00012300 
00   
10   ----
20  |    |
 1  |    |
30   ----
40  |    |
 1  |    |
50   ----
60

这里,大多数逻辑行和列分别仅由一个物理行和列组成,除了逻辑行 2 和 4(各有 2 个物理行)和逻辑列 2,有 4 个物理列。

这可以表示为一系列字符串。并且可以非常方便地为每个元素表达我们希望在关闭和打开状态下看到它的方式。在以下定义中,我只是为了示例而沉迷于一些艺术自由:

phyLineN= []
phyLineN.append([])
phyLineN[0]= []
phyLineN[0].append([ "....", ".", "....",".", "...." ])
phyLineN.append([])
phyLineN[1]= []
phyLineN[1].append([ ".   ", " ", ". . "," ", "    " ])
phyLineN.append([])
phyLineN[2]= []
phyLineN[2].append([ ".   ", ".", "    ",".", "    " ])
phyLineN[2].append([ ".   ", " ", "    "," ", "    " ])
phyLineN.append([])
phyLineN[3]= []
phyLineN[3].append([ ".   ", " ", ". . "," ", "    " ])
phyLineN.append([])
phyLineN[4]= []
phyLineN[4].append([ ".   ", ".", "    ",".", "    " ])
phyLineN[4].append([ ".   ", " ", "    "," ", "    " ])
phyLineN.append([])
phyLineN[5]= []
phyLineN[5].append([ ".   ", " ", ". . "," ", "    " ])
phyLineN.append([])
phyLineN[6]= []
phyLineN[6].append([ "....", ".", "....",".", "...." ])

phyLineY= []
phyLineY.append([])
phyLineY[0]= []
phyLineY[0].append([ "    ", " ", "    "," ", "    " ])
phyLineY.append([])
phyLineY[1]= []
phyLineY[1].append([ "    ", " ", "===="," ", "    " ])
phyLineY.append([])
phyLineY[2]= []
phyLineY[2].append([ "    ", "H", "    ","H", "    " ])
phyLineY[2].append([ "    ", "H", "    ","H", "    " ])
phyLineY.append([])
phyLineY[3]= []
phyLineY[3].append([ "    ", " ", "===="," ", "    " ])
phyLineY.append([])
phyLineY[4]= []
phyLineY[4].append([ "    ", "H", "    ","H", "    " ])
phyLineY[4].append([ "    ", "H", "    ","H", "    " ])
phyLineY.append([])
phyLineY[5]= []
phyLineY[5].append([ "    ", " ", "===="," ", "    " ])
phyLineY.append([])
phyLineY[6]= []
phyLineY[6].append([ "    ", " ", "    "," ", "    " ])

def printNumberNY(num,structN,structY):

    phyRowH= [ len(structN[0]), len(structN[1]), len(structN[2]), len(structN[3]), len(structN[4]), len(structN[5]), len(structN[6]) ]

    # Validate structure and compute phyColW
    # This could be moved to an object constructor so is computed only once
    first= 1
    for line in structN :
        for phyLine in line :
            if first :
                phyColW= [ len(phyLine[0]), len(phyLine[1]), len(phyLine[2]), len(phyLine[3]), len(phyLine[4]) ] 
                first= 0
            else:
                for i, _ in enumerate(phyLine) :
                    if len(phyLine[i]) != phyColW[i] : raise "Inconsistent physical column width"

    # Real rendering of the (full) number in 7-segment form
    num= str(num)
    for linenum, linetype in enumerate(typeforline) :
        for phyLine in range(phyRowH[linenum]) :
            line= ""
            for d in num :
                for col, qq in enumerate(phyColW) :
                    if digits[int(d)].lines[linenum][col] != " " :
                        line+= structY[linenum][phyLine][col]
                    else:
                        line+= structN[linenum][phyLine][col]
            print( line )

printNumberNY(3475649560458,phyLineN,phyLineY)

的代码printNumberNY并不比宽度*n 的简单情况的代码难多少。

width*n 的情况实际上是这种设置的一种特殊情况,可以用以下方式构造:

def sizeVH(vSegHeight,hSegWidth,vSep,hSep):

    hSepStr= " " *hSep
    hSegN= " "* hSegWidth 
    hSegY= "-"* hSegWidth

    phyLineN= []
    phyLineN.append([])
    phyLineN[0]= []
    phyLineN.append([])
    phyLineN[1]= []
    phyLineN[1].append([ "", " ", hSegN," ", hSepStr ])
    phyLineN.append([])
    phyLineN[2]= []
    for i in range(vSegHeight) :
        phyLineN[2].append([ "", " ", hSegN," ", hSepStr ])
    phyLineN.append([])
    phyLineN[3]= []
    phyLineN[3].append([ "", " ", hSegN," ", hSepStr ])
    phyLineN.append([])
    phyLineN[4]= []
    for i in range(vSegHeight) :
        phyLineN[4].append([ "", " ", hSegN," ", hSepStr ])
    phyLineN.append([])
    phyLineN[5]= []
    phyLineN[5].append([ "", " ", hSegN," ", hSepStr ])
    phyLineN.append([])
    phyLineN[6]= []
    for i in range(vSep) :
        phyLineN[6].append([ "", " ", hSegN," ", hSepStr ])

    phyLineY= []
    phyLineY.append([])
    phyLineY[0]= []
    phyLineY.append([])
    phyLineY[1]= []
    phyLineY[1].append([ "", " ", hSegY," ", hSepStr ])
    phyLineY.append([])
    phyLineY[2]= []
    for i in range(vSegHeight) :
        phyLineY[2].append([ "", "|", hSegN,"|", hSepStr ])
    phyLineY.append([])
    phyLineY[3]= []
    phyLineY[3].append([ "", " ", hSegY," ", hSepStr ])
    phyLineY.append([])
    phyLineY[4]= []
    for i in range(vSegHeight) :
        phyLineY[4].append([ "", "|", hSegN,"|", hSepStr ])
    phyLineY.append([])
    phyLineY[5]= []
    phyLineY[5].append([ "", " ", hSegY," ", hSepStr ])
    phyLineY.append([])
    phyLineY[6]= []
    for i in range(vSep) :
        phyLineY[6].append([ "", " ", hSegN," ", hSepStr ])

    return (phyLineN,phyLineY)

phyLineN, phyLineY= sizeVH(4,6,1,3)
printNumberNY(3475649560458,phyLineN,phyLineY)

我知道我没有使用我一开始定义的一些元素,但这就是我建模它的方式。如果我们继续扩展解决方案,它们可能会很有用。

于 2013-08-25T02:12:56.700 回答
1

哈哈,多么有趣的问题!

DISP = 7
#  1
#2   3
#  4
#5   6
#  7

def digit(cur, size = 5, ch = '*'):
    def draw(led_code):    
        for a, b, c in led_code:
            if a:
                print ' ' + ch * size + ' '
            if b and c:
                print (ch + ' ' * size + ch + '\n') * size
                continue

            if b:
                print (ch + ' ' * size + ' ' + '\n') * size
            if c:
                print (' ' + ' ' * size + ch + '\n') * size
    digits = {
        1 : [(0,0,1),(0,0,1),(0,0,0)],
        0 : [(1,1,1),(0,1,1),(1,0,0)]
    }

    draw(digits.get(cur, digits[1]))
    print


for x in bin(42).split('b')[1]:
    digit(int(x))
于 2013-08-25T02:41:00.520 回答
1

我会把它当作一个有趣的练习(也许我的解决方案会给你一些想法):

from collections import defaultdict

class Cell:
    def __init__ (self, width = 4, height = 2, hChar = '*', vChar = '*'):
        self.width = width
        self.height = height
        self.hChar = hChar
        self.vChar = vChar

    def showSegments (self, segments):
        def char (segment):
            if segment not in segments: return ' '
            return self.hChar if segment in (0, 3, 6) else self.vChar
        lines = []
        lines.append (' ' + char (0) * self.width + ' ')
        for _ in range (self.height):
            lines.append (char (1) + ' ' * self.width + char (2) )
        lines.append (' ' + char (3) * self.width + ' ')
        for _ in range (self.height):
            lines.append (char (4) + ' ' * self.width + char (5) )
        lines.append (' ' + char (6) * self.width + ' ')
        return lines

class Display:
    def __init__ (self, encoding, cells, padding = 1, width = 4, height = 2, hChar = '*', vChar = '*'):
        self.encoding = encoding
        self.padding = padding
        self.cells = [Cell (width, height, hChar, vChar) for _ in range (cells) ]

    def show (self, string):
        cellLines = []
        for idx, c in enumerate (string):
            if idx >= len (self.cells): break
            cellLines.append (self.cells [idx].showSegments (self.encoding [c] ) )
        if not cellLines: return
        cellLines = zip (*cellLines)
        print ('\n'.join ( (' ' * self.padding).join (line) for line in cellLines) )

encoding = defaultdict (lambda: {} )
encoding ['0'] = {0, 1, 2, 4, 5, 6}
encoding ['1'] = {2, 5}
encoding ['2'] = {0, 2, 3, 4, 6}
encoding ['3'] = {0, 2, 3, 5, 6}

d = Display (encoding, 5, 2)
d.show ('12301')
于 2013-08-25T03:28:17.500 回答
0

我认为这里的解决方案是从小处着手,然后继续前进,直到整个程序完成。

首先编写一个可以绘制单个数字的函数,例如 ,drawTwo()它可以绘制第二个数字。弄清楚这一点后,将其重构为drawTwo(width),它会绘制具有正确宽度的数字。现在你已经弄清楚了,为每个数字 0 到 10 写一个应该不会太难。

拥有十个函数后,编写一个函数,将输入的数字拆分为数字,并为每个数字调用正确的函数(可能使用 switch 语句)。

一步一步来。

于 2013-08-25T02:18:50.593 回答