Snake Game Question

I’ve created the core of a snake game, but I’m trying to fix a bug and I’m not quite sure how. Let me try to explain:

The game works on a timer where each tick means moving each part of the snake body one block in the direction that it is going. There is a KeyDown event that handles changing the direction, and then there is an Update event that handles moving the snake on each tick of the timer. There are restrictions to the changing your direction though: if you’re moving right then you cannot start moving left, if you’re moving up then you cannot start moving down, etc. My problem is that these restrictions can be bypassed. For example, if the snake is moving left then if you press the right key, the snake will not start moving to the right. Although, if you press the down key and then the right key in a quick succession, quicker than the interval of the timer than the snake will start moving right. Here’s the code for the two events described above:


        //  Directions: 0 = right, 1 = down, 2 = left, 3 = up
        private void frmMain_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyData)
            {
                case Keys.Right:
                    if (direction != 2)
                        direction = 0;
                    break;
                case Keys.Down:
                    if (direction != 3)
                        direction = 1;
                    break;
                case Keys.Left:
                    if (direction != 0)
                        direction = 2;
                    break;
                case Keys.Up:
                    if (direction != 1)
                        direction = 3;
                    break;
            }
        }

        private void Update(object sender, EventArgs e)
        {
            lblScore.Text = string.Format("Score: {0}", score);
            snake.Move(direction);
            for (int i = 1; i < snake.Body.Length; i++)
                if (snake.Body[0].IntersectsWith(snake.Body[i]))
                    Restart();
            if (snake.Body[0].X < 0 || snake.Body[0].X > 440)
                Restart();
            if (snake.Body[0].Y < 0 || snake.Body[0].Y > 250)
                Restart();
            if (snake.Body[0].IntersectsWith(food.Piece))
            {
                score += 1;
                snake.Grow();
                food.Generate(rand);
            }
            this.Invalidate();
        }

I hope that I explained it well enough that you guys can understand. If needed, I can try and make a video that shows you what I mean. I was thinking maybe I could disable the directional keys for the remainder of the interval when one is pressed? But I’m not sure. Thanks for any help!

Or maybe load pressed keys into a queue and execute when the next interval comes. Idkkkk mannnn

You could use an int that counts the distance you’ve traveled in a direction (Horizontal & Vertical) and compare it to make sure that the distance traveled is enough to actually move in that direction. Not sure I fully understand the problem though…


    //  Directions: 0 = right, 1 = down, 2 = left, 3 = up
        private void frmMain_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyData)
            {
                case Keys.Right:
                    if (direction != 2 && currentVerticalDistance > someReasonableDistance)
                        direction = 0;
                    break;
                case Keys.Down:
                    if (direction != 3 && currentHorizontalDistance > someReasonableDistance)
                        direction = 1;
                    break;
                case Keys.Left:
                    if (direction != 0 && currentVerticalDistance > someReasonableDistance)
                        direction = 2;
                    break;
                case Keys.Up:
                    if (direction != 1 && currentHorizontalDistance > someReasonableDistance)
                        direction = 3;
                    break;
            }
        }

Hmmm, I did something similar where the user could only press one directional key during an interval and this is essentially the same thing because it won’t move until it has hit the next interval and the whole snake has moved one block. I’m not sure if this solution in particular would yield better results than what I tried, but I would imagine it would not, but I’ll try and get back to you. I didn’t like the way that my solution worked, it made the game harder.