C#控制台实现倒计时

原文地址:https://www.cnblogs.com/jingjiangtao/p/14766049.html

效果

文章最后有完整代码,以下是逐步实现。

准备工作

要在控制台上绘制出数字,可以将控制台看作一个网格,在网格中填充颜色就可以显示不同的数字。首先在excel中做一个网格来确定大小和坐标:

 

 可以看到,画布大小是 41 x 11,组成每个数字的网格也都标出了坐标,程序中需要绘制数字时只需要参照这个excel网格就行了。

关于如何将excel的表格修改成正方形,可以参考这篇博客:使用Excel在图片上添加正方形网格线_zy_like_study的博客-CSDN博客_图片添加网格线

开始编写代码

创建网格

 新建一个 .net 5 控制台项目。因为功能简单,所以就直接在默认的Program类中用静态函数实现了。

首先要定义一个 41 x 11 的网格用来展示数字。新建一个类 Cell 表示网格中的每一个格子,Value属性表示这个格子是否激活,true为激活,false为未激活。

public class Cell
{
    public bool Value { get; set; }
}

接下来要定义网格,可以用一个二维数组来表示,数组的类型就是上面定义的Cell。将这个二维数组定义为类的静态变量,就可以在类的静态函数中使用。

private static Cell[,] grid = new Cell[11, 41];

定义完成之后需要初始化网格,对二维数组中的类型进行实例化。Init() 函数遍历网格数组,实例化每个格子,并显式将Value设为false

private static void Init()
{
    for (int i = 0; i < grid.GetLength(0); i++)
    {
        for (int j = 0; j < grid.GetLength(1); j++)
        {
            grid[i, j] = new Cell();
            grid[i, j].Value = false;
        }
    }
}

在控制台上显示网格

现在有了数据,接下来就要将数据展示在控制台上。update() 函数遍历网格数组,判断每个格子的Value值,如果为true,就将格子设为白色,如果为false,就将格子设为黑色,其中白色表示激活,黑色表示未激活。

private static void Update()
{
    for (int i = 0; i < grid.GetLength(0); i++)
    {
        for (int j = 0; j < grid.GetLength(1); j++)
        {
            if (grid[i, j].Value)
            {
                SetWhite(i, j);
            }
            else
            {
                SetBlack(i, j);
            }
        }
    }
}

SetWhite()函数和SetBlack()函数调用了C#控制台的接口,将指定位置的背景设为指定颜色。

private static void SetWhite(int i, int j)
{
    string fill = "  "; // 两个空格
    Console.SetCursorPosition(j * fill.Length, i);
    Console.BackgroundColor = ConsoleColor.White;
    Console.Write(fill);
}

private static void SetBlack(int i, int j)
{
    string fill = "  "; // 两个空格
    Console.SetCursorPosition(j * fill.Length, i);
    Console.BackgroundColor = ConsoleColor.Black;
    Console.Write(fill);
}

 

至此,网格的创建和显示就完成了,不过这两个函数还没有被调用。

在网格上绘制数字

现在网格可以通过update()函数显示到控制台上了,接下来就可以对照那张excel表绘制指定的数字了。我用的这个绘制数字的方式是比较笨的,没有想出来更好的办法,如果有,欢迎在评论区指出。

绘制的基本方法就是把组成数字的格子设成白色,没有数字的格子设成黑色,0到9一共10个数字全都绘制一遍。

先是一个枚举,表示要绘制的数字开始的列,其中HourFirst表示“小时”的十位,开始于网格第1列,HourSecond表示“小时”的个位,开始于网格的第7列,依此类推。

public enum NumberLocation
{
    HourFirst = 1, HourSecond = 7,
    MinuteFirst = 15, MinuteSecond = 21,
    SecondFirst = 29, SecondSecond = 35,
}

 

下面是绘制代码,因为太长就默认折叠了。其中TraverseNumber函数就是为了复用二重循环。DisplayNumber函数根据每个数字的坐标设置格子的Value值,location参数表示要显示数字的列位置,接收一个枚举,比如 DisplayNumber(3, NumberLocation.HourFirst) 表示“小时”的十位是3。

