Strange Error, Possibly Linked With Deque

Recently I have been trying to remake the classic game Snake in C++. I came across this strange error which had no logically deductible cause (I'm probably just missing something).

The error returned the message "first defined here" and then "error: ld returned exit status". Also, more curiously the C++ standard library header for deque opened up in my IDE. I use Code::Blocks as my IDE and mingw as my compiler.

Snake.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  #ifndef SNAKE_H_INCLUDED
#define SNAKE_H_INCLUDED
#include <deque>

class SnakeHead {
public:
    int posX, posY;
private:

    // Snake head functions
    void input();
    void movement();

    // Checks if the snake ate a fruit or hit its tail or the wall
    void collision_detec(int height, int width);
};

class SnakePart {
public:
    // Manages snake tail
    std::deque<SnakePart> parts;

    // Cycles/adds tail
    void advance(int x, int y, bool loose_tail);
    SnakePart() = default;
private:
    int x, y;
    SnakePart(int x, int y) : x(x), y(y){}
};

#endif // SNAKE_H_INCLUDED


SnakeHead.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <conio.h>
#include "Snake.h"
#include "Game.h"

// Direction constants
enum eDirection {UP, DOWN, LEFT, RIGHT, STOP};
eDirection dir = STOP;

// Function for turning left
void turnLeft() {
    switch(dir) {
    case UP :
        dir = LEFT;
        break;
    case DOWN :
        dir = RIGHT;
        break;
    case LEFT :
        dir = DOWN;
        break;
    case RIGHT :
        dir = UP;
        break;
    case STOP :
        dir = LEFT;
        break;
    }
}

// Function for turning right
void turnRight() {
    switch(dir) {
    case UP :
        dir = RIGHT;
        break;
    case DOWN :
        dir = LEFT;
        break;
    case LEFT :
        dir = UP;
        break;
    case RIGHT :
        dir = DOWN;
        break;
    case STOP :
        dir = RIGHT;
        break;
    }
}

// Controls
void SnakeHead::input() {
    if (kbhit()) {
        switch(getch()) {
        case 'w' : case 'W' :
            if (dir == STOP)
                dir = UP;
            break;
        case 'a' : case 'A' :
            turnLeft();
            break;
        case 's' : case 'S' :
            if (dir == STOP)
                dir = DOWN;
            break;
        case 'd' : case 'D' :
            turnRight();
            break;
        }
    }
}

// Movement
void SnakeHead::movement() {
    switch (dir) {
    case LEFT :
        --posX;
        break;
    case RIGHT :
        ++posX;
        break;
    case UP :
        --posY;
        break;
    case DOWN :
        ++posY;
        break;
    }
}

void SnakeHead::collision_detec(int height, int width) {
    if (posX >= width || posX < 0)
        game.setGameOver();
}


SnakePart.cpp
1
2
3
4
5
6
7
8
9
10
#include "Snake.h"


void SnakePart::advance(int x, int y, bool loose_tail = true) {
        parts.emplace_front(SnakePart{x, y});

        if(loose_tail)
            parts.pop_back();
}


Game.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED

class Game {
public:
    void init();

    // Setter
    void setGameOver() {
        gameOver = true;
    }

    // Getter
    bool isGameOver() {
        return gameOver;
    }
private:
    int width = 20;
    int height = 20;
    bool gameOver = false;
};

// Global game variable
Game game;

#endif // GAME_H_INCLUDED


Game.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#ifndef GAME_H_INCLUDED
#include "Game.h"
#endif // GAME_H_INCLUDED

#ifndef SNAKE_H_INCLUDED
#include "Snake.h"
#endif // SNAKE_H_INCLUDED

#ifndef FRUIT_H_INCLUDED
#include "Fruit.h"
#endif // FRUIT_H_INCLUDED

void Game::init() {
    SnakeHead head;
    SnakePart tail;

    Fruit fruit;

    head.posX = width/2;
    head.posY = height/2;

    tail.advance(head.posX, head.posY, true);

    fruit.respawnFruit(width, height);
}


The rest of the files were left out due to me believing they are irrelevant to the error. If you would like to see them don't hesitate to tell me.
Last edited on
"first defined here" is a hint not the error. The error is most likely on line 24 in Game.h.

Line 24: Copy the definintion to Game.cpp then add extern: extern Game game; in Game.h

Otherwise if you #include Game.h more than once you will have the definition of game more than once and the linker will fail.
Thanks
Topic archived. No new replies allowed.