hey everyone,

I've been a bit bored lately and have made a 'snake' game. I've made made a 10x10 grid of picture boxes and I'm holding the snake positions in a linked list. I'm changing the picture box to either 'snake.jpg' or 'blankSpot.jpg.' I have a pretty decent implementation working but my only problem is when the snake makes contact with the apple it takes the LinkedList's current length in picture boxes for the change to be added. I want the length of the snake to be instantaneous and not have a delay in the increase of the snake.

For example: When the snakes collides with the apple another node is added to the linked list but the snake goes through two more picture boxes before the snake grows in length by 1 picture box. I stepped through the code and when the snake collides with the apple my linkedlist says:

snake[13];
snake[13];
snake[23];

I have three methods in which I add/remove node drawSnake(), changeTail() and detectCollision(). I'm not sure why it takes so long for the change to be applied to the snake. I would appreciate anyone's advice.

public partial class gameScreen : Form
    {
        //Thread which refreshs screen
        Thread refreshScreen;
        //holds snake buttons
        LinkedList<int> snake = new LinkedList<int>();

        int randButton,
            snakeHead,
            direction;

        public gameScreen()
        {
            //constructor. Intialize variables
            InitializeComponent();
            randButton = 0;
            //start at button 94
            snakeHead = 94;
            //add first element to linked list
            snake.AddFirst(snakeHead);
            //go 'up'
            direction = -10;
            drawPictureBoxes();
            //start the thread
            refreshScreen = new Thread(screenRefresh);
            refreshScreen.Start();
        }
        private void drawPictureBoxes()
        {
            //create 100 pictureboxes at runtime
            int xLoc = 0,
                yLoc = 0,
                increment = 0;

            for (int i = 0; i < 101; i++)
            {
                //create picture boxes
                PictureBox picBox = new PictureBox();
                picBox.Image = Image.FromFile("blankSpot.jpg");
                picBox.Size = new Size(50, 50);
                picBox.Location = new Point(xLoc, yLoc);
                picBox.Name = "pictureBox_" + i;
                this.Controls.Add(picBox);
                xLoc += 50;
                increment++;
                //when we get to 10 draw on second line
                if (increment == 10)
                {
                    xLoc = 0;
                    yLoc += 50;
                    increment = 0;
                }
            }
            //After we're done drawn apple
            drawApple();
        }
        private void screenRefresh()
        {
            //updates main screen
            while (refreshScreen.IsAlive)
            {
                //draw snake
                drawSnake();
                //detect a collision
                detectCollision();
                //change tail
                changeTail();
                Thread.Sleep(500);
            }
        }
        private void drawApple()
        {
            //create a randon number between 0-100
            Random rand = new Random();
            randButton = rand.Next(0, 100);

            //if randButton is already in snake generate another
            while (snake.Contains(randButton))
            {
                randButton = rand.Next(0, 100);
            }
            //draw an apple
            changePicture("Apple.jpg", randButton);
        }
        private void detectCollision()
        {
            //
            if (snake.First.Value == randButton)
            {
                //collision
                snake.AddFirst(snakeHead);
                changePicture("snake.jpg", snake.First.Value);
                //Draw another apple
                drawApple();
            }
        }
        private void changePicture(string picture, int value)
        {
            //method to change picture at a particular button location
            PictureBox picBox = this.Controls["pictureBox_" + value] as PictureBox;
            picBox.Image = Image.FromFile(picture);
        }
        private void drawSnake()
        {
            //increment 
            int move = snakeHead += direction;

            //if snake goes off top re-draw from bottom/top
            if (move > 100)
            {
                move -= 100;
                snakeHead = move;
            }
            else if (move < 0)
            {
                move += 100;
                snakeHead = move;
            }
            //Add another node onto snake
            snake.AddFirst(move);
            changePicture("snake.jpg", snake.First.Value);
        }
        private void changeTail()
        {
            //get rid of last node/change picture
            changePicture("blankSpot.jpg", snake.Last.Value);
            snake.RemoveLast();
        }
        private void gameScreen_KeyDown(object sender, KeyEventArgs e)
        {
            //get a key press
            int key = (int)e.KeyCode;

            //change direction based on key press
            if (key == (int)Keys.Up)
            {
                //goes up
                direction = -10;
            }
            else if (key == (int)Keys.Down)
            {
                //goes down
                direction = 10;
            }
            else if (key == (int)Keys.Left)
            {
                //goes left
                direction = -1;
            }
            else if (key == (int)Keys.Right)
            {
                //goes right
                direction = 1;
            }
        }
    }

Finally fixed it.

private void detectCollision()
{
            //
      if (snake.First.Value == randButton)
      {
             //collision
              snake.AddFirst(snakeHead += direction);
              changePicture("snake.jpg", snake.First.Value);
              //Draw another apple
               drawApple();
       }
}

I needed to add 'direction' to snakehead before I inserted it into the linked list since this is the head that the snake is currently on. Adding just snakehead was 'repeating the current button and added it into the linked list

That will make the snake grow, but didnt the snake traditionally grow at the tail end, not the head end?

What i mean is, when you hit an apple, the head moves on as normal but the tail stays put for one turn, thus the snake grows by one square at the end. Adding the direction again will prevent the user from turning as it hits the apple...hitting the apple will force the snake to go one more space in the same direction.

To implement the traditional growth method, try this:

private bool detectCollision()        {
            //
            if (snake.First.Value == randButton)
            {
                //Draw another apple
                drawApple();
                //collision
                return true;
            }
            else
            {
                  return false;
             }
        }
        private void screenRefresh()
        {
            //updates main screen
            while (refreshScreen.IsAlive)
            {
                //draw snake
                drawSnake();
                //detect a collision
                if(detectCollision())
                {
                     //change tail
                     changeTail();
                 }
                Thread.Sleep(500);
            }
        }

i havent tested it, so let me know if anything goes awry, but that should mean that if you hit an apple your tail grows rather than your head moving forward one square :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.