user9022438
user9022438

Reputation:

Why is my snake only moving up?

I have started to code Snake in C++. Here is my code so far.

main.cpp:

#include "game.hpp"

int main(void)
{
    Game game;

    int count = 0;  

    while(game.program_is_running)
    {
        game.key_events();

        if(count >= 3000)
        {
            game.tick();
            count = 0;
        }
        else
            count++;
    }

    return 0;
}

game.hpp:

#include <iostream>
#include <conio.h>
#include <stdlib.h>
#include <vector>

#include "snake.hpp"

#define NUMBER_OF_ROWS 25
#define NUMBER_OF_COLUMNS 25

class Game
{
public:

    Game(void);

    void tick(void);
    void key_events(void);

    bool program_is_running;

private:

    char grid[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS];

    Snake snake;

    bool right_pressed, left_pressed, down_pressed, up_pressed;

    void display_grid(void);
};

Game::Game(void)
{
    for(int y = 0; y < NUMBER_OF_ROWS; y++)
    {
        for(int x = 0; x < NUMBER_OF_COLUMNS; x++)
        {
            if(y == 0 || y == NUMBER_OF_ROWS - 1)
                grid[y][x] = '#';
            else if(x == 0 || x == NUMBER_OF_COLUMNS - 1)
                grid[y][x] = '#';
            else
                grid[y][x] = ' ';
        }
    }

    program_is_running = true;

    right_pressed = false;
    left_pressed = false;
    down_pressed = false;
    up_pressed = false;
}

void Game::tick(void)
{
    for(int y = 0; y < NUMBER_OF_ROWS; y++)
    {
        for(int x = 0; x < NUMBER_OF_COLUMNS; x++)
        {
            if(y == 0 || y == NUMBER_OF_ROWS - 1)
                grid[y][x] = '#';
            else if(x == 0 || x == NUMBER_OF_COLUMNS - 1)
                grid[y][x] = '#';
            else
                grid[y][x] = ' ';
        }
    }

    std::vector<Block> snake_body = snake.get_body();

    if(right_pressed)
    {
        snake.move(0, 1);
    }
    else if(left_pressed)
    {
        snake.move(0, -1);
    }
    else if(down_pressed)
    {
        snake.move(1, 0);
    }
    else if(up_pressed)
    {
        snake.move(-1, 0);
    }

    for(int y = 0; y < NUMBER_OF_ROWS; y++)
    {
        for(int x = 0; x < NUMBER_OF_COLUMNS; x++)
        {
            for(int i = 0; i < snake_body.size(); i++)
            {
                if(snake_body[i].y == y && snake_body[i].x == x)
                {
                    grid[y][x] = snake.get_symbol();
                }
            }
        }
    }

    display_grid();
}

void Game::key_events(void)
{
    char c;

    if(kbhit())
    {
        c = _getch();

        switch(c)
        {
            case 'q':
                program_is_running = false;

            case 'l':
                left_pressed = false;
                down_pressed = false;
                up_pressed = false;
                right_pressed = true;

            case 'h':
                right_pressed = false;
                down_pressed = false;
                up_pressed = false;
                left_pressed = true;

            case 'j':
                right_pressed = false;
                left_pressed = false;
                up_pressed = false;
                down_pressed = true;

            case 'k':
                right_pressed = false;
                down_pressed = false;
                left_pressed = false;
                up_pressed = true;
        }
    }
}

void Game::display_grid(void)
{
    system("cls");

    for(int y = 0; y < NUMBER_OF_ROWS; y++)
    {
        for(int x = 0; x < NUMBER_OF_COLUMNS; x++)
        {
            std::cout << grid[y][x] << ' ';
        }

        std::cout << std::endl;
    }
}

snake.hpp:

#include <vector>

struct Block
{
    int y, x;
};

class Snake
{
public:

    Snake();

    std::vector<Block> get_body();
    char get_symbol(void);

    void add_block(int, int);
    void move(int, int);

private:

    std::vector<Block> body;
    char symbol;
};

Snake::Snake(void)
{
    symbol = 'X';

    add_block(12, 12);
}

std::vector<Block> Snake::get_body()
{
    return body;
}

char Snake::get_symbol(void)
{
    return symbol;
}

void Snake::add_block(int y, int x)
{
    Block block;
    block.y = y;
    block.x = x;
    body.push_back(block);
}

void Snake::move(int y, int x)
{
    body[0].y += y;
    body[0].x += x;
}

At the moment I am just trying to get the snake to move up, down, left and right with the keys k, j, h and l. No matter which of the four keys you press, the snake will only move up. Why is this? Also, I would appreciate if someone could give advice on how to structure the program.

Upvotes: 0

Views: 134

Answers (2)

ELIZA
ELIZA

Reputation: 61

You don't have break; after your case:'s end, so your switch statement will execute every case, and because "up" is the last case, it will override all others.

Upvotes: 1

doctorlove
doctorlove

Reputation: 19282

The switch

switch(c)
{
    case 'q':
        program_is_running = false;

    case 'l':
        left_pressed = false;
        down_pressed = false;
        up_pressed = false;
        right_pressed = true;

    case 'h':
        right_pressed = false;
        down_pressed = false;
        up_pressed = false;
        left_pressed = true;

    case 'j':
        right_pressed = false;
        left_pressed = false;
        up_pressed = false;
        down_pressed = true;

    case 'k':
        right_pressed = false;
        down_pressed = false;
        left_pressed = false;
        up_pressed = true;
}

always falls through to the last case, 'k', so you will always end up with

        right_pressed = false;
        down_pressed = false;
        left_pressed = false;
        up_pressed = true;

You should add break at the end of each case to avoid this.

In terms of style, I wonder if you can collapse down the four booleans for four mutually exclusive events into one flag showing the value to move by?

You could have a lookup table (unordered map or similar), mapping the key to the move parameters, and just call move without needing the switch statement.

Upvotes: 4

Related Questions