private static void DisplayNumber(int number, NumberLocation location)
{
    int colOffset = (int)location;
    switch (number)
    {
        case 0:
            TraverseNumber(colOffset, (i, j) =>
            {
                if (i == 1 || i == 9)
                {
                    grid[i, j].Value = true;
                    return;
                }

                if (i == 2 || i == 3 || i == 4 || i == 5 || i == 6 || i == 7 || i == 8)
                {
                    if (j == colOffset || j == colOffset + 4)
                    {
                        grid[i, j].Value = true;
                        return;
                    }
                }

                grid[i, j].Value = false;
            });
            break;
        case 1:
            TraverseNumber(colOffset, (i, j) =>
            {
                if (j == colOffset + 4)
                {
                    grid[i, j].Value = true;
                    return;
                }

                grid[i, j].Value = false;
            });
            break;
        case 2:
            TraverseNumber(colOffset, (i, j) =>
            {
                if (i == 1 || i == 5 || i == 9)
                {
                    grid[i, j].Value = true;
                    return;
                }

                if (i == 2 || i == 3 || i == 4)
                {
                    if (j == colOffset + 4)
                    {
                        grid[i, j].Value = true;
                        return;
                    }
                }

                if (i == 6 || i == 7 || i == 8)
                {
                    if (j == colOffset)
                    {
                        grid[i, j].Value = true;
                        return;
                    }
                }

                grid[i, j].Value = false;
            });
            break;
        case 3:
            TraverseNumber(colOffset, (i, j) =>
            {
                if (i == 1 || i == 5 || i == 9)
                {
                    grid[i, j].Value = true;
                    return;
                }

                if (i == 2 || i == 3 || i == 4 || i == 6 || i == 7 || i == 8)
                {
                    if (j == colOffset + 4)
                    {
                        grid[i, j].Value = true;
                        return;
                    }
                }

                grid[i, j].Value = false;
            });
            break;
        case 4:
            TraverseNumber(colOffset, (i, j) =>
            {
                if (i == 5)
                {
                    grid[i, j].Value = true;
                    return;
                }

                if (i == 1 || i == 2 || i == 3 || i == 4)
                {
                    if (j == colOffset || j == colOffset + 4)
                    {
                        grid[i, j].Value = true;
                        return;
                    }
                }

                if (i == 6 || i == 7 || i == 8 || i == 9)
                {
                    if (j == colOffset + 4)
                    {
                        grid[i, j].Value = true;
                        return;
                    }
                }

                grid[i, j].Value = false;
            });
            break;
        case 5:
            TraverseNumber(colOffset, (i, j) =>
            {
                if (i == 1 || i == 5 || i == 9)
                {
                    grid[i, j].Value = true;
                    return;
                }

                if (i == 2 || i == 3 || i == 4)
                {
                    if (j == colOffset)
                    {
                        grid[i, j].Value = true;
                        return;
                    }
                }

                if (i == 6 || i == 7 || i == 8)
                {
                    if (j == colOffset + 4)
                    {
                        grid[i, j].Value = true;
                        return;
                    }
                }

                grid[i, j].Value = false;
            });
            break;
        case 6:
            TraverseNumber(colOffset, (i, j) =>
            {
                if (i == 1 || i == 5 || i == 9)
                {
                    grid[i, j].Value = true;
                    return;
                }

                if (i == 2 || i == 3 || i == 4)
                {
                    if (j == colOffset)
                    {
                        grid[i, j].Value = true;
                        return;
                    }
                }

                if (i == 6 || i == 7 || i == 8)
                {
                    if (j == colOffset || j == colOffset + 4)
                    {
                        grid[i, j].Value = true;
                        return;
                    }
                }

                grid[i, j].Value = false;
            });
            break;
        case 7:
            TraverseNumber(colOffset, (i, j) =>
            {
                if (i == 1)
                {
                    grid[i, j].Value = true;
                    return;
                }

                if (i == 2 || i == 3 || i == 4 || i == 5 || i == 6 || i == 7 || i == 8 || i == 9)
                {
                    if (j == colOffset + 4)
                    {
                        grid[i, j].Value = true;
                        return;
                    }
                }

                grid[i, j].Value = false;
            });
            break;
        case 8:
            TraverseNumber(colOffset, (i, j) =>
            {
                if (i == 1 || i == 5 || i == 9)
                {
                    grid[i, j].Value = true;
                    return;
                }

                if (i == 2 || i == 3 || i == 4 || i == 6 || i == 7 || i == 8)
                {
                    if (j == colOffset || j == colOffset + 4)
                    {
                        grid[i, j].Value = true;
                        return;
                    }
                }

                grid[i, j].Value = false;
            });
            break;
        case 9:
            TraverseNumber(colOffset, (i, j) =>
            {
                if (i == 1 || i == 5 || i == 9)
                {
                    grid[i, j].Value = true;
                    return;
                }

                if (i == 2 || i == 3 || i == 4)
                {
                    if (j == colOffset || j == colOffset + 4)
                    {
                        grid[i, j].Value = true;
                        return;
                    }
                }

                if (i == 6 || i == 7 || i == 8)
                {
                    if (j == colOffset + 4)
                    {
                        grid[i, j].Value = true;
                        return;
                    }
                }

                grid[i, j].Value = false;
            });
            break;
    }
}
DisplayNumber

 

