If statement with coords seems to be slightly off

Hello, I have made a snake game because I thought it would be something fun to make for practice. There is one slight bug that I noticed. it is with my "Head hits body" part. Seems to not always work especially when it is shorter(PS the loop starts at 3 because I figured that if the squares are 2x2 it would be impossible to run into itself with there being any less than 4 pieces of the snake).
Here is my code any suggestions would be greatly appreciated I am fairly sure it is because of my "addTail" function on line 148 or or my if statement on line 338 but everything I try seems to not work unfortunately =/

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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
#include <iostream>
#include <windows.h>
#include <conio.h>
#include <time.h>
#include <vector>

class Console {
public:
    void setTitle( void )
    {
        SetConsoleTitle( L"Snake - Andrew ******" );
    }

    void hideCursor( void )
    {
        const CONSOLE_CURSOR_INFO info = { 1, false };

        const HANDLE handle = GetStdHandle( STD_OUTPUT_HANDLE );
        SetConsoleCursorInfo( handle , &info );
    }

    const char keyPressed()
    {
        char ch = char();
        if( kbhit() )
        {
            ch = getch();
            return( ch );
        }
    }

    void goToXY( const unsigned int X , const unsigned int Y )
    {
        HANDLE handle = GetStdHandle( STD_OUTPUT_HANDLE );
        COORD position = { X , Y };
        SetConsoleCursorPosition( handle , position );
    }

    void colorText( const char ch )
    {
        HANDLE handle = GetStdHandle( STD_OUTPUT_HANDLE );
        switch(ch)
        {
        case 'S':
            SetConsoleTextAttribute( handle , 2 );
            break;
        case 'B':
            SetConsoleTextAttribute( handle , 14 );
            break;
        case 'T':
            SetConsoleTextAttribute( handle , 12 );
            break;
        default:
            SetConsoleTextAttribute( handle , 7 );
        }
    }

};

class Game {
    Console c;

public:
    const char drawBackground( void )
    {
        c.goToXY( 0 , 24);
        std::cout << ( char ) -56 << std::flush;
        c.goToXY( 79 , 24 );
        std::cout << ( char ) -68 << std::flush;
        c.goToXY( 0 , 2 );
        std::cout << ( char ) -55 << std::flush;
        c.goToXY( 79 , 2 );
        std::cout << ( char ) -69 << std::flush;
        for( unsigned int i = 3; i < 24; i++ )
        {
            c.goToXY( 0 , i );
            std::cout << ( char ) -70 << std::flush;
            c.goToXY( 79 , i );
            std::cout << ( char ) -70 << std::flush;
        }
        for( unsigned int i = 1; i < 79; i++ )
        {
            c.goToXY( i ,  2 );
            std::cout << ( char ) -51 << std::flush;
            c.goToXY( i , 24 );
            std::cout << ( char ) -51 << std::flush;
        }
    }

    const std::vector < unsigned int > getDirection( const char input , unsigned int direction )
    {
        std::vector < unsigned int > directions;
        unsigned int prevDirection = int();
        switch( input )
        {
        case 'd': case 'D':
            if( direction != 3 )
            {
                prevDirection = direction;
                direction = 1;
            }
            break;
        case 'w': case 'W':
            if( direction != 4 )
            {
                prevDirection = direction;
                direction = 2;
            }
            break;
        case 'a': case 'A':
            if( direction != 1 )
            {
                prevDirection = direction;
                direction = 3;
            }
            break;
        case 's': case 'S':
            if( direction != 2 )
            {
                prevDirection = direction;
                direction = 4;
            }
            break;
        case 27:
            direction = 5;
            break;
        }
        directions.push_back( prevDirection );
        directions.push_back( direction );
        return( directions );
    }

