How to build your first Snake Game in C++?

Creating animation with Screen Refreshes.

Sagnik Mitra
6 min readJun 12, 2020

Yes, there are many videos and Programmes to build a Snake Game but what is rare to find is something that doesn’t need any graphics-intensive coding. I made this earlier this year and though there is a minor flickering issue, it works fine.

Let’s clear the dependencies first. You need a good IDE to get good results from the Screen Refresh. I tried with VSCode & Atom and for both of them it worked fine but with Codeblcoks, in my machine, I saw some unusual breaks in the program. I wrote the program in C++ but will soon convert it to Python. I consider C++ because it is easier to understand for this type of program. So, let’s start with the coding part.

Importing Libraries & Using Namespace:

I used iostream for regular input-output functions. windows.h for Setup(), Draw(), Logic() functions and conio.h is necessarily used for _kbhit() , _getch() functions.

#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;

Defining Arrow Keys

You can easily play this game with A-W-S-D keys but for flexibility of playing, I embedded the ability to access arrow keys too. And I used their Conventional Name & ASCII Value to define those.

#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77

Declaring Variables

I have taken a boolean variable ‘gameOver’ to determine in the game whether you have crashed with your body and the game has ended or not, height and width, snakehead position ( x for x-axis & y for the y-axis), fruit/foodPosition (Both the axis), score, tail position (Both the axis) and the length of the snake (nTail) and an enum variable for the directions & stop.

bool gameOver;
const int width = 40;
const int height = 20;
int x, y, fruitPosX, fruitPosY, score;
int tailX[100], tailY[100];
int nTail;
enum eDirecton {
STOP = 0,LEFT,RIGHT,UP,DOWN
};
eDirecton dir;

Setup Function

Here, you need to initialize the gameOver to False, dir to Stop, and though you can generate the snake anywhere. But here I have generated it in the middle. And after generating the snake, we now need to generate the food at any random point but within the height and width.

void Setup(){
gameOver = false;
dir = STOP;
x = width / 2;
y = height / 2;
//random food position in boundary
fruitPosX = rand() % width;
fruitPosY = rand() % height;
score = 0;
}

Draw Function

Here I just build up the Wall Boundary. And the concept is pretty easy. Whenever you match with the [0] or [Wall’s Height/Width -1], you draw the wall. I have used the Characters from the hex table.

void Draw() {//screen clear for every instance to transform into animation.
system("cls");
//As I used windows to code it, i used "cls", if you are using debian or fedora, change it to: system("clear")//building the wall boundary & snake
for (int i = 0; i < width + 2; i++)
cout << "\xB2";
cout << endl;
for (int i = 0; i < height; i++){
for (int j = 0; j < width; j++){
//wall boundary building - leftmost wall
if (j == 0)
cout << "\xB2";
//wall boundary building - top & bottom wall
if (i == y && j == x)
cout << "\xDB";
/*generating the food (\xB2) in then boundary in a random place which is previously randomized by the the setup() function*/
else if (i == fruitPosY && j == fruitPosX)
cout << "\xB2";
else {
bool print = false;
for (int k = 0; k < nTail; k++) {
if (tailX[k] == j && tailY[k] == i){
cout << "\xB1";
print = true;
}
}
if (!print)
cout << " "
//wall boundary building - rightmost wall
if (j == width - 1)
cout << "\xB2";
}
}
cout << endl;
}
for (int i = 0; i < width + 2; i++)
cout << "\xB2";
cout << endl;
cout << "Made by Sagnik Mitra\nLinkedIn: https://www.linkedin.com/in/sagnik-mitra-36742b178/ \nScore:" << score << endl;
}
After drawing your setup should look like this.

Input Function

In the input function, you just need to use a nested-if loop and when the _kbhit() function occurs, you just need to maintain the switch cases ( w/up_arrow, a/left_arrow, s/down_arrow, d/right_arrow ) and charge the direction respectively.

void Input(){
if (_kbhit()){
switch (_getch()){
//a or left_arrow to go into left direction.
case 'a':
dir = LEFT;
break;
case KEY_LEFT:
dir = LEFT;
break;
//d or right_arrow to go into right direction.
case 'd':
dir = RIGHT;
break;
case KEY_RIGHT:
dir = RIGHT;
break;
//w or up_arrow to go into up direction.
case 'w':
dir = UP;
break;
case KEY_UP:
dir = UP;
break;
//s or down_arrow to go into down direction.
case 's':
dir = DOWN;
break;
case KEY_DOWN:
dir = DOWN;
break;
//x for force quit.
case 'x':
gameOver = true;
break;
}
}
}

Logic Function

In the Logic Function, we first initialized the Tail. And after that, we switched the position of the snake’s body with its previous position. And after that, you simply need to implement the body-movement according to the Keyboard Hit.

Next, as this follows the concept of an open maze, so when it disappears at one side, it appears from the other side, so you need to keep in mind that once it touches the right wall it appears from the left wall and vice-versa and same follows for the up & down walls.

Next, the head touches the body, the game crashes.

For the scoring system, you can simply add 5 / 10 or whatever points you want when the head touches the food (their position becomes the same). And every touch increases the score.

void Logic(){
//initializing the tail before going to the position replacement.
int prevX = tailX[0];
int prevY = tailY[0];
int prev2X, prev2Y;
tailX[0] = x;
tailY[0] = y;
for (int i = 1; i < nTail; i++){
//the snakes moves in the direction by replacing it's previous index when the screen refreshes.
//the following is the switch.
prev2X = tailX[i];
prev2Y = tailY[i];
tailX[i] = prevX;
tailY[i] = prevY;
prevX = prev2X;
prevY = prev2Y;
}
//changing the snake's position (x & y axis) when allowed key_hit occurs
switch (dir){
case LEFT:
x--;
break;

case RIGHT:
x++;
break;
case UP:
y--;
break;
case DOWN:
y++;
break;
default:
break;
}

if (x >= width)
x = 0;
else if (x < 0)
x = width - 1;
if (y >= height)
y = 0;
else if (y < 0)
y = height - 1;
//crashes to body or presses the reverse direction when moving towards a particular direction and game ends.for (int i = 0; i < nTail; i++)
if (tailX[i] == x && tailY[i] == y)
gameOver = true;
//increasing the tail length when the snake eats the food (head_pos touches fruit_pos)if (x == fruitPosX && y == fruitPosY){
score += 10;
fruitPosX = rand() % width;
fruitPosY = rand() % height;
nTail++;
}
}

So, in this way you can easily build a snake game. You might use letters or numbers in the wall boundary and you can skip embedding the arrow keys in the system and that depends on you how you deal with it. It is a pretty interesting and logical program for beginners (so am I :) ) with arrays, enums, different types of variables, loops, decision checks, switch cases, system functions, and many more. I hope you liked it.

You can download my source code and run it in your systems. The minor drawbacks of this implementation are flickering issues and occasional crashing due to multidirectional input.

--

--

No responses yet