Немного асинхронного и объектно-ориентированного программирования, и вот что получилось.
Создадим класс бомбы, он будет отвечать за разблокировку и отсчет оставшегося времени.
public class Bomb
{
private TimeSpan _second = TimeSpan.FromSeconds(1);
private int _code;
private TimeSpan _time;
private CancellationTokenSource _cts;
private int _left;
private int _top;
public bool Armed => _cts != null;
public Bomb(int code, TimeSpan time)
{
_code = code;
_time = time;
Console.Write("Осталось: ");
_top = Console.CursorTop;
_left = Console.CursorLeft;
Console.WriteLine(_time.ToString("mm\\:ss"));
}
public async void Arm()
{
using (_cts = new CancellationTokenSource())
{
await RunTimer(_cts.Token);
}
_cts = null;
}
public void Disarm(int code)
{
if (_cts == null)
return;
if (code == _code)
_cts?.Cancel();
else
Console.WriteLine("Неверный код");
}
private async Task RunTimer(CancellationToken token)
{
try
{
while (_time >= TimeSpan.Zero)
{
_time -= _second;
await Task.Delay(1000, token);
int tmpLeft = Console.CursorLeft;
int tmpTop = Console.CursorTop;
Console.SetCursorPosition(_left, _top);
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(_time.ToString("mm\\:ss"));
Console.ForegroundColor = ConsoleColor.Gray;
Console.SetCursorPosition(tmpLeft, tmpTop);
}
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Бах!");
Console.ForegroundColor = ConsoleColor.Gray;
}
catch (OperationCanceledException)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Обезврежено.");
Console.ForegroundColor = ConsoleColor.Gray;
}
}
}
Ну и давайте играть с этим классом
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Активация.");
int code;
do
{
Console.Write("Введите код: ");
if (!int.TryParse(ReadPassword(), out code) || code <= 0)
{
Console.WriteLine("Неподходящий код, попробуйте еще раз.");
}
}
while (code <= 0);
int seconds;
do
{
Console.Write("Введите время в секундах: ");
if (!int.TryParse(Console.ReadLine(), out seconds) || seconds <= 0)
{
Console.WriteLine("Неподходящее время, попробуйте еще раз.");
}
}
while (seconds <= 0);
Bomb bomb = new Bomb(code, TimeSpan.FromSeconds(seconds));
Console.WriteLine("Нажмите любую клавишу для активации...");
Console.ReadKey(true);
bomb.Arm();
while (bomb.Armed)
{
Console.Write("Введите код: ");
if (int.TryParse(Console.ReadLine(), out code) && code > 0)
bomb.Disarm(code);
else
if (bomb.Armed)
Console.WriteLine("Неподходящий код, попробуйте еще раз.");
}
}
private static string ReadPassword()
{
string password = string.Empty;
ConsoleKey key;
do
{
ConsoleKeyInfo keyInfo = Console.ReadKey(true);
key = keyInfo.Key;
if (key == ConsoleKey.Backspace && password.Length > 0)
{
Console.Write("\b \b");
password = password[0..^1];
}
else if (!char.IsControl(keyInfo.KeyChar))
{
Console.Write("*");
password += keyInfo.KeyChar;
}
} while (key != ConsoleKey.Enter);
Console.WriteLine();
return password;
}
}
Вывод в консоль
Активация.
Введите код: ****
Введите время в секундах: 120
Осталось: 01:52
Нажмите любую клавишу для активации...
Введите код: 123
Неверный код
Введите код: 1234
Обезврежено.
В качестве домашнего задания, разберитесь с этим кодом. Очень важно понять, как это работает. Это наверняка еще можно доработать. Например, вводить долго коды, таймер уезжает вверх и консоль начинает дергаться, чтобы отрисовать время. Но это можно исправить вводя код на одном и том же месте консоли, аналогично как выводится время в одном и том же месте.