    const std::vector < char > drawSnake( const unsigned int pieces )
    {
        std::vector < char > snake;
        for( unsigned int i = 0; i < pieces; i++ )
        {
            if( i == 0 )
            {
                snake.push_back( ( char ) 2 );
            } else {
                snake.push_back( ( char ) 4 );
            }
        }
        return( snake );
    }
    const std::vector < std::vector < unsigned int > > addTail( std::vector < std::vector < unsigned int > > oldPositions , const unsigned int direction )
    {
        std::vector < std::vector < unsigned int > > newPositions;
        std::vector < unsigned int > x , y;
        const unsigned int size = oldPositions[0].size() - 1;
        x = oldPositions[0];
        y = oldPositions[1];
        switch( direction )
        {
        case 1:
            x.push_back( x[size] - 1 );
            y.push_back( y[size] );
            break;
        case 2:
            x.push_back( x[size] );
            y.push_back( y[size] + 1 );
            break;
        case 3:
            x.push_back( x[size] + 1 );
            y.push_back( y[size] );
            break;
        case 4:
            x.push_back( x[size] );
            y.push_back( y[size] - 1 );
            break;
        }

        newPositions.push_back( x );
        newPositions.push_back( y );
        return( newPositions );
    }

    const std::vector < std::vector < unsigned int > > moveSnake( std::vector < std::vector < unsigned int > > oldPositions , const unsigned int direction )
    {
        std::vector < std::vector < unsigned int > > newPositions;
        std::vector < unsigned int > x , y;
        const unsigned int size = oldPositions[0].size();
        x = oldPositions[0];
        y = oldPositions[1];

        for( unsigned int i = size - 1; i > 0; i-- )
        {
            x[i] = x[i-1];
            y[i] = y[i-1];
        }

        switch( direction )
        {
        case 1:
            x[0]++;
            break;
        case 2:
            y[0]--;
            break;
        case 3:
            x[0]--;
            break;
        case 4:
            y[0]++;
            break;
        }

        newPositions.push_back( x );
        newPositions.push_back( y );
        return( newPositions );
    }

    const unsigned int random( const unsigned int min , const unsigned int max )
    {
        srand( time( NULL ) );
        return( rand() % ( max - min + 1 ) + min );
    }

    const std::vector < unsigned int > addFood( void )
    {
        unsigned int posX , posY;
        std::vector < unsigned int > vec;
        posX = random( 1, 78 );
        posY = random( 3, 23 );
        c.goToXY( posX, posY );
        std::cout << ( char ) 15 << std::flush;
        vec.push_back( posX );
        vec.push_back( posY );
        return( vec );

    }

    void displayGoodbye(void)
    {
        c.goToXY( 25, 10 );
        std::cout << "Game over." << std::flush;
        c.goToXY( 25, 11 );
    }
};


