2

I am making a snake game as my homework assignment , I've already added a code for making the snake head move depending on the user input (left , right , down , up) But I am stuck with the timing of it , I used Thread.Sleep in order for the game not to crash and get an exception , but my instructor told me that Thread.Sleep is a horrible idea in programming because it literally adds a delay to your game. So, I need to somehow make it that there won't be a delay in my game while avoiding Thread.Sleep

class Program
    {
        static void Main(string[] args)
        {
            Direction direction = Direction.Down;

            Console.CursorVisible = false;
            int x=0 , y=0 ;
            int xprev = 2, yprev = 2;
            char shape = 'o';
            x = xprev;
            y = yprev;
            Console.SetCursorPosition(xprev, yprev);
            Console.Write(shape);

            UserInput input = new UserInput();
            ConsoleKeyInfo? info;

            while (true)
            {

                info = input.GetKey();
                if (info.HasValue)
                {

                    switch (info.Value.Key)
                    {
                        case ConsoleKey.RightArrow:
                            direction = Direction.Right;
                            break;

                        case ConsoleKey.LeftArrow:
                            direction = Direction.Left;
                            break;

                        case ConsoleKey.UpArrow:
                            direction = Direction.Up;
                            break;

                        case ConsoleKey.DownArrow:
                            direction = Direction.Down;
                            break;
                    }

                }
                Thread.Sleep(100);

                switch (direction)
                {
                    case Direction.Up:
                        y--;

                        break;
                    case Direction.Down:
                        y++;

                        break;
                    case Direction.Left:
                        x--;


                        break;
                    case Direction.Right:
                        x++;

                        break;

                }

                Console.MoveBufferArea(xprev, yprev, 1, 1, x, y);
                xprev = x;
                yprev = y;
            }
Shlomi U
  • 41
  • 1
  • 8
  • 1
    What exactly is the purpose of the sleep command here? You didn't really explain, other than to avoid an (also unspecified) exception. It's very hard to suggest alternatives if we don't know what you are trying to achieve in the first place – ADyson Jul 18 '19 at 06:39
  • Of course, excuse me for that, the purpose of it is to slow down the snake (just a char named 'o') so it won't cause an exception, without it the snake just flies in a huge speed and causes an exception. – Shlomi U Jul 18 '19 at 06:40
  • 4
    Timers should be more suitable for this – Sohaib Jundi Jul 18 '19 at 06:40
  • if you normally use an infinite while loop, you will either soon run of memory or the compiler will shut down your code. so to ensure your code runs fine, its a practise to use Thread.sleep. https://stackoverflow.com/questions/23616506/what-is-the-reason-for-whiletrue-thread-sleep – Baahubali Jul 18 '19 at 06:42
  • 4
    @Baahubali, that,... doesn't even make sense? An infinite while loop won't cause memory exhaustion, nor will it cause the compiler to "shut down your code" - the compiler isn't even in play when the code is running. `Thread.Sleep` will have no beneficial impact in either of those non-existent scenarios – Rob Jul 18 '19 at 06:44
  • @Sohaib Jundi How can I use timers? I haven't learned it so an example would be great. – Shlomi U Jul 18 '19 at 06:44
  • Example [here](https://learn.microsoft.com/en-us/dotnet/api/system.timers.timer?view=netframework-4.8) – ForeverZer0 Jul 18 '19 at 06:46
  • 3
    "but my instructor told me that Thread.Sleep is a horrible idea in programming because it literally adds a delay to your game." You *want* a delay between logical frames, and there's nothing more interesting that your app *could* be doing in this simple case. If it were a more complex scenario, then sure - timers might be good, but here? meh, a `Thread.Sleep` is **just fine**. If you had a `Thread.Sleep`, then your `Main()` method would still have to block *anyway*. – Marc Gravell Jul 18 '19 at 07:05

1 Answers1

1

As Sohaib Jundi suggests, a timer of some description is a reasonable solution here. Your objective is:

Every 100ms, update where the snake is

Rather than solve this by saying make the application pause for 100ms, then update the snake, using a timer changes it to Have something that triggers every 100ms to update the snake.

For example:

using System;
using System.Threading;

namespace Snake
{
    class Program
    {
        static void Main(string[] args)
        {
            var snakeTimer = new Timer(updateTheSnake, null, 0, 100);
            while(true)
            {
                var keypress = Console.ReadKey();
                if (keypress.Key == ConsoleKey.Escape)
                {
                    break;
                }
            }
        }

        static void updateTheSnake(object state)
        {
            Console.Write("@");
        }
    }
}

This is a very simple example that just draws a line of @ across the screen until the user presses the escape key. In your code, you'd likely want to move everything below the Thread.Sleep into the updateTheSnake method. direction will probably need to be stored into shared state so that you can refer to it from the updateTheSnake method.

Rob
  • 45,296
  • 24
  • 122
  • 150