Kudos for learning to program, but I'm going to say the best thing you could probably do would be to find a c++ snake game tutorial online, there are lots if you google it.
I'd say that would probably be the worst thing.
You'll certainly find a lots that use plain old arrays, or worse
new[] and
delete[], or even worse self-built data structures. Global variables, reinvented wheels, and general bad style is unfortunately very common in C++ tutorials on the internet, especially in those on YouTube. By learning from internet tutorials, you get used to a lot of bad habits that are difficult to get rid of. Of course there are exceptions.
Anyway, wizh, you're doing it far too complicated. In order to draw a snake, it is enough to store a list of segments, for example in the STL container
std::deque. One possibility is to have a pure logical class called
Segment that stores the position (tile indices, not world units) of the segment, and possibly its type.
struct Segment
{
enum Type { Head, Body, Tail };
Type type;
sf::Vector2i gridPosition;
};
class Game
{
...
private:
std::deque<Segment> segments;
};
In each step, you remove the last segment with
pop_back() and insert a new one with
push_front(). If you use different segment types, you have to adapt the front one before inserting the new head.
Of course you can also iterate through all segments and just update their positions, that requires less memory allocations. In this case, you could also use
std::vector (in fact, for such tiny sizes the container choice is almost irrelevant, so you choose the one that's easiest to handle). There are many possibilities, but it's important to have a clear view of the parts of your game. This is where classes help a lot.
To render, you can just loop through all segments, create a sprite for each segment on the fly, and draw it. This won't be a performance issue. Otherwise you could still store the sprite in the segment, but it's usually cleaner to keep graphics and logics separated.
Also, don't mix event handling with game logics. Upon user inputs, you just set a variable such as the direction, but you don't change the snake directly. The snake (describing the gameplay) is modified during the update step of your game, which usually happens in regular intervals.