Code is slightly too long ( by about 1000 characters so the main function will be on next reply. )
Last edited on
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
int main( void )
{
    unsigned int prevDirection = 1 , direction = 1 , score = 0 , pieces = 1;
    bool quit = false;
    Game g;
    Console c;
    c.colorText('T');
    c.setTitle();
    c.hideCursor();
    c.colorText('B');
    g.drawBackground();
    c.goToXY( 4, 4 );
    c.colorText('S');
    std::cout << ( char ) 2 << std::flush;
    c.colorText('T');
    std::vector < unsigned int > vec = g.addFood();
    std::vector < std::vector < unsigned int > > snakeXY;
    std::vector < unsigned int > snakeX(1,4), snakeY( 1,4 );
    std::vector < char > snake = g.drawSnake( pieces );
    snakeXY.push_back( snakeX );
    snakeXY.push_back( snakeY );

    c.goToXY( 0 , 0 );
    std::cout << "Press Esc to quit.\nUse WASD or Arrows to change direction." << std::flush; //didn't get around to Arrow keys yet
    c.goToXY( 70 , 0 );
    std::cout << " time:" << 0 << std::flush;
    c.goToXY( 70 , 1 );
    std::cout << "score:" << 0 << std::flush;
    c.goToXY( 25 , 10 );
    std::cout << "Press any key to start..." << std::flush;
    for( ; ; )
    {
        if( c.keyPressed() != char() )
        {
            for( signed int i = 3; i > -1; i-- )
            {
                c.goToXY( 25 , 10 );
                std::cout << "                          " << std::flush;
                c.goToXY( 25 , 10 );
                std::cout << "              " << i << std::flush;
                if( i != 0 )
                {
                    Sleep( 1000 );
                }
            }
            break;
        }
    }

    for( ; ; )
    {
        static unsigned int timeNum = 1;
        timeNum++;
        if( timeNum == 10 )
        {
            c.goToXY( 25 , 10 );
            std::cout << "                " << std::flush;
        }
        c.colorText('T');
        c.goToXY( 70 , 0 );
        std::cout << " time:" << timeNum/10 << std::flush;
        c.goToXY( 70 , 1 );
        std::cout << "score:" << score << std::flush;
        std::vector < unsigned int > directions = g.getDirection( c.keyPressed() , direction );
        prevDirection = directions[0];
        direction = directions[1];
        c.goToXY( snakeX[pieces-1] , snakeY[pieces-1] );
        std::cout << " " << std::flush;
        snakeXY = g.moveSnake( snakeXY , direction );
        snakeX = snakeXY[0];
        snakeY = snakeXY[1];

        for( unsigned int i = 0; i < pieces; i++ )
        {
            c.goToXY(snakeX[i], snakeY[i]);
            c.colorText('S');
            std::cout << snake[i] << std::flush;
            c.colorText('T');
        }

        std::vector < unsigned int > headPosition;
        headPosition.push_back( snakeX[0] );
        headPosition.push_back( snakeY[0] );

        if( headPosition == vec )
        {
            vec = g.addFood();
            score++;
            ++pieces;
            snake = g.drawSnake( pieces );
            snakeXY = g.addTail( snakeXY, direction );
        }
        for( unsigned int i = 3; i < pieces; i++ )
        {
            if( snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i] )
            {
                quit = true;
            }
        }
        switch( headPosition[0] )
        {
        case 0: case 79:
            g.displayGoodbye();
            quit = true;
        }

        switch( headPosition[1] )
        {
        case 2: case 24:
            g.displayGoodbye();
            quit = true;
        }

        if( direction == 5 )
        {
            quit = true;
        }

        if( quit == true )
        {
            g.displayGoodbye();
            break;
        }
        Sleep( 100 );
    }
    return(0);
}
Last edited on
Rewrote but same problem
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
#include <iostream>
#include <windows.h>
#include <conio.h>
#include <vector>
#include <time.h>

namespace CONSOLE
{
    void setTitle( void )
    {
        SetConsoleTitle( L"Snake - Andrew Gibson - 2.0" );
    }

    void hideCursor( void )
    {
        HANDLE outHandle = GetStdHandle( STD_OUTPUT_HANDLE );
        SetConsoleCursorInfo( outHandle , false );
    }

    void gotoXY( const unsigned int x , const unsigned int y )
    {
        HANDLE outHandle = GetStdHandle( STD_OUTPUT_HANDLE );
        COORD position = { x , y };
        SetConsoleCursorPosition( outHandle , position );
    }

    const unsigned char keyPressed( void )
    {
        unsigned char input;
        input = getch();
        return( input );
    }

    void textColor( const unsigned int color )
    {
        HANDLE outHandle = GetStdHandle( STD_OUTPUT_HANDLE );
        SetConsoleTextAttribute( outHandle , color );
    }
}

class Snake
{
public:
    unsigned int size;
    std::vector< unsigned int > x , y;
    std::vector< unsigned char > snake;

    Snake( void )
    {
        size = 1;
        x.push_back( 4 );
        y.push_back( 4 );
        snake.push_back( 2 );
    }

