Calculator 7 Segment Display w/ Width [closed]

半腔热情 提交于 2019-12-24 14:43:05

问题


I need to write a program to make a seven segment display. It will work like this:

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

A typical output could look something like this:

numbers(100, 2)

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

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

numbers(24, 1)

 -  
  | | |
 -   -
|     |
 -

numbers(1234567890, 1)

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

numbers(8453, 3)

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

Anyway, those are a few examples (which took quite a while to type, mind you). I know I can use things such as '-' * number and such, but it is just frustrating as I cannot figure it out! I feel like I should be using classes or something, but I can't quite put my finger on it.

Thank you.


回答1:


Don't try to produce segments programmatically. Enter them manually, but in a generally encoded way. This encoding should allow you to produce different outputs. Do program these.

Please consider the following code

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)

The strings entered for each SSDigit are just canonical representations. Its structure is only for easy developer visualization. The information required to produce different sizes and forms is encoded through these representations and the other structures.

For example,

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)

Next step is to realize that, allowing for spacing, the display consists of a 7x5 matrix:

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

And that each line and column in the matrix are logical ones, i.e. can consist of several physical lines and/or columns, like in:

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

Here, most logical rows and columns consist of only one physical row and column, respectively, except logical rows 2 and 4 (with 2 physical lines each), and logical column 2, with 4 physical columns.

This can be represented as a series of strings. And it can result very convenient to express for each element how we would like to see it in an off and on state. In the following definitions I indulged in some artistic liberty just for the sake of the example:

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)

The code for printNumberNY is not much more difficult than the one for the simple case of width*n.

The case of width*n is, in fact, a particular case of this setup, and can be constructed with:

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)

I know that I didn't use some of the elements I defined at the beginning, but this is how I would have modeled it. They could be useful if we continue extending the solution.




回答2:


Haha, what a fun problem!

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))



回答3:


I will take this as a fun exercise (and maybe my solution gives you some ideas):

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')



回答4:


I think the solution here is to just start small and work your way forward until the whole program is finished.

First write a function that can draw a single digit, say, drawTwo(), which draws the digit two. Once you have this figured out, refactor this into drawTwo(width), which draws the digit with the right width. Now that you have this figured out, it shouldn't be too hard to write one for each digit zero through ten.

Once you have your ten functions, write a function that splits your input number into its digits and calls the correct function (possibly using a switch statement) for each digit.

Just take it one step at a time.



来源:https://stackoverflow.com/questions/18424973/calculator-7-segment-display-w-width

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!