利用这个函数,就可以在控制台上显示数字了,修改Main函数:

static void Main(string[] args)
{
    Init();

    DisplayNumber(1, NumberLocation.HourFirst);
    DisplayNumber(2, NumberLocation.HourSecond);
    DisplayNumber(3, NumberLocation.MinuteFirst);
    DisplayNumber(4, NumberLocation.MinuteSecond);
    DisplayNumber(5, NumberLocation.SecondFirst);
    DisplayNumber(6, NumberLocation.SecondSecond);

    Update();
}

 

 

但是现在只有数字,没有分隔 小时 : 分钟 : 秒 的那两个小点。接下来绘制分隔点。首先定义枚举类,确定分隔点所在的列:

public enum DotLocation
{
    First = 13, Second = 27
}

 

然后显示分隔点:

private static void ShowAllDot()
{
    int firstCol = (int)DotLocation.First;
    int secondCol = (int)DotLocation.Second;

    grid[3, firstCol].Value = true;
    SetWhite(3, firstCol);
    grid[7, firstCol].Value = true;
    SetWhite(7, firstCol);

    grid[3, secondCol].Value = true;
    SetWhite(3, secondCol);
    grid[7, secondCol].Value = true;
    SetWhite(7, secondCol);
}

 

在Main函数中调用:

static void Main(string[] args)
{
    Init();

    DisplayNumber(1, NumberLocation.HourFirst);
    DisplayNumber(2, NumberLocation.HourSecond);
    DisplayNumber(3, NumberLocation.MinuteFirst);
    DisplayNumber(4, NumberLocation.MinuteSecond);
    DisplayNumber(5, NumberLocation.SecondFirst);
    DisplayNumber(6, NumberLocation.SecondSecond);

    ShowAllDot();
    Update();
}

 

运行看效果:

 

至此,数字和分隔点可以正常显示了。

开始倒计时

 完成了设置数据和显示数据的功能,就可以开始实现倒计时功能了。实现倒计时需要计时库,C#提供了Stopwatch用来精确计时,我们就用这个类。

一开始先把倒计时的时间硬编码,比如倒计时70秒,完成主要功能后再考虑让用户输入。LeftTime函数将倒计时的总时间和经过的时间相减,再调用DisplayNumber修改网格的值。

修改Main函数。Main函数定义了倒计时时间,初始化网格,再定义Stopwatch变量,之后是一个无限循环。循环过程中用Stopwatch计时,如果经过时间大于倒计时总时间,则说明计时时间到。每次循环都调用Update函数来显示数字:

