Reputation: 25
I'm programming a Snake Game in C++ in order to learn more about C ++. I made the game using the paradigms of object-oriented programming, but the design of the drawGame function is not working properly.
Testing the drawGame function, I'm getting this as result:
void Game::drawGame(int fruitxpos, int fruitypos, std::vector<int>& xposition, std::vector<int>& yposition, int snakesize){
system("cls");
int printedflag = 0;
for(int j = 1; j <= ysize; j++){
if(j == 1 || j == ysize){
for(int i = 1; i <= xsize; i++){
std::cout << "#";
}
std::cout << "\n";
}
else{
for(int i = 1; i <= xsize; i++){
if(i == 1 || i == xsize){
std::cout << "#";
}
else{
for(int n = 0; n <= snakesize; n++){
if(i == xposition[n] && j == yposition[n]){
std::cout << "o";
printedflag = 1;
}
else{
printedflag = 0;
}
}
if(!printedflag){
if(i == fruitxpos && j == fruitypos){
std::cout << "F";
}
else{
std::cout << " ";
}
}
}
}
std::cout << "\n";
}
}
}
As you can see, It is printing a blank space after every snake block. Could someone explain me what is wrong?
Upvotes: 0
Views: 615
Reputation: 57749
IMHO, your program would be better by using a 2d matrix of characters. Your main program will write into the matrix. A print function would print the matrix. This eliminates the worry of having to use X,Y positioning on the console.
If you design the matrix as a {contiguous} array of characters, you can add an extra column for the newline character. The last cell of the matrix would be the nul character, '\0'. This allows you to print the matrix as if it was one long C-Style string.
const unsigned int MAX_COLUMNS = 20U + 1U; // +1 column for newline
const unsigned int MAX_ROWS = 20U;
char game_board[MAX_ROWS][MAX_COLUMNS];
void Clear_Board()
{
// Fill the board with spaces (blanks).
memset((char *) &game_board[0][0], ' ', sizeof(game_board));
// Draw the top and bottom borders
for (unsigned int column = 0; column < MAX_COLUMNS; ++column)
{
game_board[0][column] = '#';
game_board[MAX_ROWS - 1][column] = '#';
}
// Draw the side borders
const unsigned int LEFT_COLUMN = 0U;
const unsigned int RIGHT_COLUMN = MAX_COLUMNS - 2U;
const unsigned int NEWLINE_COLUMN = MAX_COLUMNS - 1U;
for (unsigned int row = 0; row < MAX_ROWS; ++row)
{
game_board[row][LEFT_COLUMN] = '#';
game_board[row][RIGHT_COLUMN] = '#';
game_board[row][NEWLINE_COLUMN] = '\n';
}
// Set the terminating nul character
game_board[MAX_ROWS - 1][MAX_COLUMNS - 1] = '\0';
}
std::cout << game_board;
or
std::cout.write(&game_board[0][0], sizeof(game_board) - 1U); // Don't print terminating nul.
unsigned int snake_head_row = 10U; // Example position.
unsigned int snake_head_column = 5u;
const char FRUIT_CHAR = 'F';
//...
if (game_board[snake_head_row][snake_head_column] == FRUIT_CHAR)
{
//...
}
Notice that the fruit encounter doesn't need printing.
IMHO, you should have the snake as a container of coordinates (row, column). Each body cell is an item in the container. If the snake grows, append a coordinate to the container. Drawing the snake involves traversing the container, placing snake characters at the appropriate game_board
positions (then drawing the board).
A game board helps remember the position of the snake body and any other items on the board. You can use a console positioning library and put the characters at their coordinates, too.
Upvotes: 2
Reputation: 13852
Suggesting to split your Game::drawGame
into sub-functions.
Also, probably the method should not get all the parameters you pass to it as they all should better be class members.
void Game::drawGame() {
drawBoard();
drawSnake();
drawFruits();
}
Then you may want to use gotoxy
that can be found on the web, e.g. here, e.g. for windows:
void gotoxy(int x, int y) {
HANDLE hc = GetStdHandle(STD_OUTPUT_HANDLE); // get console handle
COORD cursor = { x, y };
SetConsoleCursorPosition(hc, cursor); // set new cursor position
}
Upvotes: -1