Sávio Brilhante
Sávio Brilhante

Reputation: 25

Problem with drawGame function in a Snake Game

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:

enter image description here

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

Answers (2)

Thomas Matthews
Thomas Matthews

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.

Some example code:

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';
}

Printing the board:

std::cout << game_board;

or

std::cout.write(&game_board[0][0], sizeof(game_board) - 1U); // Don't print terminating nul.

Checking for fruit encounter

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

Amir Kirsh
Amir Kirsh

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

Related Questions