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

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

 

首先简介下题目:

 

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

 

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

 

例:

 

输入:145

 

输出:

         __

   ||__||__

   |   | __|

看到这个题目,也没多想,反正就是把这些数字打出来而已,那就一行一行打呗 于是在纸上画了几个计算器表示形式的数字: 规律是很明显的,每个数字都由3行4列组成,每一行只有固定的几种样式,比如说8的第一行是" __ ",第二行是"|__|",第三行是"|__|" 于是就有了思路:只要一位一位的读取这个数字,然后按照上中下的顺序依次打印其计算器表示的三行就行了。 由于每个数字的每一行的样式都是固定的,很容易将这些样式抽取出来,经过观察,我找出了其所有的样式,于是就有了如下的代码:
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

    }

}

接下来的问题就是依次获取一个数的每一位,通过一个递归,很容易实现这个功能:
    public void PrintNum(int value)

    {

        if (value != 0)

        {

            PrintNum(value / 10, layer);

            Console.Write(value % 10);

        }

    }

测试这个方法之后,接下来的工作就是一行一行的打印数值了,按照之前的思路,我把每个数字分为上中下三层,于是可以这么写:
    public void PrintNum(int value)

    {

        PrintTopBody(value);

        Console.WriteLine();

        PrintMiddleBody(value);

        Console.WriteLine();

        PrintBottomBody(value);

        Console.WriteLine();

    }

然后逐个实现每个方法,为了确保这个思路是正确的,先不用考虑所有的数字,只考虑数字1这个情况
    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作为输入进行测试,发现结果是正确的。 接下来就可以完善这三个方法了,经过一段时间的编码和测试,我完成了这道题目。其功能代码如下
    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这三个方法,使得逻辑很简单的一个程序却很难看懂。

 

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

你可能感兴趣的:(编程)