一个编程小题目引发的思考(上)

一个编程小题目引发的思考

 

首先简介下题目:

 

输入:一个不超过12位的十进制正整数

 

输出:打印此数字的十进制计算器表示

 

例:

 

输入:145

 

输出:
1
2
3
      __
||__||__
|   | __|
看到这个题目,也没多想,反正就是把这些数字打出来而已,那就一行一行打呗 于是在纸上画了几个计算器表示形式的数字: 规律是很明显的,每个数字都由3行4列组成,每一行只有固定的几种样式,比如说8的第一行是" __ ",第二行是"|__|",第三行是"|__|" 于是就有了思路:只要一位一位的读取这个数字,然后按照上中下的顺序依次打印其计算器表示的三行就行了。 由于每个数字的每一行的样式都是固定的,很容易将这些样式抽取出来,经过观察,我找出了其所有的样式,于是就有了如下的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class LCDPrinter
{
    // all the paradigms in the LCD representation
    private static readonly string S0 = "    ";
    private static readonly string S1 = " __ ";
    private static readonly string S2 = "   |";
    private static readonly string S3 = "|   ";
    private static readonly string S4 = " __|";
    private static readonly string S5 = "|__ ";
    private static readonly string S6 = "|__|";
    private static readonly string S7 = "|  |";
    public void PrintNum(int value)
    {
        //TODO: print the number layer by layer
    }
}
接下来的问题就是依次获取一个数的每一位,通过一个递归,很容易实现这个功能:
1
2
3
4
5
6
7
8
public void PrintNum(int value)
{
    if (value != 0)
    {
        PrintNum(value / 10, layer);
        Console.Write(value % 10);
    }
}
测试这个方法之后,接下来的工作就是一行一行的打印数值了,按照之前的思路,我把每个数字分为上中下三层,于是可以这么写:
1
2
3
4
5
6
7
8
9
public void PrintNum(int value)
{
    PrintTopBody(value);
    Console.WriteLine();
    PrintMiddleBody(value);
    Console.WriteLine();
    PrintBottomBody(value);
    Console.WriteLine();
}
然后逐个实现每个方法,为了确保这个思路是正确的,先不用考虑所有的数字,只考虑数字1这个情况
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
private void PrintTopBody(int value)
{
    if (value != 0)
    {
        PrintTopBody(value / 10);
        int num = value % 10;
        switch (num)
        {
            case 1:
                Console.Write(S0);
                break;
            default:
                throw new ArgumentOutOfRangeException();
        }
    }
}
private void PrintMiddleBody(int value)
{
    if (value != 0)
    {
        PrintMiddleBody(value / 10);
        int num = value % 10;
        switch (num)
        {
            case 1:
                Console.Write(S2);
                break;
            default:
                throw new ArgumentOutOfRangeException();
        }
    }
}
private void PrintBottomBody(int value)
{
    if (value != 0)
    {
        PrintBottomBody(value / 10);
        int num = value % 10;
        switch (num)
        {
            case 1:
                Console.Write(S2);
                break;
            default:
                throw new ArgumentOutOfRangeException();
        }
    }
}
然后以1,11,1111作为输入进行测试,发现结果是正确的。 接下来就可以完善这三个方法了,经过一段时间的编码和测试,我完成了这道题目。其功能代码如下
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
class LCDPriter
{
    private static readonly string S0 = "    ";
    private static readonly string S1 = " __ ";
    private static readonly string S2 = "   |";
    private static readonly string S3 = "|   ";
    private static readonly string S4 = " __|";
    private static readonly string S5 = "|__ ";
    private static readonly string S6 = "|__|";
    private static readonly string S7 = "|  |";
    public void PrintNum(int value)
    {
        PrintTopBody(value);
        Console.WriteLine();
        PrintMiddleBody(value);
        Console.WriteLine();
        PrintBottomBody(value);
        Console.WriteLine();
    }
    private void PrintTopBody(int value)
    {
        if (value != 0)
        {
            PrintTopBody(value / 10);
            int num = value % 10;
            switch (num)
            {
                case 0:
                    Console.Write(S1);
                    break;
                case 1:
                    Console.Write(S0);
                    break;
                case 2:
                    Console.Write(S1);
                    break;
                case 3:
                    Console.Write(S1);
                    break;
                case 4:
                    Console.Write(S0);
                    break;
                case 5:
                    Console.Write(S1);
                    break;
                case 6:
                    Console.Write(S1);
                    break;
                case 7:
                    Console.Write(S1);
                    break;
                case 8:
                    Console.Write(S1);
                    break;
                case 9:
                    Console.Write(S1);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
    }
    private void PrintMiddleBody(int value)
    {
        if (value != 0)
        {
            PrintMiddleBody(value / 10);
            int num = value % 10;
            switch (num)
            {
                case 0:
                    Console.Write(S7);
                    break;
                case 1:
                    Console.Write(S2);
                    break;
                case 2:
                    Console.Write(S4);
                    break;
                case 3:
                    Console.Write(S4);
                    break;
                case 4:
                    Console.Write(S6);
                    break;
                case 5:
                    Console.Write(S5);
                    break;
                case 6:
                    Console.Write(S5);
                    break;
                case 7:
                    Console.Write(S2);
                    break;
                case 8:
                    Console.Write(S6);
                    break;
                case 9:
                    Console.Write(S6);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
    }
    private void PrintBottomBody(int value)
    {
        if (value != 0)
        {
            PrintBottomBody(value / 10);
            int num = value % 10;
            switch (num)
            {
                case 0:
                    Console.Write(S6);
                    break;
                case 1:
                    Console.Write(S2);
                    break;
                case 2:
                    Console.Write(S5);
                    break;
                case 3:
                    Console.Write(S4);
                    break;
                case 4:
                    Console.Write(S2);
                    break;
                case 5:
                    Console.Write(S4);
                    break;
                case 6:
                    Console.Write(S6);
                    break;
                case 7:
                    Console.Write(S2);
                    break;
                case 8:
                    Console.Write(S6);
                    break;
                case 9:
                    Console.Write(S4);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
    }
}
虽然这段代码可以工作,但是怎么看怎么别扭,不知所以然的S0到S7这8个全局字符串(本身就不好命名),逻辑极其类似的PrintTopBody,PrintMiddleBody,PrintBottomBody这三个方法,使得逻辑很简单的一个程序却很难看懂。

 

下篇:一个编程小题目引发的思考(下)

posted @   _Luc_  阅读(3087)  评论(6编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示