    void addSegment( const unsigned int direction )
    {
        switch( direction )
        {
        case 1:
            x.push_back( x[ size - 1 ] - 1 );
            y.push_back( y[ size - 1 ] );
            snake.push_back( 4 );
            size++;
            break;
        case 2:
            x.push_back( x[ size - 1] );
            y.push_back( y[ size - 1 ] + 1 );
            snake.push_back( 4 );
            size++;
            break;
        case 3:
            x.push_back( x[ size - 1 ] + 1 );
            y.push_back( y[ size - 1 ] );
            snake.push_back( 4 );
            size++;
            break;
        case 4:
            x.push_back( x[ size - 1 ] );
            y.push_back( y[ size - 1 ] - 1 );
            snake.push_back( 4 );
            size++;
            break;
        }
    }

    void moveSnake( const unsigned int direction )
    {
        for( unsigned int i = size - 1; i > 0; i-- )
        {
            x[ i ] = x[ i - 1 ];
            y[ i ] = y[ i - 1 ];
        }

        switch( direction )
        {
        case 1:
            x[ 0 ]++;
            break;
        case 2:
            y[ 0 ]--;
            break;
        case 3:
            x[ 0 ]--;
            break;
        case 4:
            y[ 0 ]++;
            break;

        }
    }
};

class Food
{
public:
    unsigned int x , y;
    unsigned char food;
    Food( void )
    {
        srand( ( unsigned ) time( NULL ) );
        x = ( rand() % ( 78 ) ) + 1;
        y = ( rand() % ( 23 ) ) + 1;
        food = (char) 15;
    }
};

namespace GAME
{
    void drawMap( void )
    {
        CONSOLE::gotoXY( 0 , 24);
        std::cout << ( char ) -56 << std::flush;
        CONSOLE::gotoXY( 79 , 24 );
        std::cout << ( char ) -68 << std::flush;
        CONSOLE::gotoXY( 0 , 0 );
        std::cout << ( char ) -55 << std::flush;
        CONSOLE::gotoXY( 79 , 0 );
        std::cout << ( char ) -69 << std::flush;

        for( unsigned int i = 1; i < 24; i++ )
        {
            CONSOLE::gotoXY( 0 , i );
            std::cout << ( char ) -70 << std::flush;
            CONSOLE::gotoXY( 79 , i );
            std::cout << ( char ) -70 << std::flush;
        }
        for( unsigned int i = 1; i < 79; i++ )
        {
            CONSOLE::gotoXY( i ,  0 );
            std::cout << ( char ) -51 << std::flush;
            CONSOLE::gotoXY( i , 24 );
            std::cout << ( char ) -51 << std::flush;
        }
    }

    void drawSnake( Snake s )
    {
        for( unsigned int i = 0; i < s.size; i++ )
        {
            CONSOLE::gotoXY( s.x[ i ] , s.y[ i ] );
            std::cout << s.snake[ i ] << std::flush;
        }
    }

    void drawFood( Food f )
    {
        CONSOLE::gotoXY( f.x , f.y );
        std::cout << f.food << std::flush;
    }

    void removeLastPiece ( Snake s )
    {
        CONSOLE::gotoXY( s.x[ s.size - 1 ] , s.y[ s.size - 1 ] );
        std::cout << " " << std::flush;
    }

    const bool checkColision ( Snake s )
    {
        if( s.x[ 0 ] == 0 || s.x[ 0 ] == 79 || s.y[ 0 ] == 0 || s.y[ 0 ] == 24 )
        {
            return(true);
        } else {
            for( unsigned int i = 1; i < s.size; i++ )
            {
                if( s.x[ 0 ] == s.x[ i ] && s.y[ 0 ] == s.y[ i ] )
                {
                    return( true );
                } else {
                    return( false );
                }
            }
        }
    }
    
    void clearMap( Snake s, Food f )
    {
        for( unsigned int i = 0; i < s.size; i++ )
        {
            CONSOLE::gotoXY( s.x[ i ] , s.y[ i ] );
            std:: cout << " " << std::flush;
        }
        CONSOLE::gotoXY( f.x , f.y );
        std::cout << " " << std::flush;
    }
    
