We’re rewarding the question askers & reputations are being recalculated! Read more.
3 Copy edited (e.g. ref. <http://en.wikipedia.org/wiki/C%2B%2B>).
source | link

My first c++C++ game (snake console game)

I finally finished the code for a snake game iI was working on. I would like it if you were to give me some advice as to things that can be improved.

#ifndef UNICODE
#define UNICODE
#endif

#include <iostream>
#include <Windows.h>
#include <conio.h>
#include <ctime>
#include <random>
#include <queue>
#include "Snake_segment.h"

typedef std::deque<Snake_segment> Snake_container;

const enum direction {
    UP = 0,
    RIGHT,
    DOWN,
    LEFT 
};

// Constant variables
int nScreenWidth;
int nScreenHeight;
const int nFieldWidth = 40;
const int nFieldHeight = 15;

int score = 0;
bool bIsHit = true;
direction dir = direction::RIGHT;

void clear(wchar_t* buf);
void update(HANDLE hConsole, Snake_container& body, wchar_t* buf);
void directionCheck(char value);
void move(Snake_container& body, wchar_t* buf);
void genFood(wchar_t* buf);
void clearOnly(wchar_t* buf);

int main(void) {    

    DWORD dwbyteswritten = 0;

    HANDLE stdH = GetStdHandle(STD_OUTPUT_HANDLE);  
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    GetConsoleScreenBufferInfo(stdH, &csbi);

    nScreenWidth = csbi.dwSize.X;
    nScreenHeight = csbi.dwSize.Y;

    wchar_t* temp = new wchar_t[nScreenWidth * nScreenHeight];
    clear(temp);

    bool bPlay = false;
    while (true) {
        int choice;
        std::wcout << L"1. Play" << std::endl;
        std::wcout << L"2. Quit" << std::endl;
        std::cin >> choice;

        if (choice == 1) {
            bIsHit = false;
            bPlay = true;
            break;
        }

        else if (choice == 2) {
            return 0;
        }

        else {
            std::wcout << L"Invalid input!";
            WriteConsoleOutputCharacter(stdH, temp, nScreenHeight * nScreenWidth, { 0, 0 }, &dwbyteswritten);
        }
    }

    const HANDLE hConsole = CreateConsoleScreenBuffer(
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        CONSOLE_TEXTMODE_BUFFER,
        NULL
    );

    // Sets up the snake body
    Snake_container body;
    Snake_segment head;
    head.posx = nFieldWidth / 2; head.posy = nFieldHeight / 2;
    body.push_back(head);
    Snake_segment tail = head;
    --tail.posx;
    body.push_back(tail);   

    // Builds the game buffer and clears it
    wchar_t* buffer = new wchar_t[nScreenWidth * nScreenHeight];
    SetConsoleActiveScreenBuffer(hConsole);
    clear(buffer);

    // Generates food and draws game
    update(hConsole, body, buffer);
    genFood(buffer);


    // Main game loop
    while (!bIsHit) {
        if (_kbhit())
            directionCheck(_getch());
        move(body, buffer);
        update(hConsole, body, buffer);
        clear(buffer);

        Sleep(200);
    }

    CloseHandle(hConsole);


    if (bPlay) {
        WriteConsoleOutputCharacter(stdH, temp, nScreenHeight * nScreenWidth, { 0, 0 }, &dwbyteswritten);
        std::wcout << L"Game over!" << std::endl;
        std::wcout << L"Score: " << score << std::endl;
        Sleep(1000);
    }

    CloseHandle(stdH);

    return 0;
}

void update(HANDLE hConsole, Snake_container& body, wchar_t* buf) {

    DWORD dwBytesWritten = 0;

    // Draws the screen
    for (int i = 0; i < nFieldHeight; ++i) {
        for (int j = 0; j < nFieldWidth; ++j) {

            // Draws top and bottom walls
            if (i == 0 || i == nFieldHeight - 1) buf[i * nScreenWidth + j] = L'#';

            // Draws left and right walls
            else if (j == 0 || j == nFieldWidth - 1) buf[i * nScreenWidth + j] = L'#';

            // Draws free space
            else if (buf[i * nScreenWidth + j] != L'*') buf[i * nScreenWidth + j] = L' ';

            // Prints snake
            for (int k = 0, n = body.size(); k < n; ++k) {              

                // Prints snake

                if (buf[body[0].posx + body[0].posy * nScreenWidth] == L'#') bIsHit = true;

                else if (buf[body[0].posx + body[0].posy * nScreenWidth] == L'o') bIsHit = true;

                else if (body[k].posx == j && body[k].posy == i)
                    if (k)
                        buf[i * nScreenWidth + j] = L'o';
                    else buf[i * nScreenWidth + j] = L'@';
            }
        }
    }

    for (int i = 0; i < 37; ++i)
        buf[nFieldHeight * nScreenWidth + i] = L"Use 'w, a, s, d' to change directions"[i];

    WriteConsoleOutputCharacter(hConsole, buf, nScreenWidth * nScreenHeight, { 0, 0 }, &dwBytesWritten);
}

// Clears the buffer
void clear(wchar_t* buf) {
    for (int i = 0; i < nScreenHeight; ++i) {
        for (int j = 0; j < nScreenWidth; ++j)
            if(buf[i * nScreenWidth + j] != L'*')
                buf[i * nScreenWidth + j] = L' ';
    }
}

// Changes the directions according to the value
void directionCheck(char value) {
    switch (value) {
    case 'a':
        if (dir != direction::RIGHT) dir = direction::LEFT;
        break;

    case 'w':
        if (dir != direction::DOWN) dir = direction::UP;
        break;

    case 'd':
        if (dir != direction::LEFT) dir = direction::RIGHT;
        break;

    case 's':
        if (dir != direction::UP) dir = direction::DOWN;
    }
}

// Moves the snake appropriately
void move(Snake_container& body, wchar_t* buf) {

    body[0].prevXpos = body[0].posx;
    body[0].prevYpos = body[0].posy;

    switch (dir) {
    case direction::RIGHT:
        ++body[0].posx;
        break;

    case direction::DOWN:
        ++body[0].posy;
        break;

    case direction::LEFT:
        --body[0].posx;
        break;

    case direction::UP:
        --body[0].posy;
    }

    for (int i = 1, n = body.size(); i < n; ++i) {
        body[i].prevXpos = body[i].posx;
        body[i].prevYpos = body[i].posy;
        body[i].posx = body[i - 1].prevXpos;
        body[i].posy = body[i - 1].prevYpos;
    }

    if (buf[body[0].posx + body[0].posy * nScreenWidth] == L'*') {
        Snake_segment tail_thing;
        tail_thing.posx = body[body.size() - 1].prevXpos;
        tail_thing.posy = body[body.size() - 1].prevYpos;
        body.push_back(tail_thing);
        clearOnly(buf);
        genFood(buf);
        score += 100;
    }
}

// Generates the food 
void genFood(wchar_t* buf) {
    int fX;    int fY;

    do {
        time_t tim = time(NULL);
        srand(tim + rand());
        fX = rand() % (nFieldWidth - 2) + 1;
        fY = rand() % (nFieldHeight - 2) + 1;
    } while (buf[fX + fY * nScreenWidth] != L' ');

    buf[fX + fY * nScreenWidth] = L'*';
}

// Only clears * characters
void clearOnly(wchar_t* buf) {
    for (int i = 0; i < nScreenHeight; ++i) {
        for (int j = 0; j < nScreenWidth; ++j)
            if (buf[i * nScreenWidth + j] == L'*')
                buf[i * nScreenWidth + j] = L' ';
    }
}

for informationFile "Snake_segment.h" looks like this:

My first c++ game (snake console game)

I finally finished the code for a snake game i was working on. I would like it if you were to give me some advice as to things that can be improved.

#ifndef UNICODE
#define UNICODE
#endif

#include <iostream>
#include <Windows.h>
#include <conio.h>
#include <ctime>
#include <random>
#include <queue>
#include "Snake_segment.h"

typedef std::deque<Snake_segment> Snake_container;

const enum direction {
    UP = 0,
    RIGHT,
    DOWN,
    LEFT 
};

// Constant variables
int nScreenWidth;
int nScreenHeight;
const int nFieldWidth = 40;
const int nFieldHeight = 15;

int score = 0;
bool bIsHit = true;
direction dir = direction::RIGHT;

void clear(wchar_t* buf);
void update(HANDLE hConsole, Snake_container& body, wchar_t* buf);
void directionCheck(char value);
void move(Snake_container& body, wchar_t* buf);
void genFood(wchar_t* buf);
void clearOnly(wchar_t* buf);

int main(void) {    

    DWORD dwbyteswritten = 0;

    HANDLE stdH = GetStdHandle(STD_OUTPUT_HANDLE);  
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    GetConsoleScreenBufferInfo(stdH, &csbi);

    nScreenWidth = csbi.dwSize.X;
    nScreenHeight = csbi.dwSize.Y;

    wchar_t* temp = new wchar_t[nScreenWidth * nScreenHeight];
    clear(temp);

    bool bPlay = false;
    while (true) {
        int choice;
        std::wcout << L"1. Play" << std::endl;
        std::wcout << L"2. Quit" << std::endl;
        std::cin >> choice;

        if (choice == 1) {
            bIsHit = false;
            bPlay = true;
            break;
        }

        else if (choice == 2) {
            return 0;
        }

        else {
            std::wcout << L"Invalid input!";
            WriteConsoleOutputCharacter(stdH, temp, nScreenHeight * nScreenWidth, { 0, 0 }, &dwbyteswritten);
        }
    }

    const HANDLE hConsole = CreateConsoleScreenBuffer(
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        CONSOLE_TEXTMODE_BUFFER,
        NULL
    );

    // Sets up the snake body
    Snake_container body;
    Snake_segment head;
    head.posx = nFieldWidth / 2; head.posy = nFieldHeight / 2;
    body.push_back(head);
    Snake_segment tail = head;
    --tail.posx;
    body.push_back(tail);   

    // Builds the game buffer and clears it
    wchar_t* buffer = new wchar_t[nScreenWidth * nScreenHeight];
    SetConsoleActiveScreenBuffer(hConsole);
    clear(buffer);

    // Generates food and draws game
    update(hConsole, body, buffer);
    genFood(buffer);


    // Main game loop
    while (!bIsHit) {
        if (_kbhit())
            directionCheck(_getch());
        move(body, buffer);
        update(hConsole, body, buffer);
        clear(buffer);

        Sleep(200);
    }

    CloseHandle(hConsole);


    if (bPlay) {
        WriteConsoleOutputCharacter(stdH, temp, nScreenHeight * nScreenWidth, { 0, 0 }, &dwbyteswritten);
        std::wcout << L"Game over!" << std::endl;
        std::wcout << L"Score: " << score << std::endl;
        Sleep(1000);
    }

    CloseHandle(stdH);

    return 0;
}

void update(HANDLE hConsole, Snake_container& body, wchar_t* buf) {

    DWORD dwBytesWritten = 0;

    // Draws the screen
    for (int i = 0; i < nFieldHeight; ++i) {
        for (int j = 0; j < nFieldWidth; ++j) {

            // Draws top and bottom walls
            if (i == 0 || i == nFieldHeight - 1) buf[i * nScreenWidth + j] = L'#';

            // Draws left and right walls
            else if (j == 0 || j == nFieldWidth - 1) buf[i * nScreenWidth + j] = L'#';

            // Draws free space
            else if (buf[i * nScreenWidth + j] != L'*') buf[i * nScreenWidth + j] = L' ';

            // Prints snake
            for (int k = 0, n = body.size(); k < n; ++k) {              

                // Prints snake

                if (buf[body[0].posx + body[0].posy * nScreenWidth] == L'#') bIsHit = true;

                else if (buf[body[0].posx + body[0].posy * nScreenWidth] == L'o') bIsHit = true;

                else if (body[k].posx == j && body[k].posy == i)
                    if (k)
                        buf[i * nScreenWidth + j] = L'o';
                    else buf[i * nScreenWidth + j] = L'@';
            }
        }
    }

    for (int i = 0; i < 37; ++i)
        buf[nFieldHeight * nScreenWidth + i] = L"Use 'w, a, s, d' to change directions"[i];

    WriteConsoleOutputCharacter(hConsole, buf, nScreenWidth * nScreenHeight, { 0, 0 }, &dwBytesWritten);
}

// Clears the buffer
void clear(wchar_t* buf) {
    for (int i = 0; i < nScreenHeight; ++i) {
        for (int j = 0; j < nScreenWidth; ++j)
            if(buf[i * nScreenWidth + j] != L'*')
                buf[i * nScreenWidth + j] = L' ';
    }
}

// Changes the directions according to the value
void directionCheck(char value) {
    switch (value) {
    case 'a':
        if (dir != direction::RIGHT) dir = direction::LEFT;
        break;

    case 'w':
        if (dir != direction::DOWN) dir = direction::UP;
        break;

    case 'd':
        if (dir != direction::LEFT) dir = direction::RIGHT;
        break;

    case 's':
        if (dir != direction::UP) dir = direction::DOWN;
    }
}

// Moves the snake appropriately
void move(Snake_container& body, wchar_t* buf) {

    body[0].prevXpos = body[0].posx;
    body[0].prevYpos = body[0].posy;

    switch (dir) {
    case direction::RIGHT:
        ++body[0].posx;
        break;

    case direction::DOWN:
        ++body[0].posy;
        break;

    case direction::LEFT:
        --body[0].posx;
        break;

    case direction::UP:
        --body[0].posy;
    }

    for (int i = 1, n = body.size(); i < n; ++i) {
        body[i].prevXpos = body[i].posx;
        body[i].prevYpos = body[i].posy;
        body[i].posx = body[i - 1].prevXpos;
        body[i].posy = body[i - 1].prevYpos;
    }

    if (buf[body[0].posx + body[0].posy * nScreenWidth] == L'*') {
        Snake_segment tail_thing;
        tail_thing.posx = body[body.size() - 1].prevXpos;
        tail_thing.posy = body[body.size() - 1].prevYpos;
        body.push_back(tail_thing);
        clearOnly(buf);
        genFood(buf);
        score += 100;
    }
}

// Generates the food 
void genFood(wchar_t* buf) {
    int fX; int fY;

    do {
        time_t tim = time(NULL);
        srand(tim + rand());
        fX = rand() % (nFieldWidth - 2) + 1;
        fY = rand() % (nFieldHeight - 2) + 1;
    } while (buf[fX + fY * nScreenWidth] != L' ');

    buf[fX + fY * nScreenWidth] = L'*';
}

// Only clears * characters
void clearOnly(wchar_t* buf) {
    for (int i = 0; i < nScreenHeight; ++i) {
        for (int j = 0; j < nScreenWidth; ++j)
            if (buf[i * nScreenWidth + j] == L'*')
                buf[i * nScreenWidth + j] = L' ';
    }
}

for information "Snake_segment.h" looks like this:

My first C++ game (snake console game)

I finally finished the code for a snake game I was working on. I would like it if you were to give me some advice as to things that can be improved.

#ifndef UNICODE
#define UNICODE
#endif

#include <iostream>
#include <Windows.h>
#include <conio.h>
#include <ctime>
#include <random>
#include <queue>
#include "Snake_segment.h"

typedef std::deque<Snake_segment> Snake_container;

const enum direction {
    UP = 0,
    RIGHT,
    DOWN,
    LEFT
};

// Constant variables
int nScreenWidth;
int nScreenHeight;
const int nFieldWidth = 40;
const int nFieldHeight = 15;

int score = 0;
bool bIsHit = true;
direction dir = direction::RIGHT;

void clear(wchar_t* buf);
void update(HANDLE hConsole, Snake_container& body, wchar_t* buf);
void directionCheck(char value);
void move(Snake_container& body, wchar_t* buf);
void genFood(wchar_t* buf);
void clearOnly(wchar_t* buf);

int main(void) {

    DWORD dwbyteswritten = 0;

    HANDLE stdH = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    GetConsoleScreenBufferInfo(stdH, &csbi);

    nScreenWidth = csbi.dwSize.X;
    nScreenHeight = csbi.dwSize.Y;

    wchar_t* temp = new wchar_t[nScreenWidth * nScreenHeight];
    clear(temp);

    bool bPlay = false;
    while (true) {
        int choice;
        std::wcout << L"1. Play" << std::endl;
        std::wcout << L"2. Quit" << std::endl;
        std::cin >> choice;

        if (choice == 1) {
            bIsHit = false;
            bPlay = true;
            break;
        }

        else if (choice == 2) {
            return 0;
        }

        else {
            std::wcout << L"Invalid input!";
            WriteConsoleOutputCharacter(stdH, temp, nScreenHeight * nScreenWidth, { 0, 0 }, &dwbyteswritten);
        }
    }

    const HANDLE hConsole = CreateConsoleScreenBuffer(
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        CONSOLE_TEXTMODE_BUFFER,
        NULL
    );

    // Sets up the snake body
    Snake_container body;
    Snake_segment head;
    head.posx = nFieldWidth / 2; head.posy = nFieldHeight / 2;
    body.push_back(head);
    Snake_segment tail = head;
    --tail.posx;
    body.push_back(tail);

    // Builds the game buffer and clears it
    wchar_t* buffer = new wchar_t[nScreenWidth * nScreenHeight];
    SetConsoleActiveScreenBuffer(hConsole);
    clear(buffer);

    // Generates food and draws game
    update(hConsole, body, buffer);
    genFood(buffer);


    // Main game loop
    while (!bIsHit) {
        if (_kbhit())
            directionCheck(_getch());
        move(body, buffer);
        update(hConsole, body, buffer);
        clear(buffer);

        Sleep(200);
    }

    CloseHandle(hConsole);


    if (bPlay) {
        WriteConsoleOutputCharacter(stdH, temp, nScreenHeight * nScreenWidth, { 0, 0 }, &dwbyteswritten);
        std::wcout << L"Game over!" << std::endl;
        std::wcout << L"Score: " << score << std::endl;
        Sleep(1000);
    }

    CloseHandle(stdH);

    return 0;
}

void update(HANDLE hConsole, Snake_container& body, wchar_t* buf) {

    DWORD dwBytesWritten = 0;

    // Draws the screen
    for (int i = 0; i < nFieldHeight; ++i) {
        for (int j = 0; j < nFieldWidth; ++j) {

            // Draws top and bottom walls
            if (i == 0 || i == nFieldHeight - 1) buf[i * nScreenWidth + j] = L'#';

            // Draws left and right walls
            else if (j == 0 || j == nFieldWidth - 1) buf[i * nScreenWidth + j] = L'#';

            // Draws free space
            else if (buf[i * nScreenWidth + j] != L'*') buf[i * nScreenWidth + j] = L' ';

            // Prints snake
            for (int k = 0, n = body.size(); k < n; ++k) {

                // Prints snake

                if (buf[body[0].posx + body[0].posy * nScreenWidth] == L'#') bIsHit = true;

                else if (buf[body[0].posx + body[0].posy * nScreenWidth] == L'o') bIsHit = true;

                else if (body[k].posx == j && body[k].posy == i)
                    if (k)
                        buf[i * nScreenWidth + j] = L'o';
                    else buf[i * nScreenWidth + j] = L'@';
            }
        }
    }

    for (int i = 0; i < 37; ++i)
        buf[nFieldHeight * nScreenWidth + i] = L"Use 'w, a, s, d' to change directions"[i];

    WriteConsoleOutputCharacter(hConsole, buf, nScreenWidth * nScreenHeight, { 0, 0 }, &dwBytesWritten);
}

// Clears the buffer
void clear(wchar_t* buf) {
    for (int i = 0; i < nScreenHeight; ++i) {
        for (int j = 0; j < nScreenWidth; ++j)
            if(buf[i * nScreenWidth + j] != L'*')
                buf[i * nScreenWidth + j] = L' ';
    }
}

// Changes the directions according to the value
void directionCheck(char value) {
    switch (value) {
    case 'a':
        if (dir != direction::RIGHT) dir = direction::LEFT;
        break;

    case 'w':
        if (dir != direction::DOWN) dir = direction::UP;
        break;

    case 'd':
        if (dir != direction::LEFT) dir = direction::RIGHT;
        break;

    case 's':
        if (dir != direction::UP) dir = direction::DOWN;
    }
}

// Moves the snake appropriately
void move(Snake_container& body, wchar_t* buf) {

    body[0].prevXpos = body[0].posx;
    body[0].prevYpos = body[0].posy;

    switch (dir) {
    case direction::RIGHT:
        ++body[0].posx;
        break;

    case direction::DOWN:
        ++body[0].posy;
        break;

    case direction::LEFT:
        --body[0].posx;
        break;

    case direction::UP:
        --body[0].posy;
    }

    for (int i = 1, n = body.size(); i < n; ++i) {
        body[i].prevXpos = body[i].posx;
        body[i].prevYpos = body[i].posy;
        body[i].posx = body[i - 1].prevXpos;
        body[i].posy = body[i - 1].prevYpos;
    }

    if (buf[body[0].posx + body[0].posy * nScreenWidth] == L'*') {
        Snake_segment tail_thing;
        tail_thing.posx = body[body.size() - 1].prevXpos;
        tail_thing.posy = body[body.size() - 1].prevYpos;
        body.push_back(tail_thing);
        clearOnly(buf);
        genFood(buf);
        score += 100;
    }
}

// Generates the food
void genFood(wchar_t* buf) {
    int fX;    int fY;

    do {
        time_t tim = time(NULL);
        srand(tim + rand());
        fX = rand() % (nFieldWidth - 2) + 1;
        fY = rand() % (nFieldHeight - 2) + 1;
    } while (buf[fX + fY * nScreenWidth] != L' ');

    buf[fX + fY * nScreenWidth] = L'*';
}

// Only clears * characters
void clearOnly(wchar_t* buf) {
    for (int i = 0; i < nScreenHeight; ++i) {
        for (int j = 0; j < nScreenWidth; ++j)
            if (buf[i * nScreenWidth + j] == L'*')
                buf[i * nScreenWidth + j] = L' ';
    }
}

File "Snake_segment.h" looks like this:

    Tweeted twitter.com/StackCodeReview/status/1124418554282094592
    Became Hot Network Question
2 edited tags
| link
1
source | link

My first c++ game (snake console game)

I finally finished the code for a snake game i was working on. I would like it if you were to give me some advice as to things that can be improved.

#ifndef UNICODE
#define UNICODE
#endif

#include <iostream>
#include <Windows.h>
#include <conio.h>
#include <ctime>
#include <random>
#include <queue>
#include "Snake_segment.h"

typedef std::deque<Snake_segment> Snake_container;

const enum direction {
    UP = 0,
    RIGHT,
    DOWN,
    LEFT 
};

// Constant variables
int nScreenWidth;
int nScreenHeight;
const int nFieldWidth = 40;
const int nFieldHeight = 15;

int score = 0;
bool bIsHit = true;
direction dir = direction::RIGHT;

void clear(wchar_t* buf);
void update(HANDLE hConsole, Snake_container& body, wchar_t* buf);
void directionCheck(char value);
void move(Snake_container& body, wchar_t* buf);
void genFood(wchar_t* buf);
void clearOnly(wchar_t* buf);

int main(void) {    

    DWORD dwbyteswritten = 0;

    HANDLE stdH = GetStdHandle(STD_OUTPUT_HANDLE);  
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    GetConsoleScreenBufferInfo(stdH, &csbi);

    nScreenWidth = csbi.dwSize.X;
    nScreenHeight = csbi.dwSize.Y;

    wchar_t* temp = new wchar_t[nScreenWidth * nScreenHeight];
    clear(temp);

    bool bPlay = false;
    while (true) {
        int choice;
        std::wcout << L"1. Play" << std::endl;
        std::wcout << L"2. Quit" << std::endl;
        std::cin >> choice;

        if (choice == 1) {
            bIsHit = false;
            bPlay = true;
            break;
        }

        else if (choice == 2) {
            return 0;
        }

        else {
            std::wcout << L"Invalid input!";
            WriteConsoleOutputCharacter(stdH, temp, nScreenHeight * nScreenWidth, { 0, 0 }, &dwbyteswritten);
        }
    }

    const HANDLE hConsole = CreateConsoleScreenBuffer(
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        CONSOLE_TEXTMODE_BUFFER,
        NULL
    );

    // Sets up the snake body
    Snake_container body;
    Snake_segment head;
    head.posx = nFieldWidth / 2; head.posy = nFieldHeight / 2;
    body.push_back(head);
    Snake_segment tail = head;
    --tail.posx;
    body.push_back(tail);   

    // Builds the game buffer and clears it
    wchar_t* buffer = new wchar_t[nScreenWidth * nScreenHeight];
    SetConsoleActiveScreenBuffer(hConsole);
    clear(buffer);

    // Generates food and draws game
    update(hConsole, body, buffer);
    genFood(buffer);


    // Main game loop
    while (!bIsHit) {
        if (_kbhit())
            directionCheck(_getch());
        move(body, buffer);
        update(hConsole, body, buffer);
        clear(buffer);

        Sleep(200);
    }

    CloseHandle(hConsole);


    if (bPlay) {
        WriteConsoleOutputCharacter(stdH, temp, nScreenHeight * nScreenWidth, { 0, 0 }, &dwbyteswritten);
        std::wcout << L"Game over!" << std::endl;
        std::wcout << L"Score: " << score << std::endl;
        Sleep(1000);
    }

    CloseHandle(stdH);

    return 0;
}

void update(HANDLE hConsole, Snake_container& body, wchar_t* buf) {

    DWORD dwBytesWritten = 0;

    // Draws the screen
    for (int i = 0; i < nFieldHeight; ++i) {
        for (int j = 0; j < nFieldWidth; ++j) {

            // Draws top and bottom walls
            if (i == 0 || i == nFieldHeight - 1) buf[i * nScreenWidth + j] = L'#';

            // Draws left and right walls
            else if (j == 0 || j == nFieldWidth - 1) buf[i * nScreenWidth + j] = L'#';

            // Draws free space
            else if (buf[i * nScreenWidth + j] != L'*') buf[i * nScreenWidth + j] = L' ';

            // Prints snake
            for (int k = 0, n = body.size(); k < n; ++k) {              

                // Prints snake

                if (buf[body[0].posx + body[0].posy * nScreenWidth] == L'#') bIsHit = true;

                else if (buf[body[0].posx + body[0].posy * nScreenWidth] == L'o') bIsHit = true;

                else if (body[k].posx == j && body[k].posy == i)
                    if (k)
                        buf[i * nScreenWidth + j] = L'o';
                    else buf[i * nScreenWidth + j] = L'@';
            }
        }
    }

    for (int i = 0; i < 37; ++i)
        buf[nFieldHeight * nScreenWidth + i] = L"Use 'w, a, s, d' to change directions"[i];

    WriteConsoleOutputCharacter(hConsole, buf, nScreenWidth * nScreenHeight, { 0, 0 }, &dwBytesWritten);
}

// Clears the buffer
void clear(wchar_t* buf) {
    for (int i = 0; i < nScreenHeight; ++i) {
        for (int j = 0; j < nScreenWidth; ++j)
            if(buf[i * nScreenWidth + j] != L'*')
                buf[i * nScreenWidth + j] = L' ';
    }
}

// Changes the directions according to the value
void directionCheck(char value) {
    switch (value) {
    case 'a':
        if (dir != direction::RIGHT) dir = direction::LEFT;
        break;

    case 'w':
        if (dir != direction::DOWN) dir = direction::UP;
        break;

    case 'd':
        if (dir != direction::LEFT) dir = direction::RIGHT;
        break;

    case 's':
        if (dir != direction::UP) dir = direction::DOWN;
    }
}

// Moves the snake appropriately
void move(Snake_container& body, wchar_t* buf) {

    body[0].prevXpos = body[0].posx;
    body[0].prevYpos = body[0].posy;

    switch (dir) {
    case direction::RIGHT:
        ++body[0].posx;
        break;

    case direction::DOWN:
        ++body[0].posy;
        break;

    case direction::LEFT:
        --body[0].posx;
        break;

    case direction::UP:
        --body[0].posy;
    }

    for (int i = 1, n = body.size(); i < n; ++i) {
        body[i].prevXpos = body[i].posx;
        body[i].prevYpos = body[i].posy;
        body[i].posx = body[i - 1].prevXpos;
        body[i].posy = body[i - 1].prevYpos;
    }

    if (buf[body[0].posx + body[0].posy * nScreenWidth] == L'*') {
        Snake_segment tail_thing;
        tail_thing.posx = body[body.size() - 1].prevXpos;
        tail_thing.posy = body[body.size() - 1].prevYpos;
        body.push_back(tail_thing);
        clearOnly(buf);
        genFood(buf);
        score += 100;
    }
}

// Generates the food 
void genFood(wchar_t* buf) {
    int fX; int fY;

    do {
        time_t tim = time(NULL);
        srand(tim + rand());
        fX = rand() % (nFieldWidth - 2) + 1;
        fY = rand() % (nFieldHeight - 2) + 1;
    } while (buf[fX + fY * nScreenWidth] != L' ');

    buf[fX + fY * nScreenWidth] = L'*';
}

// Only clears * characters
void clearOnly(wchar_t* buf) {
    for (int i = 0; i < nScreenHeight; ++i) {
        for (int j = 0; j < nScreenWidth; ++j)
            if (buf[i * nScreenWidth + j] == L'*')
                buf[i * nScreenWidth + j] = L' ';
    }
}

for information "Snake_segment.h" looks like this:

class Snake_segment {
public:
    int posx, posy, prevXpos, prevYpos;
};