I am making a C# console maths test where the user answers maths questions
I am trying to add a timer to the test, but I can't make my timer run at the same time as my other code
Here is an example of my code:
class Program
{
public static OtherCode()
{
\\*other code for test
}
public class Timer
{
public static int Timers(int timeLeft)
{
do
{
Console.Write("\rtimeLeft: {0} ", timeLeft);
timeLeft--;
Thread.Sleep(1000);
} while (timeLeft > 0);
Console.Write(Environment.NewLine);
return timeLeft;
}
}
public static void Main(string[] args)
{
int numberOfSeconds = 30;
Timer.Timers(numberOfSeconds);
\\other code
OtherCode();
}
}
I would like my timer to be running at the top of the console and the maths questions to be asked underneath like this except the question should be on a newline:
Any help appreciated!
UPDATE
When I add Console.SetCursorPosition() to my code like so:
do
{
Console.SetCursorPosition(0, 9);
Console.Write("\rtimeLeft: {0} ", timeLeft);
timeLeft--;
Thread.Sleep(1000);
} while (timeLeft > 0);
My code won't move the timer but when I type the answer to one of my maths questions it makes me type it on the same line as the timer like this:
In order to have a status message that stays at the bottom of the console you need a way to manipulate the screen buffer so you continuously overwrite your status message.
The Console.SetCursorPos
can be used for this and is usefull in more advanced scenarios, but I think you can get by with simply using \r to reset the cursor to the beginning of the line.
Proof of consept:
using System;
namespace consoletimer
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
int numberOfSeconds = 300;
var thread = new System.Threading.Thread(()=> PrintStatusMessage(numberOfSeconds));
thread.Start();
int n = 5;
while(n-- > 0){
WriteToScreen("Example text", false);
ReadInput();
System.Threading.Thread.Sleep(2000);
}
}
static void PrintStatusMessage(int numberOfSeconds){
var whenToStop = DateTime.Now.AddSeconds(numberOfSeconds);
while(DateTime.Now < whenToStop){
var timeLeft = (whenToStop-DateTime.Now).ToString(@"hh\:mm\:ss");
WriteToScreen($"Time Remaining: {timeLeft}", true);
System.Threading.Thread.Sleep(500);
}
}
static string ReadInput(){
string input = Console.ReadLine();
Console.Write(new string(' ',100));
Console.CursorLeft = 0;
return input;
}
static object lockObject = new object();
static void WriteToScreen(string message, bool resetCursor){
lock(lockObject){
if(resetCursor){
int leftPos = Console.CursorLeft;
Console.WriteLine();
Console.Write(message.PadRight( 50, ' '));
Console.CursorTop--;
Console.CursorLeft = leftPos;
}
else{
Console.WriteLine(message);
Console.Write(new string(' ',100));
Console.CursorLeft = 0;
}
}
}
}
}
Edit
We need to clear the next line whenever we write to the console so that we remove the status message that was there previously.