2

Мне нужно, чтобы во время цикла был доступен ввод от пользователя, дабы ввести код деактивации. Не понимаю, как сделать.

Мой код:

Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Введите код для активации бомбы:");
string bombCode = Console.ReadLine();
if (Convert.ToInt32(bombCode) == 30032005)
{
    Console.WriteLine("До взрыва осталось 45 секунд. Чтобы разминировать бомбу - введите код деактивации.");
    for (int bombtimer = 45; bombtimer >= 0; bombtimer--) 
    {
        Thread.Sleep(1000);
        Console.WriteLine($"До взрыва осталось {bombtimer} секунд.");
    }
}
else
{
    Console.WriteLine("Неверный код для активации бомбы!");
}
aepot
  • 49,560
pokychlove
  • 23
  • 3

1 Answers1

6

Немного асинхронного и объектно-ориентированного программирования, и вот что получилось.

Создадим класс бомбы, он будет отвечать за разблокировку и отсчет оставшегося времени.

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(&quot;Введите время в секундах: &quot;);
        if (!int.TryParse(Console.ReadLine(), out seconds) || seconds &lt;= 0)
        {
            Console.WriteLine(&quot;Неподходящее время, попробуйте еще раз.&quot;);
        }
    }
    while (seconds &lt;= 0);

    Bomb bomb = new Bomb(code, TimeSpan.FromSeconds(seconds));
    Console.WriteLine(&quot;Нажмите любую клавишу для активации...&quot;);
    Console.ReadKey(true);
    bomb.Arm();
    while (bomb.Armed)
    {
        Console.Write(&quot;Введите код: &quot;);
        if (int.TryParse(Console.ReadLine(), out code) &amp;&amp; code &gt; 0)
            bomb.Disarm(code);
        else
        if (bomb.Armed)
            Console.WriteLine(&quot;Неподходящий код, попробуйте еще раз.&quot;);
    }
}

private static string ReadPassword()
{
    string password = string.Empty;
    ConsoleKey key;
    do
    {
        ConsoleKeyInfo keyInfo = Console.ReadKey(true);
        key = keyInfo.Key;

        if (key == ConsoleKey.Backspace &amp;&amp; password.Length &gt; 0)
        {
            Console.Write(&quot;\b \b&quot;);
            password = password[0..^1];
        }
        else if (!char.IsControl(keyInfo.KeyChar))
        {
            Console.Write(&quot;*&quot;);
            password += keyInfo.KeyChar;
        }
    } while (key != ConsoleKey.Enter);
    Console.WriteLine();
    return password;
}

}

Вывод в консоль

Активация.
Введите код: ****
Введите время в секундах: 120
Осталось: 01:52
Нажмите любую клавишу для активации...
Введите код: 123
Неверный код
Введите код: 1234
Обезврежено.

В качестве домашнего задания, разберитесь с этим кодом. Очень важно понять, как это работает. Это наверняка еще можно доработать. Например, вводить долго коды, таймер уезжает вверх и консоль начинает дергаться, чтобы отрисовать время. Но это можно исправить вводя код на одном и том же месте консоли, аналогично как выводится время в одном и том же месте.

aepot
  • 49,560