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
实际上我找到了一种更好的方法,更容易实现和理解。只需使用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;
}
}