static void Main(string[] args)
{
    int countdownSec = 70;

    Init();
    Stopwatch stopwatch = null;
    while (true)
    {
        if (stopwatch == null)
        {
            stopwatch = Stopwatch.StartNew();
        }

        // 时间到
        if (stopwatch != null && stopwatch.Elapsed.TotalSeconds > countdownSec)
        {
            LeftTime(countdownSec, countdownSec);
            stopwatch.Stop();
            stopwatch = null;

        }
        else
        {
            LeftTime(countdownSec, (int)stopwatch.Elapsed.TotalSeconds);
        }

        Update();
    }
}

private static void LeftTime(int countdownSec, int elapsedSec)
{
    var timeLeft = TimeSpan.FromSeconds(countdownSec - elapsedSec);
    DisplayNumber(timeLeft.Hours / 10, NumberLocation.HourFirst);
    DisplayNumber(timeLeft.Hours % 10, NumberLocation.HourSecond);
    DisplayNumber(timeLeft.Minutes / 10, NumberLocation.MinuteFirst);
    DisplayNumber(timeLeft.Minutes % 10, NumberLocation.MinuteSecond);
    DisplayNumber(timeLeft.Seconds / 10, NumberLocation.SecondFirst);
    DisplayNumber(timeLeft.Seconds % 10, NumberLocation.SecondSecond);
}

 

运行一下:

 

 可以看到计时器开始正常运行了。但是发现了一个问题,没有分隔点。分隔点都是闪烁的,不是静止的,所以需要添加一个切换分隔点状态的函数,每次调用这个函数,分隔点都会切换显示或隐藏的状态:

private static void SwitchDot(DotLocation location)
{
    int colOffset = (int)location;
    if (grid[3, colOffset].Value)
    {
        grid[3, colOffset].Value = false;
        SetBlack(3, colOffset);
    }
    else
    {
        grid[3, colOffset].Value = true;
        SetWhite(3, colOffset);
    }

    if (grid[7, colOffset].Value)
    {
        grid[7, colOffset].Value = false;
        SetBlack(7, colOffset);
    }
    else
    {
        grid[7, colOffset].Value = true;
        SetWhite(7, colOffset);
    }
}

 

可以让分隔点每500ms切换一次状态,方法和倒计时的方法相同。为了不让分隔点的计算影响倒计时的计算,需要单独开一个线程。这里用Thread开线程,也可以用Task.Run开线程。修改Main函数:

static void Main(string[] args)
{
    int countdownSec = 70;

    Init();

    Thread dotThread = new Thread(() =>
    {
        ShowAllDot();

        Stopwatch dotWatch = null;
        while (true)
        {
            if (dotWatch == null)
            {
                dotWatch = Stopwatch.StartNew();
            }

            if (dotWatch.ElapsedMilliseconds >= 500)
            {
                SwitchDot(DotLocation.First);
                SwitchDot(DotLocation.Second);

                dotWatch.Stop();
                dotWatch = null;
            }
        }
    });
    dotThread.Start();

    Stopwatch stopwatch = null;
    while (true)
    {
        if (stopwatch == null)
        {
            stopwatch = Stopwatch.StartNew();
        }

        // 时间到
        if (stopwatch != null && stopwatch.Elapsed.TotalSeconds > countdownSec)
        {
            LeftTime(countdownSec, countdownSec);
            stopwatch.Stop();
            stopwatch = null;

        }
        else
        {
            LeftTime(countdownSec, (int)stopwatch.Elapsed.TotalSeconds);
        }

        Update();
    }
}

 

运行一下:

可以看到分隔点闪烁起来了。

但是现在的这个计时器不会停止,等计时完成后会重新开始,所以我们要让计时完成时停止计时,并让分隔点静止。设置一个bool变量isCounting表示是否正在计时,为true表示正在计时,为false表示计时完毕。

修改Main函数:

