0

The goal of my current Typing Game feature (code provided below) is to countdown from either 10(hard), 20(medium), or 30(easy), depending on the users difficulty selection once the game has started. Once the countdown reaches zero OR the user runs out of lives, the game is over (which stops the countdown). The game starts properly, displays the first word to be typed by the user, and begins counting down from 10. My current problem is that I can't figure out how to stop the timer from counting down past 0. I have tried using t.Change(Timeout.Infinite , Timeout.Infinite) and checking when timeLeft == 0 with no prevail. I really feel like I am overthinking this (or underthinking), some help or a nudge in the right direction would be greatly appreciated!

my code is provided below:

    class Program
{
    // List of words to be typed
    public static string[] words = { "some", "side", "add", "another", "would", "book" ,"water", "came" ,"your" ,"big","both", "from", "learn", "been", "me" ,"school" ,"land", "took", "place",
            "try", "line", "tell", "earth", "can", "do","children", "without", "my", "must", "take", "follow", "year", "is", "being", "different", "miss", "could", "on", "he", "open", "night", "were",
            "line","said", "around", "an", "plant", "know", "set","been", "life","young","of", "face", "we", "hand", "while", "is", "white", "call", "live","may", "study","after" ,"down", "him", "now", "different",
            "could", "over", "work","all", "mean","begin","go","fall", "really", "oil", "before","into","one","name","has","a", "well", "got","something","turn" };
    // Keeps track of words array
    public static int numWords = 88;
    public static int correctWords = 0;
    // Initialize our random number generator
    public static Random rand = new Random();
    // Handles user input
    public static string userInput = "";
    public static string endGameChoice = "";
    // Handles gamestate variables
    public static bool gameActive = false;
    public static int numLives = 0;
    public static int timeLeft;
    public static System.Threading.Timer t;


    // Entry Point
    static void Main(string[] args)
    {
        // Start the game
        Start();
    }

    // Handles gameplay
    static void Play()
    {
        // Assigns the current word to any random word in
        // the words array
        string currentWord = words[rand.Next(0, 88)];
        // Print the current word separated by lines
        Console.WriteLine("********");
        Console.WriteLine(currentWord);
        Console.WriteLine("********");
        // While the answser is incorrect/empty
        while (!userInput.Equals("exit"))
        {
            // Reads user input
            userInput = Console.ReadLine();
            if (userInput.Equals(""))
            {
                Play();
            }
            // Checks if userInput is equal to current word
            if (!(userInput.Equals(currentWord)))
            {
                // If incorrect, display loss of life
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Incorrect!!!");
                Console.WriteLine("Lives: " + numLives);
                numLives--; // Take a life away
                Console.ResetColor();

            }
            if (numLives == -1)
            {
                outOfLives();
            }
            if (userInput.Equals(currentWord))
            {
                correctWords++;
                Play();
            }
        }
        if (userInput.Equals("exit"))
        {
            Environment.Exit(0);
        }

    }
    // Function for running out of lives
    private static void outOfLives()
    {
        Console.WriteLine("Game over! You typed " + correctWords + " words correctly!");
        Console.WriteLine("Type anything and press enter to retry, Press Escape to Quit!");

        var endGameKey = Console.ReadKey();

        if (endGameKey.Key == ConsoleKey.Escape)
        {
            Environment.Exit(0);
        }
        if (endGameKey.Key == ConsoleKey.Enter)
        {
            restartGame();
        }
        else
        {
            outOfLives();

        }

    }
    // Function for running out of time
    private static void outOfTime()
    {
        Console.WriteLine("Out of time! You typed " + correctWords + " words correctly!");
        Console.WriteLine("Type anything and press enter to retry, Press Escape to Quit!");

        var endGameKey = Console.ReadKey();

        if (endGameKey.Key == ConsoleKey.Escape)
        {
            Environment.Exit(0);
        }
        if (endGameKey.Key == ConsoleKey.Enter)
        {
            restartGame();
        }
        else
        {
            outOfTime();
        }

    }

    // Prompts user for input for difficulty along with game instructions
    static void StartMessage()
    {
        Console.WriteLine("Welcome to my Typing Practice App!");
        Console.WriteLine("Type the word displayed as fast as you can");

        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine("Difficulties are listed from hardest to easiest");
        Console.WriteLine();
        Console.WriteLine("Select a difficulty( 1 ,2 , or 3 ): ");
        Console.WriteLine();
        Console.ResetColor();

        Console.ForegroundColor = ConsoleColor.DarkRed;
        Console.WriteLine("-- Press ENTER --");
        Console.WriteLine("***  Satan Himself  ***");
        Console.WriteLine();
        Console.ResetColor();

        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine("-- Type 1 --)");
        Console.WriteLine("***  Software Engineer  ***");
        Console.WriteLine();
        Console.ResetColor();

        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.WriteLine("-- Type 2 --)");
        Console.WriteLine("***  Social Media Fanatic  ***");
        Console.WriteLine();
        Console.ResetColor();

        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine("-- Type 3 --)");
        Console.WriteLine("*** Filthy Peasant ***");
        Console.WriteLine();
        Console.ResetColor();

        string difficultyChoice = Console.ReadLine();
        switch (difficultyChoice)
        {
            case "1":
                numLives = 1;
                Console.WriteLine("You have 2 lives! Good luck!");
                timeLeft = 10;
                break;
            case "2":
                numLives = 3;
                Console.WriteLine("You have 4 lives! Good luck!");
                timeLeft = 20;
                break;
            case "3":
                numLives = 5;
                Console.WriteLine("You have 6 lives! Good luck!");
                timeLeft = 30;
                break;

            default:
                numLives = 0;
                Console.ForegroundColor = ConsoleColor.DarkRed;
                Console.WriteLine("Miss one and you're done!!!!!");
                Console.ResetColor();
                timeLeft = 10;
                break;
        }
    }
    public static void restartGame()
    {
        Console.Clear();
        //numLives = 5;
        numWords = words.Length;
        correctWords = 0;
        Start();
    }

