Snake game

Recommended Posts

Hello. I planned to do a simple snake clone, but I got stuck when I tried to think out a way to show the tail of the snake. And make the tail follow the head. I thought about a array or a vector (almost the same thing, but then again-not) to hold the tail. But I still don't know how to make the tail follow the head. There must be a point where the tail should turn of, but I don't know. Are there anyone out there who wants to help with my noob question? I don't want any code please. I would rather write the code by my self, but I would like a tip of how to think. //walle

Share on other sites
A queue is the best structure for a snake game.

The head(first in) is pushed onto the queue and the tail(first out) is pushed out.

Here's the basic structure

1. Set queue size
2. Put new head into queue from a the direction your going
3. if the queue is too big, pop a value off.
4. Transverse queue to draw you snake & check for collisions
5. goto 2

If the snake eats a dot, increase the queue size, which will increase your snake's size.

Share on other sites
I am not sure I am understanding your question correctly... But I would think of the tail as a part of the path the snake head has traveled before. So you'd need to store a certain number (depending on the length of the snake) of the last known positions of the snake's head. Well, and maybe the direction the head was looking at at that position.

Does this help at all?

Share on other sites
Ok. thanks for the quick replies.

Binomine

What is a queue ( I use c++, but I've never herd of it) is it c++?

If it's like an array, why do you pop one of if it's too big?

And (a little embarising) could you explane "Transverse" a little more, don't know the swedish word for it.

Kassandra

Now I don't really understand what you aim at. What relevance does the old direction matter? The new I can understand, but if you could explane it I would be greatful.

//walle

Share on other sites
Just an idea... and maybe not a good one but....

Maybe you could keep a movement "queue", so when the head moves one forward then you store that movement in the queue and when the given delay (length of tail) has passed, then the tail starts "playing" back the heads movements. So, the queue would be a FIFO (First In First Out) type of queue.

Example:
Head movement (1 move = 1 tick) delay = 6 ticks
Left
Left
Up
Right
Up
Up

Tail Movement (After delay)
Left
Left
Up
Right
Up
Up

Again, just an idea... let me know what you think.

<EDIT>
Too late, someone already suggested this as I was writing my post :(

Share on other sites
To simplify what Binomine said, you basically need to keep a list of where the snake has been. As the snake moves foward, you use the list of old positions to erase the positions that are too far back. If the snake was 3 units long for example, you would erase the 3rd unit (old tail position), move the positions down so #2 becomes #3 and #1 becomes #2, then make #1 be where the head has just moved to.

A queue is a data structure that would make such operations easy. I believe C++ has one but I'm not sure on the details.

Traverse means to go through all the elements of the list in this case.

Share on other sites

Akusei

I do really like the idea. I asume by the edit you made this is what Binomine ment?

Ok. Then my question is: how do you use queues?

//walle

Share on other sites
Quote:
 Original post by walleNow I don't really understand what you aim at. What relevance does the old direction matter? The new I can understand, but if you could explane it I would be greatful.

I can try, I am having difficulties finding the right words to explain what I mean.

Assuming that the image you are using to display the snake's tail has a certain direction - like the head has a certain direction it needs to be displayed in to make sense, meaning the eyes and the snout/muzzle (whatever the mouth of a snake is called in English) always have to point in the direction the snake is going in - you would need to know what direction the head was looking at when it was at that position (where you are now displaying a piece of the snake's tail) to display the tail's image correctly. To not accidently turn it around, like having it appear sideways.

So if this is the snake's head: ->
And this would be used for displaying its tail: -

You would want it to look like this:
-->
|
|
----

And not like this:

-->
-
-
-----

Do you understand me now? I don't even know if this is relevant for you or if you already knew or didn't even want to know anything going in this direction - since I am not sure if I understood your question correctly. And I apologize for my bad explanation...

Share on other sites
Another way to do this (I remember doing this myself many a year ago) is to store the direction of each "piece" of snake on the map, and also store the location of the head and tail. (The map being the array or whatever that you use to store the structure of the level). For this method you do not need a queue.

When you want the tail to move:
1) Look up the direction the tail is pointing, by reading the map data that occupies the location of the tail.
2) Write over the map at the location of the tail with "empty".
3) Move the tail in the direction obtained in 1.