    const unsigned int getDirection( const unsigned int oldDirection )
    {
        unsigned int newDirection = oldDirection;
    
        switch( CONSOLE::keyPressed() )
        {
        case 'd':
            if( oldDirection != 3 )
            {
                newDirection = 1;
            }
            break;
        case 'w':
            if( oldDirection != 4 )
            {
                newDirection = 2;
            }
            break;
        case 'a':
            if( oldDirection != 1 )
            {
                newDirection = 3;
            }
            break;
        case 's':
            if( oldDirection != 2 )
            {
                newDirection = 4;
            }
            break;
        case 27:
            newDirection = 6;
            break;
        }
        return( newDirection );
    }
}


int main( void )
{
    enum
    {
        black , blue , green , cyan , red , magenta , brown , normal , darkgrey , lightblue , lightgreen , lightcyan , lightred , lightmagenta , yellow , white
    };

    bool play = true , fail = false;
    unsigned int score = 0;

    do
    {
        unsigned int direction = 1 ;
        score = 0;
        Snake *s;
        Food *f;

        s = new Snake;
        f = new Food;

        CONSOLE::gotoXY( 25 , 10 );
        std::cout << "                                       " << std::flush;

        CONSOLE::hideCursor();
        GAME::drawMap();
        GAME::drawSnake( *s );
        GAME::drawFood( *f );

        for ( ; ; )
        {
            if( kbhit() )
            {
                direction = GAME::getDirection( direction );
            }

            if( direction == 6 )
            {
                play = false;
                delete f;
                delete s;
                break;
            }

            GAME::removeLastPiece( *s );
            s->moveSnake( direction );
            GAME::drawSnake( *s );

            if( s->x[ 0 ] == f->x && s->y[ 0 ] == f->y )
            {
                score++;
                s->addSegment( direction );
                delete f;
                f = new Food;
                GAME::drawFood( *f );
            }

            fail = GAME::checkColision( *s );

            if( fail )
            {
                score = 0;
                GAME::clearMap( *s , *f );
                delete f;
                delete s;
                break;
            }

            Sleep( 150 );
        }
        CONSOLE::gotoXY( 25 , 10 );
        std::cout << "Would you like to play again? <y/n> " << std::flush;
        if( CONSOLE::keyPressed() == 'y' )
        {
            play = true;
        } else {
            play = false;
        }
    } while( play );

    CONSOLE::gotoXY( 25 , 10 );
    std::cout << "                                    " << std::flush;
    CONSOLE::gotoXY( 25 , 10 );
    std::cout << "Game Over." << std::flush;
    CONSOLE::gotoXY( 25 , 11 );
    std::cout << "Score: " << score << std::flush;
    CONSOLE::gotoXY( 0 , 25 );
}

Any suggestions?
Tried moving "hit" function before moving snake doesn't work
Last edited on
I knew there was something wrong with my "hit" function but I couldn't seem to wrap my finger around it then I tried to use the code with out calling the function and realized what my problem was. I had a loop and if statement and if it hit then it returned true and if it didn't hit it returned false. The problem was that I forgot to break the loop after it returned true and if it did not collide it needs to return false. fixed solution:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    const bool checkColision ( Snake s )
    {
        bool noReturn = true;
        if( s.x[ 0 ] == 0 || s.x[ 0 ] == 79 || s.y[ 0 ] == 0 || s.y[ 0 ] == 24 )
        {
            return( true );
            noReturn = false;
        } else {
            for( unsigned int i = 1; i < s.size; i++ )
            {
                if( s.x[ 0 ] == s.x[ i ] && s.y[ 0 ] == s.y[ i ] )
                {
                    return( true );
                    noReturn = false;
                    break;
                }
            }
        }
        if( noReturn )
        {
            return( false );
        }
    }
Last edited on
Topic archived. No new replies allowed.