static void Main(string[] args)
{
    int countdownSec = 5;

    Init();

    bool isCounting = true;

    Thread dotThread = new Thread(() =>
    {
        ShowAllDot();

        Stopwatch dotWatch = null;
        while (true)
        {
            if (dotWatch == null && isCounting)
            {
                dotWatch = Stopwatch.StartNew();
            }

            if (isCounting && dotWatch.ElapsedMilliseconds >= 500)
            {
                SwitchDot(DotLocation.First);
                SwitchDot(DotLocation.Second);

                dotWatch.Stop();
                dotWatch = null;
            }
        }
    });
    dotThread.Start();

    Stopwatch stopwatch = null;
    while (true)
    {
        if (stopwatch == null && isCounting)
        {
            stopwatch = Stopwatch.StartNew();
        }

        // 时间到
        if (stopwatch != null && stopwatch.Elapsed.TotalSeconds > countdownSec)
        {
            LeftTime(countdownSec, countdownSec);
            ShowAllDot();
            stopwatch.Stop();
            stopwatch = null;
            isCounting = false;
        }
        else if(isCounting)
        {
            LeftTime(countdownSec, (int)stopwatch.Elapsed.TotalSeconds);
        }

        Update();
    }
}

 

为了尽快看到效果,把计时总时间改为5秒。运行一下:

 

 可以看到计时完成之后数字不再改变,分隔点也静止了。

至此,倒计时的主要功能就完成了。

用户输入

作为一个倒计时工具,把倒计时时间硬编码肯定是不行的,需要让用户输入,还有退出倒计时页面、隐藏游标等功能。修改Main函数:

static void Main(string[] args)
{
    while (true)
    {
        Console.Clear();
        Console.CursorVisible = true;
        bool isQuit = false;
        bool isCounting = false;
        int countdownSec = 0;
        while (true)
        {
            Console.Write("Input Countdown Seconds: ");
            string countdownSecStr = Console.ReadLine();
            if (int.TryParse(countdownSecStr, out countdownSec))
            {
                break;
            }
        }

        Init();
        Console.CursorVisible = false;
        isCounting = true;

        Thread dotThread = new Thread(() =>
        {
            ShowAllDot();

            Stopwatch dotWatch = null;
            while (true)
            {
                if (isQuit)
                {
                    break;
                }

                if (dotWatch == null && isCounting)
                {
                    dotWatch = Stopwatch.StartNew();
                }

                if (isCounting && dotWatch.ElapsedMilliseconds >= 500)
                {
                    SwitchDot(DotLocation.First);
                    SwitchDot(DotLocation.Second);

                    dotWatch.Stop();
                    dotWatch = null;
                }
            }
        });
        dotThread.Start();

        Thread quitThread = new Thread(() =>
        {
            ConsoleKeyInfo key = Console.ReadKey();
            if (key.Key == ConsoleKey.Q)
            {
                isQuit = true;
            }
        });
        quitThread.Start();

        Stopwatch stopwatch = null;
        while (true)
        {
            if (isQuit)
            {
                break;
            }

            if (stopwatch == null && isCounting)
            {
                stopwatch = Stopwatch.StartNew();
            }

            // 时间到
            if (stopwatch != null && stopwatch.Elapsed.TotalSeconds > countdownSec)
            {
                LeftTime(countdownSec, countdownSec);
                ShowAllDot();
                stopwatch.Stop();
                stopwatch = null;
                isCounting = false;

            }
            else if (isCounting)
            {
                LeftTime(countdownSec, (int)stopwatch.Elapsed.TotalSeconds);
            }

            Update();
            Console.WriteLine("\n  Press q to quit");
        }
    }
}

 

最外层是一个无限循环,以保证程序不会自己退出。循环刚开始就接收用户输入的以秒为单位的总时间,之后初始化网格,隐藏游标,设置标志变量,开启线程等。quitThread线程监听用户是否按了q键,是就退出倒计时页面,返回到输入页面。

完整代码

完整代码将Main函数中的所有操作提取到了Countdown函数中,Main函数调用Countdown函数。