To move the head, write the direction that you want to move the snake to onto the map at the position of the head, then move the head, then write "snake-x" onto the new position of the head.

1) IMHO this is way simpler.
2) Uses less dynamic memory.
3) Easier to draw if you draw the pieces of snake when they are seen on the map.
4) Makes collisions easy.

1) Makes the map "tile" structure more complex.
2) Slightly harder to find the 'nth' piece of snake.
3) Harder to draw if you want to draw the whole snake at once.

A basic tile structure. (Tile = single element of the map).
struct tile {    byte type; // wall, snake-1, snake-2, empty etc.    byte direction;}

Share on other sites
Kassandra

Ok. (how do you spell out ok? have totaly slipped my mind. And I'm getting tired of saying ok)

Now I totaly get what you mean, good explanation with the images =)

I had'nt really thougt about it, I planed to use a plain circle at first (I'm not really good att drawing) and mayby later make it look a little nicer. So that is the reason I didn't understand you compleatly.

//walle

Share on other sites
C++ has the Standard Template Library. I'm not too experienced with it myself, but I am pretty sure it includes a class to implement a queue.

as for the direction, I would just use an enum for the directions (up, down, left, right), and update the head's new position based on the state of a flag that keeps track of the current direction.
(if flag is set to up, subtract from X, etc). I would then copy the positions down the queue and redraw for each cycle, with each position in the queue representing a segment of the snake's body.

When the snake increases its length, I would push a container onto the queue that is initialized to the new position of the head.

As for collision detection, I would check for a condition where the position of the head is equal to the position of any other part of the snake's body.

This is all off the top of my head, so some of it might not make sense. If you need any further help, I can try my best to clarify.

*Edit* heh, looks like my help isn't needed after all.

Share on other sites
Krylloan

What does IMHO stand for?

//walle

Share on other sites
IMHO = In my humble opinion
IMO = In my opinion

Share on other sites
Quote:
 Original post by ExtrariusA queue is a data structure that would make such operations easy. I believe C++ has one but I'm not sure on the details.

You're absolutely right, it's inside queue, and it's called std::queue.

Personally I would do this by storing the coordinates at which the snake exists. And since you (presumably) want the snake to die when it touches itself I would store in each tile a bool which indicates whether the snake is there; flag it as true when the snake enters the tile and flag it as false when the snake enters the tile.

So roughly you might have:

class Snake {std::queue<Tile> mTiles;void UpdatePosition(Tile nextTile){    Tile t;    mTiles.pop(t);    t.UnflagSnake();    if(nextTile.FlaggedForSnake())        CrashBurnAndDie();    else    {        nextTile.FlagSnake();        mTiles.push(nextTile);    }}}

Share on other sites
Don't you have to include a header file to use the queue class?

I know you have to include the vector header when using vectors.

I just looked, and there is a header for queue.

Share on other sites
I suggest a simple dynamic array that you move with memmove() and resize with realloc().

Share on other sites
he might as well use a vector instead of putting the effort into coding a dynamic array.

Share on other sites
He might as well just use a queue, since it's perfect for the task and there's on in the standard library. Oh, and you're quite right, KingFred -- you have to #include<queue> to use a queue (intuitive, ain't it?).

Share on other sites
yeah, I could see how queue would be perfect for the task. push the head, pop the tail. Yes, it is intuitive if you've used STL before. If you haven't you may not be aware you need to include a header.

[Edited by - KindFred on November 24, 2004 1:34:38 PM]

Share on other sites
Yes. A queue sounds perfect for the job.

I'll have to read up on them thoug...but "knowlege is a light burden". (spelling is crappy i guess)

Thanks for all ideas.

//walle

Create an account

Register a new account

• Forum Statistics

• Total Topics
628400
• Total Posts
2982446

• 10
• 9
• 19
• 24
• 10