abdul wadood Ответов: 2

Не могу ничего написать пока таймер работает на языке Си#


Я сделал таймер, который работает в обратном направлении, начиная с 10.Я просто хочу создать небольшую простую игру.Я хочу написать предложение "я люблю программировать" менее чем за 10 секунд, если я смогу это сделать , сообщение должно быть показано "ты выиграл,Грац", но когда часы заканчиваются, сообщение должно быть показано "ты проиграл", но оно не берет предложение, и когда я пишу, оно исчезает.Я пытался сделать это вот мой код.

Что я уже пробовал:

class Program
   {
       static Timer timer = new Timer(1000);
       static int i = 10;

       static void Main(string[] args)
       {
           Console.WriteLine("Write the sentence in 10 seconds");
           Console.WriteLine("I love programming");
           Console.ReadKey();
           timer.Elapsed += timer_Elapsed;
           timer.Start();
           Console.Read();
       }

       private static void timer_Elapsed(object sender, ElapsedEventArgs e)
       {
           i--;
           Console.Clear();
           Console.WriteLine("=======================");
           Console.WriteLine("  Time is running out       ");
           Console.WriteLine("");
           Console.WriteLine("The Clock starts: {0}", i.ToString());
           Console.WriteLine("");
           Console.WriteLine("=======================");

           while (true)
           {
               if (Console.ReadLine() == "I love programming")
               {
                   Console.Clear();
                   Console.WriteLine("=======================");
                   Console.WriteLine("     You Win                     ");
                   Console.WriteLine("");
                   Console.WriteLine("     Gratz                      ");
                   Console.WriteLine("");
                   Console.WriteLine("=======================");
                   timer.Stop();
                   timer.Dispose();

               }
           }

           GC.Collect();
       }
   }

2 Ответов

Рейтинг:
9

CPallini

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

class Program
{
    static Timer timer = new Timer(1000);
    static int i = 10;
    static string sin;

    static void Main(string[] args)
    {
        sin = string.Empty;
        Console.WriteLine("Write the sentence in 10 seconds");
        Console.WriteLine("I love programming");
        timer.Elapsed += timer_Elapsed;
        timer.Start();
        while (i != 0)
        {
            if (Console.KeyAvailable)
            {
                sin += Console.ReadKey(true).KeyChar;
            }
        }
        timer.Stop();
        if (sin == "I love programming")
            Console.WriteLine("OK");
        else
            Console.WriteLine("KO");
    }

    private static void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        i--;
        Console.Clear();
        Console.WriteLine("=======================");
        Console.WriteLine("  Time is running out       ");
        Console.WriteLine("");
        Console.WriteLine("The Clock starts: {0}", i.ToString());
        Console.WriteLine("");
        Console.WriteLine(sin);
        Console.WriteLine("=======================");
    }
}


abdul wadood

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

Рейтинг:
1

OriginalGriff

Проблема заключается в том, что событие timer Elapsed вызывается в потоке, который его запустил, - том же потоке, который вызывает Console.Read.
К Сожалению, Консоль.Читать-это а блокировка вызова - он не возвращается до тех пор, пока пользовательский ввод не будет завершен, и это означает, что пользователь нажимает ENTER.

Что вам нужно сделать, так это переместить таймер в другой поток, чтобы он мог работать независимо от вашего основного кода. Но... это также не сработает для вас, потому что ваш истекший код также пытается считывать входные данные от пользователя, а ReadLine также является блокирующим вызовом. Так что это не будет продолжаться до тех пор, пока пользователь не наберет ENTER! И вы вечно петляете внутри истекшего метода, так что это никогда не закончится! Но что еще хуже, тогда у вас есть два конкурирующих потока, пытающихся читать с одного и того же ввода, так что какой из них получит то, о чем можно только догадываться!

То, что вы пытаетесь сделать, на удивление сложно: вам нужно будет полностью прекратить использование блокирующих вызовов, а это означает, что вы должны начать думать очень, очень по-другому.
Это можно сделать как консольное приложение: Как прочитать, что написал пользователь (не нажимая enter) - консоль C# - переполнение стека[^ но это довольно продвинутая штука. Я бы настоятельно рекомендовал вам оставить это на неделю или две, когда вы доберетесь до приложений Windows вместо консольных, которые гораздо, гораздо больше подходят для многопоточной работы, таймеров и неблокирующих входов!


abdul wadood

Спасибо за информацию.Да, вы правы, это довольно сложно, так как я новичок, я просто хотел протестировать таймер в консоли, что я уже сделал в форме win, но все равно спасибо.Но можете ли вы посоветовать, над какими проектами индивидуум должен работать над консольным приложением для начинающих, что мне будет полезно знать?

OriginalGriff

Это не совсем случай "вы хотите работать над этим типом проекта", а скорее "консольные приложения предназначены для обучения кодированию в .NET" - по крайней мере, до тех пор, пока вы не получите хороший опыт, а затем не узнаете, когда их использовать. В большинстве случаев в наши дни windows (или веб-приложение) является лучшим выбором, поскольку пользователи гораздо лучше знакомы с ними и с тем, как их использовать.

Я бы не стал вкладывать много труда в выполнение сложных вещей в консольном приложении - ограничения ввода и вывода усложняют его, как показывает ответ Карло. Совершенно не очевидно, что там происходит и почему, и это затрудняет написание кода, над которым вы можете работать позже.

Подобное приложение в WinForms гораздо проще написать, потому что они уже основаны на концепции событий и событийного программирования - в отличие от консольных приложений, которые в значительной степени всегда процедурны и в результате испытывают трудности при работе с событиями. Я бы вернулся к вашему учебнику и попробовал некоторые упражнения - они научат вас гораздо большему (и лучше структурированному), чем случайные попытки запустить приложение! :смеяться:

abdul wadood

Я думал, что каждый новичок, изучающий C#, начинает с консольных приложений, чтобы изучить некоторые основы, вот почему я начал его...Я изучу основы отсюда, а затем скоро перейду на Winform

OriginalGriff

Это звучит очень похоже на "Я делаю это сам" - если так, остановитесь прямо сейчас!
Вместо этого возьмите книгу - или лучше курс - и следуйте ему от начала до конца. Материал будет представлен в структурированном виде с упражнениями, чтобы убедиться, что вы понимаете, что вы делаете на каждом этапе, прежде чем строить на этом для следующего этапа. (Аддисон Уэсли делает хорошие вещи, как это делают Wrox и Microsoft Press)
Попытка подобрать его по ходу дела не приведет вас далеко, потому что вы не будете иметь ни малейшего представления о том, чего вы не знаете, что могло бы сделать вашу жизнь намного проще!

abdul wadood

Звучит здорово! Я буду искать книги и курсы.Большое вам спасибо :D
есть ли в любом случае на этом сайте, где я могу связаться с вами, если мне понадобится какая - то помощь-просто говоря, что я горю желанием научиться программированию, я знаю, что в будущем мне понадобится гораздо больше советов :смейтесь:

OriginalGriff

Просто напишите вопрос - здесь полно полезных людей!