Reputation:
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
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
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