    public static void SetTimer(Object o)
    {
        timeLeft--;
        Thread.Sleep(1000);
        Console.WriteLine(timeLeft);
        if (timeLeft == 0)
        {
            outOfTime();
        }

    }


    public static void Start()
    {
        // Display start message
        StartMessage();
        gameActive = true;
        t = new System.Threading.Timer(SetTimer, null, 0, 1250);
        // While user wants to play
        while (!userInput.Equals("exit"))
        {
            // While the game is active
            while (gameActive == true)
            {
                // Start the game
                Play();
            }
        }
        if (userInput.Equals("exit"))
        {
            Environment.Exit(0);
        }

    }
}

}

  • I see this: Console.WriteLine(timeLeft) in the SetTimer method - are you seeing output from that? – toni Jan 14 '19 at 22:47
  • Why are you calling `Thread.Sleep(1000);` in the callback? Also you aren't stopping it anywhere – TheGeneral Jan 14 '19 at 22:48
  • @toni I am getting a normal countdown displayed with that line until it reaches 0, thats when it proceeds into the negatives. I am using it to test the countdown – StonedProgrammer13 Jan 14 '19 at 22:50
  • @TheGeneral Great point, that was left out from a previous attempt. I removed it – StonedProgrammer13 Jan 14 '19 at 22:51
  • Maybe pass an object to SetTimer with timeLeft as a property - it could be a context/scope issue, although strange because timeLeft is declared as static. – toni Jan 14 '19 at 22:54
  • **[Navigating through Your code using the Step Debugger](https://msdn.microsoft.com/en-us/library/y740d9d3.aspx)** – Ňɏssa Pøngjǣrdenlarp Jan 14 '19 at 22:57
  • You'll be a lot happier if you do this in a graphical framework like Windows Forms or WPF. Doing complicated UI in a console app is no fun at all. – Flydog57 Jan 14 '19 at 22:58
  • @Flydog57 I absolutely agree, and will likely move over to Windows Forms for future upgrades. I just wanted to see how far I could go with a console application – StonedProgrammer13 Jan 14 '19 at 22:59

4 Answers4

0

Try to use this. Coroutines should solve your problem if you can get it to work.

  • YESSSSS thank you! I have no idea why I didn't think of that! I'll try implementing coroutines now – StonedProgrammer13 Jan 14 '19 at 22:52
  • This is a fairly low quality answer, its in essence just a link, there is no explanation of what they are or how they could fix the problem and no explanation of what the current problem might be – TheGeneral Jan 14 '19 at 22:57
0

You don't need a progammatic timer or thread to have a game timer. Just record the time at the beginning of the game:

//During initialization
var startTime = DateTime.Now;

And any time you wish to display or use a timer, compute it:

var timerValue = DateTime.Now - startTime;
Console.WriteLine("Time elapsed: {0} seconds", timerValue.Seconds);
John Wu
  • 50,556
  • 8
  • 44
  • 80
  • That won't interrupt the game loop (`Console.ReadLine()`). – Nigel Whatling Jan 14 '19 at 22:51
  • 1
    Neither will a timer. When the timer interrupts the main thread, the console will still complete the data entry for the original ReadLine. During this time, the timer code will block. Try it. OP will need to live with this or redesign with a non-blocking call in the main thread. – John Wu Jan 14 '19 at 23:02
  • Hmm. Good point. You could at least semi-gracefully handle the response after the timeout had elapsed. But ultimately agree. Needs redesign. – Nigel Whatling Jan 14 '19 at 23:11
  • @JohnWu Thank you for the reply, I will definitely try this out. – StonedProgrammer13 Jan 14 '19 at 23:12
0

you can use Timer in this way.

It works for you

var timer2 = new Timer();
timer2.Elapsed += (o, e) =>
{
    Console.WriteLine("Time Elapsed {0}", e.SignalTime);
    timer2.Stop();
};
timer2.Interval = 1000;
timer2.Start();
Derviş Kayımbaşıoğlu
  • 28,492
  • 4
  • 50
  • 72
0

As a direct fix to the problem presented (timer going below 0), you need to stop the timer when it is no longer needed. For that, use this line:

t.Change(Timeout.Infinite, Timeout.Infinite);

You could add this line to the start of your outOfLives and outOfTime methods:

private static void outOfLives()
{
    t.Change(Timeout.Infinite, Timeout.Infinite);
    Console.WriteLine("Game over! You typed " + correctWords + " words correctly!");
    ...

and...

private static void outOfTime()
{
    t.Change(Timeout.Infinite, Timeout.Infinite);
    Console.WriteLine("Out of time! You typed " + correctWords + " words correctly!");
    ...

EDIT: Sorry. Just re-read your question and realised you had already tried this line. Did you have it in the correct place(s)?

Nigel Whatling
  • 2,371
  • 1
  • 16
  • 22