c# -通过ReadLine()在控制台中显示倒计时计时器供用户输入

本文关键字:倒计时 显示 计时器 输入 用户 控制台 ReadLine -通过 | 更新日期: 2023-09-27 18:16:30

目前我正在尝试创建一个主机游戏。基本概念是,用户得到一些随机的字母,并在有限的时间内用这些字母拼出尽可能多的单词。例如,用户获取[a,a,c,t,t,e,g,s,o,i],其中有效的单词是"get","got","test"等。检查用户输入是否出现在单词列表中,以及它是否由允许使用的字母组成。不幸的是,我有一些麻烦,试图实现和显示这个游戏的计时器。

请注意:我的c#知识非常有限,因为我只是一个初学者。

目前我有一个后台线程,其中包含一个循环与ReadLine()函数。'normal'代码使用Sleep()函数暂停,并在时间结束时继续。它很大程度上受到了这里给出的解决方案的启发。我希望实现的是在控制台中显示一个计时器,告诉用户他还剩下多少秒来填写单词。然而,我还没有想出如何实现这一点。

由于以下原因,我很难想出解决办法。计时器单词的原因是因为在"正常"代码暂停之后,包含请求用户输入的循环的线程在没有中断的情况下处于活动状态。这意味着没有可以允许打印计时器的中断。我不知道如何定期"暂停"readline函数,同时保持其功能。

所以我的问题是,我怎样才能做到这一点?

这是一段仅包含此功能的独立代码。因此,不测试这些单词是否符合要求。

using System;
using System.Collections.Generic;
using System.Threading;
namespace UnderstandingThreading
{
    class Reader
    {
        private static Thread inputThread;
        private static List<string> userInput = new List<string>();
        private static bool closeLoop = new bool();
        static Reader()
        {
            inputThread = new Thread(reader);
            closeLoop = false;
            inputThread.IsBackground = true;
            inputThread.Start();
        }
        private static void reader()
        {
            while (!closeLoop)
            {
                userInput.Add(Console.ReadLine());
            }
        }
        public static List<string> ReadLine(int timeOutMilliseconds)
        {
            Thread.Sleep(timeOutMilliseconds);
            closeLoop = true;
            return userInput;
        }
    }

    class MainClass
    {
        public static void Main(string[] args)
        {
            List<string> allEntries = new List<string>();
            Console.WriteLine("Please enter random things for the next 5 seconds");
            allEntries = Reader.ReadLine(5000);
            for (int i = 0; i < allEntries.Count; i++)
            {
                Console.WriteLine(allEntries[i]);
            }
        }
    }
}

谢谢你,

Sebastiaan

c# -通过ReadLine()在控制台中显示倒计时计时器供用户输入

实际上我找到了一种更好的方法,更容易实现和理解。只需使用system . timer . timer !

class MainClass
{
    private static int delay { get; set; }
    private static int time_left { get; set; }
    public static void Main(string[] args)
    {
        delay = 8;
        time_left = delay;
        List<string> allEntries = new List<string>();
        Console.WriteLine("Please enter random things for the next 5 seconds");
        Console.SetCursorPosition(0, 2);
        System.Timers.Timer Timer = new System.Timers.Timer(1000);
        Timer.Elapsed += WriteTimeLeft;
        Timer.AutoReset = true;
        Timer.Enabled = true;
        Timer.Start();
        allEntries = Reader.ReadLine(10000);
        Timer.Stop();
        for (int i = 0; i < allEntries.Count; i++)
        {
            Console.WriteLine(allEntries[i]);
        }
        Console.Read();
    }
    public static void WriteTimeLeft(Object source, ElapsedEventArgs e)
    {
        int currentLineCursorTop = Console.CursorTop;
        int currentLineCursorLeft = Console.CursorLeft;
        Console.CursorVisible = false;
        Console.SetCursorPosition(0, 1);
        Console.Write(new string(' ', Console.WindowWidth));
        Console.SetCursorPosition(0, 1);
        Console.Write(time_left);
        Console.SetCursorPosition(currentLineCursorLeft, currentLineCursorTop);
        Console.CursorVisible = true;
        time_left -= 1;
    }

基本上,我们设置了一个间隔为1000ms的计时器,并将其设置为AutoReset,因此当它被激活时,它将每秒触发一个事件。我们只需将自定义方法WriteTimeLeft(对象源,ElapsedEventArgs e)添加到事件启动的方法列表中,就可以开始了!:)

我找到了使用Task.Delay()解决问题的方法。基本上,我创建的任务有多少秒就有多少,我让每个任务比前一个多等待1秒。当任务完成时,它调用writetimelleft()函数,该函数负责正确显示时间并允许用户键入他的答案(我擦除显示时间的行,并用新时间替换它,然后将光标移回原来的位置)。为此,我添加了常量"delay"和变量"time_left"。由于这个动作非常快,用户可以不间断地输入:)

我相信代码是可以理解的,但如果你有任何问题,请不要犹豫问:)

这不是完美的(我不是一个专业的c#),但它会做你要求的;)

class MainClass
{
    private static int delay { get; set; }
    private static int time_left { get; set; }
    public static void Main(string[] args)
    {
        delay = 10;
        time_left = delay;
        List<string> allEntries = new List<string>();
        Console.WriteLine("Please enter random things for the next 10 seconds");
        Console.SetCursorPosition(0, 2);
        Timer();
        allEntries = Reader.ReadLine(11000);
        for (int i = 0; i < allEntries.Count; i++)
        {
            Console.WriteLine(allEntries[i]);
        }
        Console.Read();
    }
    public static void Timer()
    {
        for (int i = 11; i > 0; i--)
        {
            var t = Task.Delay(i*1000).ContinueWith(_ => WriteTimeLeft());
        }
    }
    public static void WriteTimeLeft()
    {
        int currentLineCursorTop = Console.CursorTop;
        int currentLineCursorLeft = Console.CursorLeft;
        Console.CursorVisible = false;
        Console.SetCursorPosition(0, 1);
        Console.Write(new string(' ', Console.WindowWidth));
        Console.SetCursorPosition(0, 1);
        Console.Write(time_left);
        Console.SetCursorPosition(currentLineCursorLeft, currentLineCursorTop);
        Console.CursorVisible = true;
        time_left -= 1;
    }
}