Question Simple Snake Game - Snake Head is not moving after ReadKey()

Joined
Sep 26, 2022
Messages
16
Programming Experience
1-3
The snake head ```0``` does not move anywhere when ```Console.ReadKey()``` happens.
Here is the full code:

C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SimpleSnakeGame_ConsoleApp
{
    internal class Program
    {
        public bool gameOver = true;
        public int width = 20;
        public int height = 20;

        //HEAD POS
        public int x, y;

        //FRUIT POS
        public int fruitX, fruitY;

        public int score;

        //bir kere basınca oraya gitmeni sağlayacak enum
        enum eDirection { STOP = 0, LEFT, RIGHT, UP, DOWN };
        eDirection dir; //enum class gibi çalışıyor enum'dan dir isimli bir object yarattık

        static void Main(string[] args)
        {

            Program oyun = new Program();

                oyun.Setup();

                oyun.Draw();
                oyun.Input();
                oyun.Logic();


            Console.ReadLine();
        }

        //Setting Up the MAP
        public void Setup()
        {
            gameOver = false;
            string a = "!!!!! SİMPLE SNAKE GAME !!!!!";
            Console.WriteLine(gameOver.ToString() + " " + a, "{0}" + "{1}");
            dir = eDirection.STOP;
            x = width / 2;
            y = height / 2;

            Random rnd = new Random();
            fruitX = rnd.Next(1, 19);
            fruitY = rnd.Next(1, 19);
            score = 0;

        }
        void Draw()
        {
            for (int j = 0; j < height; j++)
            {
                for (int i = 0; i < width; i++)
                {
                    if (i == y && j == x)
                    {
                        Console.Write("0");
                    }
                    else if (i == fruitY && j == fruitX)
                    {
                        Console.Write("F");
                    }
                    else if (j > 0 && j < height - 1 && i > 0 && i < width - 1)
                    {
                        Console.Write(" ");
                    }
                    else
                    {
                        Console.Write("#");
                    }

                }

                Console.WriteLine();
            }

            Console.WriteLine();
        }
        void Input()
        {
            ConsoleKey key;

            // Key is available - read it
            key = Console.ReadKey(true).Key;

            if (key == ConsoleKey.A)
            {
                dir = eDirection.LEFT;
            }
            else if (key == ConsoleKey.D)
            {
                dir = eDirection.RIGHT;
            }
            else if (key == ConsoleKey.W)
            {
                dir = eDirection.UP;
            }
            else if (key == ConsoleKey.S)
            {
                dir = eDirection.DOWN;
            }
            else if (key == ConsoleKey.X)
            {
                gameOver=true;
            }
        }
        void Logic()
        {
            switch (dir)
            {
                case eDirection.LEFT:
                    x--;
                    break;
                case eDirection.RIGHT:
                    x++;
                    break;
                case eDirection.UP:
                    y--;
                    break;
                case eDirection.DOWN:
                    y++;
                    break;
                default:
                    break;
            }
        }
    }

}

I guess the problem is ```Console.ReadKey()``` function here:

C#:
void Input()
        {
            ConsoleKey key;

            // Key is available - read it
            key = Console.ReadKey(true).Key;

            if (key == ConsoleKey.A)
            {
                dir = eDirection.LEFT;
            }
            else if (key == ConsoleKey.D)
            {
                dir = eDirection.RIGHT;
            }
            else if (key == ConsoleKey.W)
            {
                dir = eDirection.UP;
            }
            else if (key == ConsoleKey.S)
            {
                dir = eDirection.DOWN;
            }
            else if (key == ConsoleKey.X)
            {
                gameOver=true;
            }
        }
However I do not know what to replace
C#:
Console.ReadKey()
with and how to do it.

Here is the OUTPUT:

1666256815642.png
 
You don't have a game loop. You just have the body of a game loop, but the actual looping structure.
 
Your code execution proceeds from line 34, to line 35, to line 36, and then to line 39. Within the Draw() method you call on line 34, you draw the screen. Within the Input() method called on line 35, you read one key from the console, and map the key to a direction. Within the Logic() method called on line 36, you compute the next position of the head. On line 39, you then call ReadLine() to accept input from the console until the user presses the enter key.

You need a game loop so that the code execution goes from lines 34, 35, 36, and then back to line 34 so that cycle begins again and the screen is re-redrawn with the new computed position, and the next input is taken, and the new position is computed.

 
You don't have a game loop. You just have the body of a game loop, but the actual looping structure.
I have already tried putting a while loop as you did, but the code drew the game area/skeleton infinitely. The while loop makes Visual Studio console draw the game infinitely one below another.

I do not know how to solve this either.
 
You cross-posted this on Code Forum as well... There I pointed out that Console.ReadKey(true).Key doesn't actually return until you hit the Enter key, but Console.ReadKey().Key does the job. Not sure why, but this is how it worked for me.
Now if you want to create a console game like this you'll a) need to have a loop (duh.....) and b) use terminal escape sequences to move the cursor where you want it. That will work in a DOS box but I'm not sure if it will in the Visual Studio console just like that. This article Console Virtual Terminal Sequences - Windows Console may help with that.
 
No variant of ReadKey() waits for the enter key to be pressed.
 
I would like to think so, but the OP's code did when I ran it in Visual Studio. Until I removed the true parameter.
Here's minimal code to show that both ReadKey() don't need the Enter key to get the key press
C#:
using System;

Console.WriteLine("Before ReadKey(true)");
var first = Console.ReadKey(true).Key;
Console.WriteLine();
Console.WriteLine($"You typed {first}");

Console.WriteLine("Before ReadKey()");
var second = Console.ReadKey().Key;
Console.WriteLine();
Console.WriteLine($"You typed {second}");

Console.WriteLine("Press Enter to quit");
while (Console.ReadKey(true).Key != ConsoleKey.Enter)
    ; // do nothing

In particular, if your assertion that the true is needed then that while loop on line 14 should only exit after the user presses Enter twice.
 
Last edited:
I would like to think so, but the OP's code did when I ran it in Visual Studio. Until I removed the true parameter.
Leave the true in place, and just replace the blank line 94 with this:
C#:
Console.WriteLine($"Got {key}");
You'll see that the user's input was accepted.

Recall that the true parameter is there as a flag whether to echo back the what the user typed in or not. A value of true means do not echo the input.
 
Yes I know what the true parameter is for. And so was very surprised that it was blocking - I had a breakpoint on the next line which I wasn't hitting until enter was pressed. Having removed the flag it worked right away, so I blithely assumed it was some side effect of the flag (a bug maybe). But guess what, now that I try again it works fine with the parameter also. Either my interaction with the debugger was borked, or I was just being stupid. Either way sorry for the disinformation. I only barged into this thread because I replied to the question on another forum.
 

Latest posts

Back
Top Bottom