using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace Countdown
{
    class Program
    {
        private static Cell[,] grid = new Cell[11, 41];

        static void Main(string[] args)
        {
            Countdown();
        }

        private static void Countdown()
        {
            while (true)
            {
                Console.Clear();
                Console.CursorVisible = true;
                bool isQuit = false;
                bool isCounting = false;
                int countdownSec = 0;
                while (true)
                {
                    Console.Write("Input Countdown Seconds: ");
                    string countdownSecStr = Console.ReadLine();
                    if (int.TryParse(countdownSecStr, out countdownSec))
                    {
                        if (countdownSec > 86400)
                        {
                            continue;
                        }

                        break;
                    }
                }

                Init();
                Console.CursorVisible = false;
                isCounting = true;

                Thread dotThread = new Thread(() =>
                {
                    ShowAllDot();

                    Stopwatch dotWatch = null;
                    while (true)
                    {
                        if (isQuit)
                        {
                            break;
                        }

                        if (dotWatch == null && isCounting)
                        {
                            dotWatch = Stopwatch.StartNew();
                        }

                        if (isCounting && dotWatch.ElapsedMilliseconds >= 500)
                        {
                            SwitchDot(DotLocation.First);
                            SwitchDot(DotLocation.Second);

                            dotWatch.Stop();
                            dotWatch = null;
                        }
                    }
                });
                dotThread.Start();

                Thread quitThread = new Thread(() =>
                {
                    ConsoleKeyInfo key = Console.ReadKey();
                    if (key.Key == ConsoleKey.Q)
                    {
                        isQuit = true;
                    }
                });
                quitThread.Start();

                Stopwatch stopwatch = null;
                while (true)
                {
                    if (isQuit)
                    {
                        break;
                    }

                    if (stopwatch == null && isCounting)
                    {
                        stopwatch = Stopwatch.StartNew();
                    }

                    // 时间到
                    if (stopwatch != null && stopwatch.Elapsed.TotalSeconds > countdownSec)
                    {
                        LeftTime(countdownSec, countdownSec);
                        ShowAllDot();
                        stopwatch.Stop();
                        stopwatch = null;
                        isCounting = false;

                    }
                    else if (isCounting)
                    {
                        LeftTime(countdownSec, (int)stopwatch.Elapsed.TotalSeconds);
                    }

                    Update();
                    Console.WriteLine("\n  Press q to quit");
                }
            }
        }

        private static void LeftTime(int countdownSec, int elapsedSec)
        {
            var timeLeft = TimeSpan.FromSeconds(countdownSec - elapsedSec);
            DisplayNumber(timeLeft.Hours / 10, NumberLocation.HourFirst);
            DisplayNumber(timeLeft.Hours % 10, NumberLocation.HourSecond);
            DisplayNumber(timeLeft.Minutes / 10, NumberLocation.MinuteFirst);
            DisplayNumber(timeLeft.Minutes % 10, NumberLocation.MinuteSecond);
            DisplayNumber(timeLeft.Seconds / 10, NumberLocation.SecondFirst);
            DisplayNumber(timeLeft.Seconds % 10, NumberLocation.SecondSecond);
        }

        private static void Init()
        {
            for (int i = 0; i < grid.GetLength(0); i++)
            {
                for (int j = 0; j < grid.GetLength(1); j++)
                {
                    grid[i, j] = new Cell();
                    grid[i, j].Value = false;
                }
            }
        }

        private static void Update()
        {
            for (int i = 0; i < grid.GetLength(0); i++)
            {
                for (int j = 0; j < grid.GetLength(1); j++)
                {
                    if (grid[i, j].Value)
                    {
                        SetWhite(i, j);
                    }
                    else
                    {
                        SetBlack(i, j);
                    }
                }
            }
        }

        private static void SetWhite(int i, int j)
        {
            string fill = "  ";
            Console.SetCursorPosition(j * fill.Length, i);
            Console.BackgroundColor = ConsoleColor.White;
            Console.Write(fill);
        }

        private static void SetBlack(int i, int j)
        {
            string fill = "  ";
            Console.SetCursorPosition(j * fill.Length, i);
            Console.BackgroundColor = ConsoleColor.Black;
            Console.Write(fill);
        }

        private static void DisplayNumber(int number, NumberLocation location)
        {
            int colOffset = (int)location;
            switch (number)
            {
                case 0:
                    TraverseNumber(colOffset, (i, j) =>
                    {
                        if (i == 1 || i == 9)
                        {
                            grid[i, j].Value = true;
                            return;
                        }

                        if (i == 2 || i == 3 || i == 4 || i == 5 || i == 6 || i == 7 || i == 8)
                        {
                            if (j == colOffset || j == colOffset + 4)
                            {
                                grid[i, j].Value = true;
                                return;
                            }
                        }

                        grid[i, j].Value = false;
                    });
                    break;
                case 1:
                    TraverseNumber(colOffset, (i, j) =>
                    {
                        if (j == colOffset + 4)
                        {
                            grid[i, j].Value = true;
                            return;
                        }

                        grid[i, j].Value = false;
                    });
                    break;
                case 2:
                    TraverseNumber(colOffset, (i, j) =>
                    {
                        if (i == 1 || i == 5 || i == 9)
                        {
                            grid[i, j].Value = true;
                            return;
                        }

                        if (i == 2 || i == 3 || i == 4)
                        {
                            if (j == colOffset + 4)
                            {
                                grid[i, j].Value = true;
                                return;
                            }
                        }

                        if (i == 6 || i == 7 || i == 8)
                        {
                            if (j == colOffset)
                            {
                                grid[i, j].Value = true;
                                return;
                            }
                        }

                        grid[i, j].Value = false;
                    });
                    break;
                case 3:
                    TraverseNumber(colOffset, (i, j) =>
                    {
                        if (i == 1 || i == 5 || i == 9)
                        {
                            grid[i, j].Value = true;
                            return;
                        }

                        if (i == 2 || i == 3 || i == 4 || i == 6 || i == 7 || i == 8)
                        {
                            if (j == colOffset + 4)
                            {
                                grid[i, j].Value = true;
                                return;
                            }
                        }

                        grid[i, j].Value = false;
                    });
                    break;
                case 4:
                    TraverseNumber(colOffset, (i, j) =>
                    {
                        if (i == 5)
                        {
                            grid[i, j].Value = true;
                            return;
                        }

                        if (i == 1 || i == 2 || i == 3 || i == 4)
                        {
                            if (j == colOffset || j == colOffset + 4)
                            {
                                grid[i, j].Value = true;
                                return;
                            }
                        }

                        if (i == 6 || i == 7 || i == 8 || i == 9)
                        {
                            if (j == colOffset + 4)
                            {
                                grid[i, j].Value = true;
                                return;
                            }
                        }

                        grid[i, j].Value = false;
                    });
                    break;
                case 5:
                    TraverseNumber(colOffset, (i, j) =>
                    {
                        if (i == 1 || i == 5 || i == 9)
                        {
                            grid[i, j].Value = true;
                            return;
                        }

                        if (i == 2 || i == 3 || i == 4)
                        {
                            if (j == colOffset)
                            {
                                grid[i, j].Value = true;
                                return;
                            }
                        }

                        if (i == 6 || i == 7 || i == 8)
                        {
                            if (j == colOffset + 4)
                            {
                                grid[i, j].Value = true;
                                return;
                            }
                        }

                        grid[i, j].Value = false;
                    });
                    break;
                case 6:
                    TraverseNumber(colOffset, (i, j) =>
                    {
                        if (i == 1 || i == 5 || i == 9)
                        {
                            grid[i, j].Value = true;
                            return;
                        }

                        if (i == 2 || i == 3 || i == 4)
                        {
                            if (j == colOffset)
                            {
                                grid[i, j].Value = true;
                                return;
                            }
                        }

                        if (i == 6 || i == 7 || i == 8)
                        {
                            if (j == colOffset || j == colOffset + 4)
                            {
                                grid[i, j].Value = true;
                                return;
                            }
                        }

                        grid[i, j].Value = false;
                    });
                    break;
                case 7:
                    TraverseNumber(colOffset, (i, j) =>
                    {
                        if (i == 1)
                        {
                            grid[i, j].Value = true;
                            return;
                        }

                        if (i == 2 || i == 3 || i == 4 || i == 5 || i == 6 || i == 7 || i == 8 || i == 9)
                        {
                            if (j == colOffset + 4)
                            {
                                grid[i, j].Value = true;
                                return;
                            }
                        }

                        grid[i, j].Value = false;
                    });
                    break;
                case 8:
                    TraverseNumber(colOffset, (i, j) =>
                    {
                        if (i == 1 || i == 5 || i == 9)
                        {
                            grid[i, j].Value = true;
                            return;
                        }

                        if (i == 2 || i == 3 || i == 4 || i == 6 || i == 7 || i == 8)
                        {
                            if (j == colOffset || j == colOffset + 4)
                            {
                                grid[i, j].Value = true;
                                return;
                            }
                        }

                        grid[i, j].Value = false;
                    });
                    break;
                case 9:
                    TraverseNumber(colOffset, (i, j) =>
                    {
                        if (i == 1 || i == 5 || i == 9)
                        {
                            grid[i, j].Value = true;
                            return;
                        }

                        if (i == 2 || i == 3 || i == 4)
                        {
                            if (j == colOffset || j == colOffset + 4)
                            {
                                grid[i, j].Value = true;
                                return;
                            }
                        }

                        if (i == 6 || i == 7 || i == 8)
                        {
                            if (j == colOffset + 4)
                            {
                                grid[i, j].Value = true;
                                return;
                            }
                        }

                        grid[i, j].Value = false;
                    });
                    break;
            }
        }

        private static void TraverseNumber(int colOffset, Action<int, int> action)
        {
            for (int i = 1; i < 10; i++)
            {
                for (int j = colOffset; j < colOffset + 5; j++)
                {
                    action(i, j);
                }
            }
        }

        private static void SwitchDot(DotLocation location)
        {
            int colOffset = (int)location;
            if (grid[3, colOffset].Value)
            {
                grid[3, colOffset].Value = false;
                SetBlack(3, colOffset);
            }
            else
            {
                grid[3, colOffset].Value = true;
                SetWhite(3, colOffset);
            }

            if (grid[7, colOffset].Value)
            {
                grid[7, colOffset].Value = false;
                SetBlack(7, colOffset);
            }
            else
            {
                grid[7, colOffset].Value = true;
                SetWhite(7, colOffset);
            }
        }

        private static void ShowAllDot()
        {
            int firstCol = (int)DotLocation.First;
            int secondCol = (int)DotLocation.Second;

            grid[3, firstCol].Value = true;
            SetWhite(3, firstCol);
            grid[7, firstCol].Value = true;
            SetWhite(7, firstCol);

            grid[3, secondCol].Value = true;
            SetWhite(3, secondCol);
            grid[7, secondCol].Value = true;
            SetWhite(7, secondCol);
        }

        private static void HideAllDot()
        {
            int firstCol = (int)DotLocation.First;
            int secondCol = (int)DotLocation.Second;

            grid[3, firstCol].Value = false;
            SetBlack(3, firstCol);
            grid[7, firstCol].Value = false;
            SetBlack(7, firstCol);

            grid[3, secondCol].Value = false;
            SetBlack(3, secondCol);
            grid[7, secondCol].Value = false;
            SetBlack(7, secondCol);
        }
    }

    public class Cell
    {
        public bool Value { get; set; }
    }

    public enum NumberLocation
    {
        HourFirst = 1, HourSecond = 7,
        MinuteFirst = 15, MinuteSecond = 21,
        SecondFirst = 29, SecondSecond = 35,
    }

    public enum DotLocation
    {
        First = 13, Second = 27
    }
}

 

posted @ 2021-05-14 20:58  是只香菇  阅读(2787)  评论(2编辑  收藏  举报